def load_form(self, name, dialog=None): '''Load a form from pmg_qt/forms/{name}.py''' import importlib if dialog is None: dialog = QtWidgets.QDialog(self) widget = dialog elif dialog == 'floating': widget = QtWidgets.QWidget(self) else: widget = dialog try: m = importlib.import_module('.forms.' + name, 'pmg_qt') except ImportError as e: if pymol.Qt.DEBUG: print('load_form import failed (%s)' % (e, )) uifile = os.path.join(os.path.dirname(__file__), 'forms', '%s.ui' % name) form = pymol.Qt.utils.loadUi(uifile, widget) else: if hasattr(m, 'Ui_Form'): form = m.Ui_Form() else: form = m.Ui_Dialog() form.setupUi(widget) if dialog == 'floating': dialog = QtWidgets.QDockWidget(widget.windowTitle(), self) dialog.setFloating(True) dialog.setWidget(widget) dialog.resize(widget.size()) form._dialog = dialog return form
def VolumePanelDocked(parent, *args, **kwargs): widget = QtWidgets.QWidget(parent) window = QtWidgets.QDockWidget(parent) _VolumePanel(widget, window, *args, **kwargs) window.setWidget(widget) parent.addDockWidget(Qt.BottomDockWidgetArea, window) # disabled: always use default style # window.topLevelChanged.connect(widget.editor.windowTopLevelChanged) return window
def toggle_ext_window_dockable(self, neverfloat=False): ''' Toggle whether the "external" GUI is dockable ''' dockWidget = self.ext_window if dockWidget.titleBarWidget() is None: tbw = QtWidgets.QWidget() else: tbw = None dockWidget.setFloating(tbw is None and not neverfloat) dockWidget.setTitleBarWidget(tbw) dockWidget.show()
def __init__(self, *args, **kwargs): super(PyMod_plot_window_qt, self).__init__(*args, **kwargs) # Central widget. self.central_widget = QtWidgets.QWidget() self.setCentralWidget(self.central_widget) self.central_widget_layout = QtWidgets.QGridLayout() self.central_widget.setLayout(self.central_widget_layout) #------------------------------------------------ # Upper frame (contains the plot and controls). - #------------------------------------------------ expanding_size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) preferred_size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) # The upper frame contains three frames: info, plot and controls frames. # The infor and controls frames will be displayed only if the 'use_controls' # argument is set to 'True' when calling the 'build_plotting_area' method. self.upper_frame = QtWidgets.QFrame() self.upper_frame.setStyleSheet("background-color: #646464") self.upper_frame_layout = QtWidgets.QGridLayout() self.upper_frame.setLayout(self.upper_frame_layout) self.upper_frame.setSizePolicy(expanding_size_policy) self.central_widget_layout.addWidget(self.upper_frame, 0, 0) # Info frame, it contains the messagebar of the plot. self.info_frame = QtWidgets.QFrame() self.info_frame_layout = QtWidgets.QHBoxLayout() self.info_frame.setLayout(self.info_frame_layout) self.info_frame.setSizePolicy(preferred_size_policy) self.info_label = QtWidgets.QLabel("") self.info_frame_layout.addWidget(self.info_label) # Plot frame. self.plot_frame = QtWidgets.QFrame() # self.plot_frame.setStyleSheet("background-color: red") self.plot_frame_layout = QtWidgets.QGridLayout() self.plot_frame.setLayout(self.plot_frame_layout) self.plot_frame.setSizePolicy(expanding_size_policy) self.build_plot_widget() # Controls frame. self.controls_frame = QtWidgets.QWidget() self.controls_frame.setStyleSheet("background-color: #747474") self.controls_frame_layout = QtWidgets.QGridLayout() self.controls_frame.setLayout(self.controls_frame_layout) self.controls_frame_layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.controls_scrollarea = QtWidgets.QScrollArea() self.controls_scrollarea.setWidgetResizable(True) self.controls_scrollarea.setWidget(self.controls_frame) self.labels_title = QtWidgets.QLabel("Plots list") # Middle splitter. self.middle_splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal) self.middle_splitter.setSizePolicy(expanding_size_policy) #--------------------------------------- # Lower frame (contains some options). - #--------------------------------------- self.lower_frame = QtWidgets.QFrame() self.lower_frame_layout = QtWidgets.QGridLayout() self.lower_frame.setLayout(self.lower_frame_layout) self.central_widget_layout.addWidget(self.lower_frame, 1, 0) # View buttons. self.view_label = QtWidgets.QLabel("View:") self.lower_frame_layout.addWidget(self.view_label, 0, 0) self.home_view_button = QtWidgets.QPushButton("Fit to data") self.home_view_button.clicked.connect(self.on_home_button_click) self.lower_frame_layout.addWidget(self.home_view_button, 0, 1) # On click behaviour. The buttons will be shown later, in the # 'build_plotting_area' metohd. self.interact_buttons_group = QtWidgets.QButtonGroup() self.on_click_label = QtWidgets.QLabel("Interact on click:") self.interact_button = QtWidgets.QPushButton("Yes") self.interact_button.setCheckable(True) self.interact_buttons_group.addButton(self.interact_button) self.interact_button.clicked.connect(self.on_interact_button_click) self.no_interaction_button = QtWidgets.QPushButton("No") self.no_interaction_button.setCheckable(True) self.no_interaction_button.setChecked(True) self.interact_buttons_group.addButton(self.no_interaction_button) self.no_interaction_button.clicked.connect(self.on_no_interaction_button_click) # Show/hide all buttons. They will be shown later, in the 'build_plotting_area' # method. self.show_label = QtWidgets.QLabel("Show:") self.show_all_button = QtWidgets.QPushButton("All") self.show_all_button.clicked.connect(self.show_all_command) self.hide_all_button = QtWidgets.QPushButton("None") self.hide_all_button.clicked.connect(self.hide_all_command) self.lower_frame_layout.setAlignment(QtCore.Qt.AlignLeft) #--------------------- # Build a main menu. - #--------------------- self.save_to_csv_action = QtWidgets.QAction('Save to CSV', self) self.save_to_csv_action.triggered.connect(lambda a=None: self.save_to_csv_event()) self.save_to_png_action = QtWidgets.QAction('Save to PNG', self) self.save_to_png_action.triggered.connect(lambda a=None: self.save_to_png_event()) self.main_menubar = self.menuBar() self.file_menu = self.main_menubar.addMenu('File')
def __init__(self): # noqa QtWidgets.QMainWindow.__init__(self) self.setDockOptions(QtWidgets.QMainWindow.AllowTabbedDocks | QtWidgets.QMainWindow.AllowNestedDocks) # resize Window before it is shown options = pymol.invocation.options self.resize(options.win_x + (220 if options.internal_gui else 0), options.win_y + (246 if options.external_gui else 18)) # for thread-safe viewport command self.viewportsignal.connect(self.pymolviewport) # reusable dialogs self.dialog_png = None self.advanced_settings_dialog = None self.props_dialog = None self.builder = None # setting index -> callable self.setting_callbacks = defaultdict(list) # "session_file" setting in window title self.setting_callbacks[440].append(lambda v: self.setWindowTitle( "PyMOL (" + os.path.basename(v) + ")")) # "External" Command Line and Loggin Widget self._setup_history() self.lineedit = CommandLineEdit() self.lineedit.setObjectName("command_line") self.browser = QtWidgets.QPlainTextEdit() self.browser.setObjectName("feedback_browser") self.browser.setReadOnly(True) # convenience: clicking into feedback browser gives focus to command # line. Drawback: Copying with CTRL+C doesn't work in feedback # browser -> clear focus proxy while text selected self.browser.setFocusProxy(self.lineedit) @self.browser.copyAvailable.connect def _(yes): self.browser.setFocusProxy(None if yes else self.lineedit) self.browser.setFocus() # Font self.browser.setFont(getMonospaceFont()) connectFontContextMenu(self.browser) lineeditlayout = QtWidgets.QHBoxLayout() command_label = QtWidgets.QLabel("PyMOL>") command_label.setObjectName("command_label") lineeditlayout.addWidget(command_label) lineeditlayout.addWidget(self.lineedit) self.lineedit.setToolTip('''Command Input Area Get the list of commands by hitting <TAB> Get the list of arguments for one command with a question mark: PyMOL> color ? Read the online help for a command with "help": PyMOL> help color Get autocompletion for many arguments by hitting <TAB> PyMOL> color ye<TAB> (will autocomplete "yellow") ''') layout = QtWidgets.QVBoxLayout() layout.addWidget(self.browser) layout.addLayout(lineeditlayout) quickbuttonslayout = QtWidgets.QVBoxLayout() quickbuttonslayout.setSpacing(2) extguilayout = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.LeftToRight) extguilayout.setContentsMargins(2, 2, 2, 2) extguilayout.addLayout(layout) extguilayout.addLayout(quickbuttonslayout) class ExtGuiFrame(QtWidgets.QFrame): def mouseDoubleClickEvent(_, event): self.toggle_ext_window_dockable(True) _size_hint = QtCore.QSize(options.win_x, options.ext_y) def sizeHint(self): return self._size_hint dockWidgetContents = ExtGuiFrame(self) dockWidgetContents.setLayout(extguilayout) dockWidgetContents.setObjectName("extgui") self.ext_window = \ dockWidget = QtWidgets.QDockWidget(self) dockWidget.setWindowTitle("External GUI") dockWidget.setWidget(dockWidgetContents) if options.external_gui: dockWidget.setTitleBarWidget(QtWidgets.QWidget()) else: dockWidget.hide() self.addDockWidget(Qt.TopDockWidgetArea, dockWidget) # rearrange vertically if docking left or right @dockWidget.dockLocationChanged.connect def _(area): if area == Qt.LeftDockWidgetArea or area == Qt.RightDockWidgetArea: extguilayout.setDirection(QtWidgets.QBoxLayout.BottomToTop) quickbuttonslayout.takeAt(quickbuttons_stretch_index) else: extguilayout.setDirection(QtWidgets.QBoxLayout.LeftToRight) if quickbuttons_stretch_index >= quickbuttonslayout.count(): quickbuttonslayout.addStretch() # OpenGL Widget self.pymolwidget = PyMOLGLWidget(self) self.setCentralWidget(self.pymolwidget) cmd = self.cmd = self.pymolwidget.cmd ''' # command completion completer = QtWidgets.QCompleter(cmd.kwhash.keywords, self) self.lineedit.setCompleter(completer) ''' # overload <Tab> action self.lineedit.installEventFilter(self) self.pymolwidget.installEventFilter(self) # Quick Buttons for row in [ [ ('Reset', cmd.reset), ('Zoom', lambda: cmd.zoom(animate=1.0)), ('Orient', lambda: cmd.orient(animate=1.0)), # render dialog will be constructed when the menu is shown # for the first time. This way it's populated with the current # viewport and settings. Also defers parsing of the ui file. ('Draw/Ray', WidgetMenu(self).setSetupUi(self.render_dialog)), ], [ ('Unpick', cmd.unpick), ('Deselect', cmd.deselect), ('Rock', cmd.rock), ('Get View', self.get_view), ], [ ('|<', cmd.rewind), ('<', cmd.backward), ('Stop', cmd.mstop), ('Play', cmd.mplay), ('>', cmd.forward), ('>|', cmd.ending), ('MClear', cmd.mclear), ], [ ('Builder', self.open_builder_panel), ('Properties', self.open_props_dialog), ('Rebuild', cmd.rebuild), ], ]: hbox = QtWidgets.QHBoxLayout() hbox.setSpacing(2) for name, callback in row: btn = QtWidgets.QPushButton(name) btn.setProperty("quickbutton", True) btn.setAttribute(Qt.WA_LayoutUsesWidgetRect) # OS X workaround hbox.addWidget(btn) if callback is None: btn.setEnabled(False) elif isinstance(callback, QtWidgets.QMenu): btn.setMenu(callback) else: btn.released.connect(callback) quickbuttonslayout.addLayout(hbox) # progress bar hbox = QtWidgets.QHBoxLayout() self.progressbar = QtWidgets.QProgressBar() self.progressbar.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) hbox.addWidget(self.progressbar) self.abortbutton = QtWidgets.QPushButton('Abort') self.abortbutton.setStyleSheet("background: #FF0000; color: #FFFFFF") self.abortbutton.released.connect(cmd.interrupt) hbox.addWidget(self.abortbutton) quickbuttonslayout.addLayout(hbox) quickbuttonslayout.addStretch() quickbuttons_stretch_index = quickbuttonslayout.count() - 1 # menu top level self.menubar = menubar = self.menuBar() # action groups actiongroups = {} def _addmenu(data, menu): '''Fill a menu from "data"''' menu.setTearOffEnabled(True) menu.setWindowTitle(menu.title()) # needed for Windows for item in data: if item[0] == 'separator': menu.addSeparator() elif item[0] == 'menu': _addmenu(item[2], menu.addMenu(item[1].replace('&', '&&'))) elif item[0] == 'command': command = item[2] if command is None: print('warning: skipping', item) else: if isinstance(command, str): command = lambda c=command: cmd.do(c) menu.addAction(item[1], command) elif item[0] == 'check': if len(item) > 4: menu.addAction( SettingAction(self, cmd, item[2], item[1], item[3], item[4])) else: menu.addAction( SettingAction(self, cmd, item[2], item[1])) elif item[0] == 'radio': label, name, value = item[1:4] try: group, type_, values = actiongroups[item[2]] except KeyError: group = QtWidgets.QActionGroup(self) type_, values = cmd.get_setting_tuple(name) actiongroups[item[2]] = group, type_, values action = QtWidgets.QAction(label, self) action.triggered.connect(lambda _=0, args=(name, value): cmd.set(*args, log=1, quiet=0)) self.setting_callbacks[cmd.setting._get_index( name)].append( lambda v, V=value, a=action: a.setChecked(v == V)) group.addAction(action) menu.addAction(action) action.setCheckable(True) if values[0] == value: action.setChecked(True) elif item[0] == 'open_recent_menu': self.open_recent_menu = menu.addMenu('Open Recent...') else: print('error:', item) # recent files menu self.open_recent_menu = None # for plugins self.menudict = {'': menubar} # menu for _, label, data in self.get_menudata(cmd): assert _ == 'menu' menu = menubar.addMenu(label) self.menudict[label] = menu _addmenu(data, menu) # hack for macOS to hide "Edit > Start Dictation" # https://bugreports.qt.io/browse/QTBUG-43217 if pymol.IS_MACOS: self.menudict['Edit'].setTitle('Edit_') QtCore.QTimer.singleShot( 10, lambda: self.menudict['Edit'].setTitle('Edit')) # recent files menu if self.open_recent_menu: @self.open_recent_menu.aboutToShow.connect def _(): self.open_recent_menu.clear() for fname in self.recent_filenames: self.open_recent_menu.addAction( fname if len(fname) < 128 else '...' + fname[-120:], lambda fname=fname: self.load_dialog(fname)) # some experimental window control menu = self.menudict['Display'].addSeparator() menu = self.menudict['Display'].addMenu('External GUI') menu.addAction('Toggle floating', self.toggle_ext_window_dockable, QtGui.QKeySequence('Ctrl+E')) ext_vis_action = self.ext_window.toggleViewAction() ext_vis_action.setText('Visible') menu.addAction(ext_vis_action) # extra key mappings (MacPyMOL compatible) QtWidgets.QShortcut(QtGui.QKeySequence('Ctrl+O'), self).activated.connect(self.file_open) QtWidgets.QShortcut(QtGui.QKeySequence('Ctrl+S'), self).activated.connect(self.session_save) # feedback self.feedback_timer = QtCore.QTimer() self.feedback_timer.setSingleShot(True) self.feedback_timer.timeout.connect(self.update_feedback) self.feedback_timer.start(100) # legacy plugin system self.menudict['Plugin'].addAction('Initialize Plugin System', self.initializePlugins) # focus in command line if options.external_gui: self.lineedit.setFocus() else: self.pymolwidget.setFocus() # Apply PyMOL stylesheet try: with open( cmd.exp_path('$PYMOL_DATA/pmg_qt/styles/pymol.sty')) as f: style = f.read() except IOError: print('Could not read PyMOL stylesheet.') print('DEBUG: PYMOL_DATA=' + repr(os.getenv('PYMOL_DATA'))) style = "" if style: self.setStyleSheet(style)
def initialize_plot(self, pymod, target_element, residues_tags, plot_title, aa_list): self.pymod = pymod self.target_element = target_element self.residues_tags = residues_tags self.plot_title = plot_title self.setWindowTitle("%s Ramachandran Plot" % self.target_element.my_header) self.aa_list = aa_list # Frame of the window containing a row for some control buttons, a row for # the plot and a row for a messagebar. self.plot_frame = QtWidgets.QWidget() self.plot_frame_layout = QtWidgets.QGridLayout() self.plot_frame.setLayout(self.plot_frame_layout) self.setCentralWidget(self.plot_frame) # Control frame. self.controls_frame = QtWidgets.QWidget() self.controls_frame_layout = QtWidgets.QGridLayout() self.controls_frame.setLayout(self.controls_frame_layout) self.plot_frame_layout.addWidget(self.controls_frame, 0, 0) self.scale_factor = 0 self.scale_down_button = QtWidgets.QPushButton("Zoom out") try: self.scale_down_button.setIcon(QtGui.QIcon.fromTheme("go-down")) except: pass self.scale_down_button.clicked.connect( lambda a=None: self.scale_plot_down()) self.controls_frame_layout.addWidget(self.scale_down_button, 0, 0) self.scale_up_button = QtWidgets.QPushButton("Zoom in") try: self.scale_up_button.setIcon(QtGui.QIcon.fromTheme("go-up")) except: pass self.scale_up_button.clicked.connect( lambda a=None: self.scale_plot_up()) self.controls_frame_layout.addWidget(self.scale_up_button, 0, 1) self.controls_frame_layout.setAlignment(QtCore.Qt.AlignLeft) # Frame containing the plot (with a scrollbar). self.canvas_plot_frame = QtWidgets.QWidget() self.canvas_plot_frame.setStyleSheet("background-color: white") self.canvas_plot_frame_layout = QtWidgets.QGridLayout() self.canvas_plot_frame.setLayout(self.canvas_plot_frame_layout) self.canvas_plot_scrollarea = QtWidgets.QScrollArea() self.canvas_plot_scrollarea.setWidgetResizable(True) self.canvas_plot_scrollarea.setWidget(self.canvas_plot_frame) self.plot_frame_layout.addWidget(self.canvas_plot_scrollarea, 1, 0) self.default_pen = QtGui.QPen(QtGui.QColor(0, 0, 0, 255), 1) self.default_brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 230)) self.highlight_brush = QtGui.QBrush(QtGui.QColor(255, 0, 255)) self.highlight_region_brush = QtGui.QBrush(QtGui.QColor(0, 255, 255)) # Builds the scene where to draw the Ramachandran plot. self.canvas_plot_scene = QtWidgets.QGraphicsScene() # Builds the graphics view containing the scene above. self.canvas_plot_view = QtWidgets.QGraphicsView(self.canvas_plot_scene) self.canvas_plot_frame_layout.addWidget(self.canvas_plot_view) # A bottom frame fo the window, containing some buttons to interact with the graph. self.message_frame = QtWidgets.QFrame() self.message_frame_layout = QtWidgets.QFormLayout() self.message_frame.setLayout(self.message_frame_layout) self.plot_frame_layout.addWidget(self.message_frame, 1, 1) # Label to show which residue/position pair is currently being hovered by the mouse pointer. self.view_label_prefix = "Showing: " self.default_message = "Hover dots to color residues of the same type" # Hover over title. self.message_label = QtWidgets.QLabel(self.default_message) self.message_label.setStyleSheet(small_font_style) self.message_frame_layout.addRow(self.message_label) # Actually draws the plot. self.draw_plot() # Shows some data about the type of residues and their dihedral angles. self.regions_labels_dict = {} tot_regular_res = float(self.residues_count["T"]) label_params = [ ("F", "Residues in the most favoured regions", "residues in most favoured regions", True, True), ("A", "Residues in additional allowed regions", "residues in additional allowed regions", True, True), ("G", "Residues in generously allowed regions", "residues in generously allowed regions", True, True), ("D", "Residues in disallowed regions", "residues in disallowed regions", True, True), ("T", "Non-gly and non-pro residues (circles)", "non-glycine and non-proline residues", True, True), ("end_res", "End-residues", "end residues", False, False), ("gly", "Gly residues (triangles)", "glycine residues", True, False), ("pro", "Pro residues (squares)", "proline residues", True, False), ("total", "Total number of residues", "all residues", True, False) ] for region, label, message, active, use_ratio in label_params: region_label = Ramachandran_plot_info_labels( label, message, region, active, self) region_label.setStyleSheet(small_font_style) if use_ratio: text = "%s (%s%%)" % (self.residues_count[region], round( self.residues_count[region] / tot_regular_res * 100, 1)) else: text = str(self.residues_count[region]) region_label_count = QtWidgets.QLabel(text) region_label_count.setStyleSheet(small_font_style) self.message_frame_layout.addRow(region_label, region_label_count) self.regions_labels_dict[region] = { "info": region_label, "data": region_label_count }
def initialize_map(self, pymod, data_array, pymod_elements, ref_residues, ref_selectors, title=None, pixel_size=5, feature_type="contact", threshold=8.0, interaction_center="ca"): # Sets the attributes. self.data_array = data_array self.pixel_size = pixel_size self.feature_type = feature_type self.threshold = threshold self.interaction_center = interaction_center if self.feature_type in ("contact", "distance"): self.pymod_elements = pymod_elements self.pymod_element = self.pymod_elements[0] else: self.pymod_elements = pymod_elements # Get the PyMod residues for each residue having an interaction center and the PyMOL selectors # for each residue. self.ref_residues = ref_residues self.ref_selectors = ref_selectors # Assign the methods to get the labels. if self.feature_type == "contact": self.get_value_label = self._get_value_label_contact elif self.feature_type == "distance": self.get_value_label = self._get_value_label_distance elif self.feature_type == "distances_difference": self.get_value_label = self._get_value_label_distance_diff elif self.feature_type == "distances_mean": self.get_value_label = self._get_value_label_distance_mean elif self.feature_type == "distances_std": self.get_value_label = self._get_value_label_distance_std else: raise KeyError(self.feature_type) # Set the canvas size. min_size = 150 h = self.pixel_size * len(self.data_array) win_size = min((910, h)) win_size = max((min_size, win_size)) if title: self.setWindowTitle(title) # Set some appearance parameters. self.controls_padding = 4 if self.feature_type in ("contact", "distance"): self.controls_font = "helvetica 11 bold" else: self.controls_font = "helvetica 10 bold" self.controls_config = { "fg": "black", "font": self.controls_font, "padx": self.controls_padding, "pady": self.controls_padding } self.labels_pack_config = { "side": "left", "pady": (0, 5), "padx": (5, 0) } self.buttons_pack_config = { "side": "left", "pady": (0, 5), "padx": (1, 0) } # Frame of the window containing a row for some control buttons, a row for # the plot and a row for a messagebar. self.plot_frame = QtWidgets.QWidget() self.plot_frame_layout = QtWidgets.QGridLayout() self.plot_frame.setLayout(self.plot_frame_layout) self.setCentralWidget(self.plot_frame) # Control frame. self.controls_frame = QtWidgets.QWidget() self.controls_frame_layout = QtWidgets.QGridLayout() self.controls_frame.setLayout(self.controls_frame_layout) self.plot_frame_layout.addWidget(self.controls_frame) self.delete_distances_button = QtWidgets.QPushButton( "Delete all distances in PyMOL") self.delete_distances_button.setEnabled(False) self.delete_distances_button.clicked.connect( lambda a=None: self.clear_plot()) self.controls_frame_layout.addWidget(self.delete_distances_button, 0, 0) self.scale_factor = 0 self.scale_down_button = QtWidgets.QPushButton("Zoom out") try: self.scale_down_button.setIcon(QtGui.QIcon.fromTheme("go-down")) except: pass self.scale_down_button.clicked.connect( lambda a=None: self.scale_plot_down()) self.controls_frame_layout.addWidget(self.scale_down_button, 0, 1) self.scale_up_button = QtWidgets.QPushButton("Zoom in") try: self.scale_up_button.setIcon(QtGui.QIcon.fromTheme("go-up")) except: pass self.scale_up_button.clicked.connect( lambda a=None: self.scale_plot_up()) self.controls_frame_layout.addWidget(self.scale_up_button, 0, 2) self.controls_frame_layout.setAlignment(QtCore.Qt.AlignLeft) # Frame containing the plot (with a scrollbar). self.canvas_plot_frame = QtWidgets.QWidget() self.canvas_plot_frame.setStyleSheet("background-color: white") self.canvas_plot_frame_layout = QtWidgets.QGridLayout() self.canvas_plot_frame.setLayout(self.canvas_plot_frame_layout) self.canvas_plot_scrollarea = QtWidgets.QScrollArea() self.canvas_plot_scrollarea.setWidgetResizable(True) self.canvas_plot_scrollarea.setWidget(self.canvas_plot_frame) self.plot_frame_layout.addWidget(self.canvas_plot_scrollarea) # Builds the scene where to draw the contact map. self.canvas_plot_scene = QtWidgets.QGraphicsScene() # Builds the graphics view containing the scene above. self.canvas_plot_view = Contact_map_graphics_view( self.canvas_plot_scene) self.canvas_plot_frame_layout.addWidget(self.canvas_plot_view) # A bottom frame fo the window, containing some buttons to interact with the graph. self.message_frame = QtWidgets.QFrame() self.message_frame_layout = QtWidgets.QHBoxLayout() self.message_frame.setLayout(self.message_frame_layout) self.plot_frame_layout.addWidget(self.message_frame) # Label to show which residue/position pair is currently being hovered by the mouse pointer. if self.feature_type in ("contact", "distance"): view_label_text = "Couple:" else: view_label_text = "Alignment positions:" self.view_label = QtWidgets.QLabel(view_label_text) # self.view_label.setStyleSheet(self.controls_config) self.message_frame_layout.addWidget(self.view_label) # Actually draws the contact map. self.draw_map()
def __init__(self, parent, protocol): super(Similarity_searches_results_window_qt, self).__init__(parent) self.protocol = protocol ######################### # Configure the window. # ######################### self.setWindowTitle(self._get_window_title()) # Sets the central widget. self.central_widget = QtWidgets.QWidget() self.setCentralWidget(self.central_widget) # The window has a main vbox layout. self.main_vbox = QtWidgets.QVBoxLayout() ################ # Upper frame. # ################ title_text = self._get_upper_frame_title() self.upper_frame_title = QtWidgets.QLabel(title_text) self.main_vbox.addWidget(self.upper_frame_title) ################# # Middle frame. # ################# # Scroll area which contains the widgets, set as the centralWidget. self.middle_scroll = QtWidgets.QScrollArea() self.main_vbox.addWidget(self.middle_scroll) # Widget that contains the collection of Vertical Box. self.middle_widget = QtWidgets.QWidget() # Scroll area properties. self.middle_scroll.setWidgetResizable(True) self.middle_scroll.setWidget(self.middle_widget) # QFormLayout in the middle frame. self.middle_formlayout = QtWidgets.QFormLayout() self.middle_widget.setLayout(self.middle_formlayout) #----------------- # Buttons frame. - #----------------- # Set the frame and its layout. self.buttons_frame = QtWidgets.QFrame() self.middle_formlayout.addRow(self.buttons_frame) self.buttons_hbox = QtWidgets.QHBoxLayout() self.buttons_frame.setLayout(self.buttons_hbox) # Build the control buttons. self.blast_select_all_button = QtWidgets.QPushButton(text="Select All") self.blast_select_all_button.clicked.connect(self.blast_select_all) self.blast_select_none_button = QtWidgets.QPushButton(text="Select None") self.blast_select_none_button.clicked.connect(self.blast_select_none) self.blast_select_n_button = QtWidgets.QPushButton(text="Select Top:") self.blast_select_n_button.clicked.connect(self.blast_select_n) for button in [self.blast_select_all_button, self.blast_select_none_button, self.blast_select_n_button]: self.buttons_hbox.addWidget(button) # Build the line-edit for selecting only top entries. self.blast_select_n_enf = PyMod_entryfield_qt(label_text="", value="10", validate={'validator': 'integer', 'min': 1, 'max': 5000}) self.blast_select_n_enf.entry.setFixedWidth(70) self.buttons_hbox.addWidget(self.blast_select_n_enf.entry) # Align to the left all these widgets. self.buttons_hbox.setAlignment(QtCore.Qt.AlignLeft) for button in [self.blast_select_all_button, self.blast_select_none_button, self.blast_select_n_button]: button.setFixedWidth(button.sizeHint().width()+30) #----------------- # Results frame. - #----------------- # Set the frame and its layout. self.results_frame = QtWidgets.QFrame() self.middle_formlayout.addRow(self.results_frame) self.results_grid = QtWidgets.QGridLayout() self.results_frame.setLayout(self.results_grid) # Calls a method which actually displays the similarity searches results. self.display_blast_hits() # Align the gridded widgets to the left. self.results_grid.setAlignment(QtCore.Qt.AlignLeft) self.results_grid.setHorizontalSpacing(30) ################# # Bottom frame. # ################# self.main_button = QtWidgets.QPushButton("Submit") self.main_button.clicked.connect(lambda a=None: self.protocol.blast_results_state()) self.main_vbox.addWidget(self.main_button) self.main_button.setFixedWidth(self.main_button.sizeHint().width()) # Sets the main vertical layout. self.central_widget.setLayout(self.main_vbox) self.main_vbox.setAlignment(self.main_button, QtCore.Qt.AlignCenter)
def __init__( self, parent, title="New PyMod Window", upper_frame_title="New PyMod Window Sub-title", submit_command=None, submit_button_text="Submit", with_scroll=True, # geometry=None ): super(PyMod_tool_window_qt, self).__init__(parent) #------------------------ # Configure the window. - #------------------------ # Command executed when pressing on the main button of the window. self.submit_command = submit_command # Configure the window. self.setWindowTitle(title) # if geometry is not None: # self.setGeometry(*geometry) # Sets the central widget. self.central_widget = QtWidgets.QWidget() self.setCentralWidget(self.central_widget) # The window has a main vbox layout. self.main_vbox = QtWidgets.QVBoxLayout() #--------------- # Upper frame. - #--------------- self.upper_frame_title = QtWidgets.QLabel(upper_frame_title) self.main_vbox.addWidget(self.upper_frame_title) #---------------- # Middle frame. - #---------------- # Widget that contains the collection of Vertical Box. self.middle_widget = QtWidgets.QWidget() # The Vertical Box that contains other widgets to be displayed in the window. self.middle_vbox = QtWidgets.QVBoxLayout() self.middle_widget.setLayout(self.middle_vbox) # Scroll area which contains the widgets, set as the centralWidget. self.middle_scroll = QtWidgets.QScrollArea() # Scroll area properties. # self.middle_scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn) # self.middle_scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.middle_scroll.setWidgetResizable(True) self.middle_scroll.setWidget(self.middle_widget) # QFormLayout in the middle frame. if self.middle_layout_type == "qform": self.middle_formlayout = PyMod_QFormLayout() self.middle_vbox.addLayout(self.middle_formlayout) elif self.middle_layout_type == "qgrid": self.middle_formlayout = QtWidgets.QGridLayout() self.middle_vbox.addLayout(self.middle_formlayout) else: raise KeyError("Unknown 'middle_layout_type': %s" % middle_layout_type) self.add_middle_frame_widgets() self.main_vbox.addWidget(self.middle_scroll) #---------------- # Bottom frame. - #---------------- self.submit_command = submit_command if self.submit_command is not None: self.main_button = QtWidgets.QPushButton(submit_button_text) self.main_button.clicked.connect( lambda a=None: self.submit_command()) self.main_vbox.addWidget(self.main_button) self.main_button.setFixedWidth(self.main_button.sizeHint().width()) # Sets the main vertical layout. self.central_widget.setLayout(self.main_vbox) self.main_vbox.setAlignment(self.main_button, QtCore.Qt.AlignCenter)
def __init__(self, parent=None, app=None): super(_BuilderPanel, self).__init__(parent) self.setWindowTitle("Builder") self.setObjectName("builder") self.cmd = app.pymol.cmd self.layout = QtWidgets.QVBoxLayout() self.setLayout(self.layout) self.buttons_layout = QtWidgets.QVBoxLayout() self.tabs = QtWidgets.QTabWidget(self) self.layout.setContentsMargins(5, 5, 5, 5); self.layout.setSpacing(5); self.layout.addWidget(self.tabs) self.layout.addLayout(self.buttons_layout) self.layout.addStretch() self.fragments_layout = QtWidgets.QGridLayout() self.fragments_layout.setContentsMargins(5, 5, 5, 5); self.fragments_layout.setSpacing(5); self.fragments_tab = QtWidgets.QWidget() self.fragments_tab.setLayout(self.fragments_layout) self.protein_layout = QtWidgets.QGridLayout() self.protein_layout.setContentsMargins(5, 5, 5, 5); self.protein_layout.setSpacing(5); self.protein_tab = QtWidgets.QWidget() self.protein_tab.setLayout(self.protein_layout) self.tabs.addTab(self.fragments_tab, "Chemical") self.tabs.addTab(self.protein_tab, "Protein") self.getIcons() buttons = [ [ ("H", "Hydrogen", lambda: self.replace("H", 1, 1, "Hydrogen")), ("C", "Carbon", lambda: self.replace("C", 4, 4, "Carbon")), ("N", "Nitrogen", lambda: self.replace("N", 4, 3, "Nitrogen")), ("O", "Oxygen", lambda: self.replace("O", 4, 2, "Oxygen")), ("P", "Phosphorus", lambda: self.replace("P",4,3, "Phosphorous")), ("S", "Sulfur", lambda: self.replace("S",2,2, "Sulfur")), ("F", "Fluorine", lambda: self.replace("F",1,1, "Fluorine")), ("Cl", "Chlorrine", lambda: self.replace("Cl",1,1, "Chlorine")), ("Br", "Bromine", lambda: self.replace("Br",1,1, "Bromine")), ("I", "Iodine", lambda: self.replace("I",1,1, "Iodine")), ("-CF3", "Trifluoromethane", lambda: self.replace("trifluoromethane",4,0, "trifluoro")), ("-OMe", "Methanol", lambda: self.replace("methanol",5,0, "methoxy")), ], [ ("CH4", "Methyl", lambda: self.grow("methane",1,0,"methyl")), ("C=C", "Ethylene", lambda: self.grow("ethylene",4,0,"vinyl")), ("C#C", "Acetylene", lambda: self.grow("acetylene",2,0,"alkynl")), ("C#N", "Cyanide", lambda: self.grow("cyanide",2,0,"cyano")), ("C=O", "Aldehyde", lambda: self.grow("formaldehyde",2,0,"carbonyl",)), ("C=OO", "Formic Acid", lambda: self.grow("formic",4,0,"carboxyl")), ("C=ON", "C->N amide", lambda: self.grow("formamide",5,0,"C->N amide")), ("NC=O", "N->C amide", lambda: self.grow("formamide",3,1,"N->C amide")), ("S=O2", "Sulfone", lambda: self.grow("sulfone",3,1,"sulfonyl")), ("P=O3", "Phosphite", lambda: self.grow("phosphite",4,0,"phosphoryl")), ("N=O2", "Nitro", lambda: self.grow("nitro",3,0,"nitro")), ], [ ("#cyc3", "Cyclopropane", lambda: self.grow("cyclopropane",4,0,"cyclopropyl")), ("#cyc4", "Cyclobutane", lambda: self.grow("cyclobutane",4,0,"cyclobutyl")), ("#cyc5", "Cyclopentane", lambda: self.grow("cyclopentane",5,0,"cyclopentyl")), ("#cyc6", "Cyclohexane", lambda: self.grow("cyclohexane",7,0,"cyclohexyl")), ("#cyc7", "Cycloheptane", lambda: self.grow("cycloheptane",8,0,"cycloheptyl")), ("#aro5", "Cyclopentadiene", lambda: self.grow("cyclopentadiene",5,0,"cyclopentadienyl")), ("#aro6", "Benzene", lambda: self.grow("benzene",6,0,"phenyl")), ("#aro65", "Indane", lambda: self.grow("indane",12,0,"indanyl")), ("#aro66", "Napthylene", lambda: self.grow("napthylene",13,0,"napthyl")), ("#aro67", "Benzocycloheptane", lambda: self.grow("benzocycloheptane",13,0, "benzocycloheptyl")), ] ] self.btn_icons = {} requestsize = QtCore.QSize(48, 48) for row, btn_row in enumerate(buttons): for col, bb in enumerate(btn_row): btn_label, btn_tooltip, btn_command = bb btn = makeFragmentButton() if btn_label.startswith('#'): icons = self.icons[btn_label[1:]] btn.setIcon(icons[0]) btn.setIconSize(icons[1].actualSize(requestsize)) self.btn_icons[btn] = icons else: btn.setText(btn_label) btn.setToolTip(btn_tooltip) btn.clicked.connect(btn_command) self.fragments_layout.addWidget(btn, row, col) buttons = [ [ 'Ace', 'Ala', 'Arg', 'Asn', 'Asp', 'Cys', 'Gln', 'Glu', 'Gly', 'His', 'Ile', 'Leu' ], [ 'Lys', 'Met', 'Phe', 'Pro', 'Ser', 'Thr', 'Trp', 'Tyr', 'Val', 'NMe', 'NHH' ] ] for row, btn_row in enumerate(buttons): for col, btn_label in enumerate(btn_row): btn = makeFragmentButton() btn.setText(btn_label) btn.setToolTip("Build %s residue" % btn_label) res = btn_label.lower() slot = lambda val=None, s=self,r=res: s.attach(r) btn.clicked.connect(slot) self.protein_layout.addWidget(btn, row, col) lab = QtWidgets.QLabel('Secondary Structure:') lab_cols = 3 self.ss_cbox = QtWidgets.QComboBox() self.ss_cbox.addItem("Alpha Helix") self.ss_cbox.addItem("Beta Sheet (Anti-Parallel)") self.ss_cbox.addItem("Beta Sheet (Parallel)") self.protein_layout.addWidget(lab, 2, 0, 1, lab_cols) self.protein_layout.addWidget(self.ss_cbox, 2, lab_cols, 1, 4) self.ss_cbox.currentIndexChanged[int].connect(self.ssIndexChanged) buttons = [ [ ( "@Atoms:", None, None), ( "Fix H", "Fix hydrogens on picked atoms", self.fixH), ( "Add H", "Add hydrogens to entire molecule", self.addH), ( "Invert", "Invert stereochemistry around pk1 (pk2 and pk3 will remain fixed)", self.invert), ( "Delete", "Remove atoms", self.removeAtom), ( "Clear", "Delete everything", self.clear), ( "@ Charge:", None, None), ( " +1 ", "Positive Charge", lambda: self.setCharge(1,"+1")), ( " 0 ", "Neutral Charge", lambda: self.setCharge(0,"neutral")), ( " -1 ", "Negative Charge", lambda: self.setCharge(-1,"-1")), ], [ ( "@Bonds:", None, None), ( "Create", "Create bond between pk1 and pk2", self.createBond), ( "Delete", "Delete bond between pk1 and pk2", self.deleteBond), ( "Cycle", "Cycle bond valence", self.cycleBond), ( " | ", "Create single bond", lambda: self.setOrder("1", "single")), ( " || ", "Create double bond", lambda: self.setOrder("2", "double")), ( " ||| ", "Create triple bond", lambda: self.setOrder("3", "triple")), ( "Arom", "Create aromatic bond", lambda: self.setOrder("4", "aromatic")), ( "@ Model:", None, None), ( "Clean", "Cleanup structure", self.clean), ( "Sculpt", "Molecular sculpting", self.sculpt), ( "Fix", "Fix atom positions", self.fix), ( "Rest", "Restrain atom positions", self.rest), ], [ ( "$El-stat", "Electrostatics term for 'Clean' action", "clean_electro_mode"), ( "@ ", None, None), ( "$Bumps", "Show VDW contacts during sculpting", "sculpt_vdw_vis_mode"), ( "@ ", None, None), ( "#Undo Enabled", "", "suspend_undo"), ( "Undo", "Undo last change", self.undo), ( "Redo", "Redo last change", self.redo), ] ] for row, btn_row in enumerate(buttons): btn_row_layout = QtWidgets.QHBoxLayout() self.buttons_layout.addLayout(btn_row_layout) for col, bb in enumerate(btn_row): btn_label, btn_tooltip, btn_command = bb if btn_label[0] == '@': btn = QtWidgets.QLabel(btn_label[1:]) elif btn_label[0] in ('#', '$'): btn = QtWidgets.QCheckBox(btn_label[1:]) setting = btn_command value = self.cmd.get_setting_int(setting) if btn_label[0] == '$': btn.setChecked(bool(value)) @btn.toggled.connect def _(checked, n=setting): self.cmd.set(n, checked, quiet=0) else: btn.setChecked(not value) @btn.toggled.connect def _(checked, n=setting): self.cmd.set(n, not checked, quiet=0) else: btn = makeFragmentButton() btn.setText(btn_label) btn.clicked.connect(btn_command) if btn_tooltip: btn.setToolTip(btn_tooltip) btn_row_layout.addWidget(btn) btn_row_layout.addStretch()
def __init__(self, parent, protocol): super(Hmmscan_results_window_qt, self).__init__(parent) self.protocol = protocol self.query_len = len( self.protocol.query_element.my_sequence.replace('-', '')) ######################### # Configure the window. # ######################### self.setWindowTitle("HMMSCAN Results") # Sets the central widget. self.central_widget = QtWidgets.QWidget() self.setCentralWidget(self.central_widget) # The window has a main vbox layout. self.main_vbox = QtWidgets.QVBoxLayout() # Parameters used to draw the 'QGraphicsView' widgets for showing domains. self.preferred_size_policy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) self.view_bg_color = "transparent" self.full_seq_pen = QtGui.QPen(QtGui.QColor(0, 0, 0, 0), 2) self.full_seq_color = "#7f7f7f" qcolor = QtGui.QColor(0, 0, 0) qcolor.setNamedColor(self.full_seq_color) self.full_seq_brush = QtGui.QBrush(qcolor) self.font_qcolor = QtGui.QColor(220, 220, 220, 255) self.font_size = 7 ################ # Upper frame. # ################ self.upper_frame = QtWidgets.QFrame() self.upper_frame_layout = QtWidgets.QGridLayout() self.upper_frame.setLayout(self.upper_frame_layout) self.main_vbox.addWidget(self.upper_frame) if 'query_descr' in self.protocol.parsed_res[ 0] and self.protocol.parsed_res[0]['query_descr']: labelseq = self.protocol.query_element.my_header # + '\n' + querydescr else: try: if len(self.protocol.query_element.description) > 79: labelseq = self.protocol.query_element.description[:78] + '...' else: labelseq = self.protocol.query_element.description except TypeError: labelseq = self.protocol.query_element.my_header self.upper_frame_title = QtWidgets.QLabel( "HMMSCAN search results for " + labelseq) self.upper_frame_layout.addWidget(self.upper_frame_title) #------------------------- # Domain graphics frame. - #------------------------- # Builds the scene where to draw the domain representations. self.canvas_plot_scene = QtWidgets.QGraphicsScene() self.canvas_plot_view = QtWidgets.QGraphicsView(self.canvas_plot_scene) self.canvas_plot_view.setFixedHeight(120) self.canvas_plot_view.setSizePolicy(self.preferred_size_policy) self.canvas_plot_view.setStyleSheet("background: %s" % self.view_bg_color) self.upper_frame_layout.addWidget(self.canvas_plot_view) # Draw a rectangle with the full sequence. self.x_init = 10 y_init = 95 # 95 self.domain_y_init = y_init - 7 self.full_seq_rect_w = 800 full_seq_rect_h = 10 self.canvas_plot_scene.addRect(self.x_init, y_init, self.full_seq_rect_w, full_seq_rect_h, self.full_seq_pen, self.full_seq_brush) # Draw the labels for the N- and C-terminal residues. text_offset_y = 15 text_offset_x = 10 text_n = self.canvas_plot_scene.addText("1") text_n.setPos(self.x_init - text_offset_x, y_init + text_offset_y) text_n.setDefaultTextColor(self.font_qcolor) text_n.setFont(QtGui.QFont(text_n.font().family(), self.font_size)) c_label = str(self.query_len) text_c = self.canvas_plot_scene.addText(c_label) text_offset_x_add = 5 if len(c_label) > 2: text_offset_x_add = 10 text_c.setPos( self.x_init + self.full_seq_rect_w - text_offset_x - text_offset_x_add, y_init + text_offset_y) text_c.setDefaultTextColor(self.font_qcolor) text_c.setFont(QtGui.QFont(text_c.font().family(), self.font_size)) ################# # Middle frame. # ################# # Scroll area which contains the widgets, set as the centralWidget. self.middle_scroll = QtWidgets.QScrollArea() self.main_vbox.addWidget(self.middle_scroll) # Widget that contains the collection of Vertical Box. self.middle_widget = QtWidgets.QWidget() # Scroll area properties. self.middle_scroll.setWidgetResizable(True) self.middle_scroll.setWidget(self.middle_widget) # QFormLayout in the middle frame. self.middle_formlayout = QtWidgets.QFormLayout() self.middle_widget.setLayout(self.middle_formlayout) #----------------- # Results frame. - #----------------- # Set the frame and its layout. self.results_frame = QtWidgets.QFrame() self.middle_formlayout.addRow(self.results_frame) self.results_grid = QtWidgets.QGridLayout() self.results_frame.setLayout(self.results_grid) # Calls a method which actually displays the similarity searches results. self.display_hmmscan_hits() # Align the gridded widgets to the left. self.results_grid.setAlignment(QtCore.Qt.AlignLeft) self.results_grid.setHorizontalSpacing(30) ################# # Bottom frame. # ################# self.main_button = QtWidgets.QPushButton("Submit") self.main_button.clicked.connect( lambda a=None: self.protocol.hmmer_results_state()) self.main_vbox.addWidget(self.main_button) self.main_button.setFixedWidth(self.main_button.sizeHint().width()) # Sets the main vertical layout. self.central_widget.setLayout(self.main_vbox) self.main_vbox.setAlignment(self.main_button, QtCore.Qt.AlignCenter)
def new_manager_widget(manager, title): dockWidget = QtWidgets.QDockWidget() dockWidget.setWindowTitle(title) widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout(widget) dockWidget.setWidget(widget) widget.setLayout(layout) model = QtGui.QStandardItemModel(0, 1, widget) tree = QtWidgets.QTreeView(widget) tree.setModel(model) tree.setHeaderHidden(True) current_key = None def update_treeview(): model.clear() for key in manager.get_keys(): item = QtGui.QStandardItem() item.setText(key) model.blockSignals(True) model.appendRow(item) model.blockSignals(False) @model.rowsInserted.connect def onRowsInserted(index): key = model.itemFromIndex(index).text() store_view(key) update_treeview() @model.dataChanged.connect def onDataChanged(index): new_key = model.itemFromIndex(index).text() if new_key == "": manager.clear(current_key) else: manager.rename(current_key, new_key) update_treeview() @dockWidget.visibilityChanged.connect def onVisibilityChanged(visible): if not visible: return update_treeview() @tree.clicked.connect def onClicked(index): nonlocal current_key key = model.itemFromIndex(index).text() current_key = key manager.recall(key) storeBtn = QtWidgets.QPushButton("Store", widget) @storeBtn.clicked.connect def onClicked(): count = len(manager.get_keys()) manager.store(f"view{count}") update_treeview() layout.addWidget(tree) layout.addWidget(storeBtn) return dockWidget