def initUI(self): self.setWindowTitle(self.title) vertical_layout = QtWidgets.QVBoxLayout() self.thread_progressbar = QtWidgets.QProgressBar(self) if self.progress: self.thread_progressbar.setMinimum(0) self.thread_progressbar.setMaximum(0) progressbar_label = "Computing..." # "Wait for the protocol to complete." self.thread_progressbar.setFormat(progressbar_label) self.thread_progressbar.setValue(0) vertical_layout.addWidget(self.thread_progressbar) self.thread_progress_label = QtWidgets.QLabel(self.label_text, self) self.thread_progress_label.setWordWrap(True) vertical_layout.addWidget(self.thread_progress_label) # Button for canceling the execution of the thread. horizontal_layout = QtWidgets.QHBoxLayout() self.cancel_button = QtWidgets.QPushButton('Cancel', self) self.cancel_button.clicked.connect(self.on_cancel_button_click) self.cancel_button.setEnabled(not self.lock) horizontal_layout.addWidget(self.cancel_button) vertical_layout.addLayout(horizontal_layout) self.setLayout(vertical_layout)
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 setupUi(self, UpdateDialog): UpdateDialog.setObjectName("UpdateDialog") UpdateDialog.resize(950, 470) self.verticalLayout = QtWidgets.QVBoxLayout(UpdateDialog) self.verticalLayout.setObjectName("verticalLayout") self.select_comp_label = QtWidgets.QLabel(UpdateDialog) self.select_comp_label.setObjectName("select_comp_label") self.verticalLayout.addWidget(self.select_comp_label) self.components_tableWidget = QtWidgets.QTableWidget(UpdateDialog) default_font = QtGui.QFont() default_font.setPointSize(default_font.pointSize()-1) self.components_tableWidget.setFont(default_font) self.components_tableWidget.setProperty("showDropIndicator", False) self.components_tableWidget.setDragDropOverwriteMode(False) self.components_tableWidget.setAlternatingRowColors(True) self.components_tableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) self.components_tableWidget.setGridStyle(QtCore.Qt.NoPen) self.components_tableWidget.setColumnCount(self.n_cols) self.components_tableWidget.setObjectName("components_tableWidget") self.components_tableWidget.setRowCount(1) vertical_header_item = QtWidgets.QTableWidgetItem() self.components_tableWidget.setVerticalHeaderItem(0, vertical_header_item) for i in range(self.n_cols): item = QtWidgets.QTableWidgetItem() self.components_tableWidget.setHorizontalHeaderItem(i, item) item = QtWidgets.QTableWidgetItem() self.components_tableWidget.setItem(0, self.component_col_idx, item) item = QtWidgets.QTableWidgetItem() self.components_tableWidget.setItem(0, self.databases_col_idx, item) self.components_tableWidget.horizontalHeader().setVisible(True) self.components_tableWidget.horizontalHeader().setCascadingSectionResizes(False) self.components_tableWidget.setColumnWidth(self.component_col_idx, 210) self.components_tableWidget.setColumnWidth(self.databases_col_idx, 180) self.components_tableWidget.setColumnWidth(self.status_col_idx, 190) # self.components_tableWidget.setColumnWidth(self.source_col_idx, 390) # self.components_tableWidget.setColumnWidth(self.last_download_col_idx, 250) self.components_tableWidget.horizontalHeader().setStretchLastSection(True) self.components_tableWidget.verticalHeader().setVisible(False) self.components_tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) self.verticalLayout.addWidget(self.components_tableWidget) self.statusLabel = QtWidgets.QLabel(UpdateDialog) self.statusLabel.setObjectName("statusLabel") self.verticalLayout.addWidget(self.statusLabel) self.installation_progressBar = QtWidgets.QProgressBar(UpdateDialog) self.installation_progressBar.setEnabled(True) self.installation_progressBar.setProperty("value", 10) self.installation_progressBar.setObjectName("installation_progressBar") self.verticalLayout.addWidget(self.installation_progressBar) self.buttonsHorizontalLayout = QtWidgets.QHBoxLayout() self.buttonsHorizontalLayout.setObjectName("buttonsHorizontalLayout") self.installSel_button = QtWidgets.QPushButton(UpdateDialog) self.installSel_button.setObjectName("installSel_button") self.buttonsHorizontalLayout.addWidget(self.installSel_button) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.buttonsHorizontalLayout.addItem(spacerItem) self.cancel_button = QtWidgets.QPushButton(UpdateDialog) self.cancel_button.setObjectName("cancel_button") self.buttonsHorizontalLayout.addWidget(self.cancel_button) self.verticalLayout.addLayout(self.buttonsHorizontalLayout) UpdateDialog.setWindowTitle("Install and update databases") self.select_comp_label.setText("Select components to install or update") self.components_tableWidget.setSortingEnabled(True) self.components_tableWidget.horizontalHeaderItem(self.component_col_idx).setText("Component") self.components_tableWidget.horizontalHeaderItem(self.databases_col_idx).setText("Databases Names") self.components_tableWidget.horizontalHeaderItem(self.status_col_idx).setText("Status") self.components_tableWidget.horizontalHeaderItem(self.source_col_idx).setText("Source") self.components_tableWidget.horizontalHeaderItem(self.last_download_col_idx).setText("Last Downloaded") __sortingEnabled = self.components_tableWidget.isSortingEnabled() self.components_tableWidget.setSortingEnabled(False) self.components_tableWidget.setSortingEnabled(__sortingEnabled) self.statusLabel.setText("") self.cancel_button.setText("Cancel") self.installSel_button.setText("Install Selected") QtCore.QMetaObject.connectSlotsByName(UpdateDialog)