def _set_step(self, step): """Proceed to a given step""" new_tab = self.tab_widget.currentIndex() + step assert new_tab < self.tab_widget.count() and new_tab >= 0 if new_tab == self.tab_widget.count()-1: try: self.table_widget.open_data(self._get_plain_text(), self.text_widget.get_col_sep(), self.text_widget.get_row_sep(), self.text_widget.trnsp_box.isChecked(), self.text_widget.get_skiprows(), self.text_widget.get_comments()) self.done_btn.setEnabled(True) self.done_btn.setDefault(True) self.fwd_btn.setEnabled(False) self.back_btn.setEnabled(True) except (SyntaxError, AssertionError) as error: QMessageBox.critical(self, _("Import wizard"), _("<b>Unable to proceed to next step</b>" "<br><br>Please check your entries." "<br><br>Error message:<br>%s") % str(error)) return elif new_tab == 0: self.done_btn.setEnabled(False) self.fwd_btn.setEnabled(True) self.back_btn.setEnabled(False) self._focus_tab(new_tab)
def set_umr_namelist(self): """Set UMR excluded modules name list""" arguments, valid = QInputDialog.getText(self, _('UMR'), _("Set the list of excluded modules as " "this: <i>numpy, scipy</i>"), QLineEdit.Normal, ", ".join(self.get_option('umr/namelist'))) if valid: arguments = to_text_string(arguments) if arguments: namelist = arguments.replace(' ', '').split(',') fixed_namelist = [module_name for module_name in namelist if programs.is_module_installed(module_name)] invalid = ", ".join(set(namelist)-set(fixed_namelist)) if invalid: QMessageBox.warning(self, _('UMR'), _("The following modules are not " "installed on your machine:\n%s" ) % invalid, QMessageBox.Ok) QMessageBox.information(self, _('UMR'), _("Please note that these changes will " "be applied only to new Python/IPython " "consoles"), QMessageBox.Ok) else: fixed_namelist = [] self.set_option('umr/namelist', fixed_namelist)
def chdir(self, directory=None, browsing_history=False): """Set directory as working directory""" if directory is not None: directory = osp.abspath(to_text_string(directory)) if browsing_history: directory = self.history[self.histindex] elif directory in self.history: self.histindex = self.history.index(directory) else: if self.histindex is None: self.history = [] else: self.history = self.history[:self.histindex+1] if len(self.history) == 0 or \ (self.history and self.history[-1] != directory): self.history.append(directory) self.histindex = len(self.history)-1 directory = to_text_string(directory) if PY2: PermissionError = OSError try: os.chdir(directory) self.parent_widget.open_dir.emit(directory) self.refresh(new_path=directory, force_current=True) except PermissionError: QMessageBox.critical(self.parent_widget, "Error", _("You don't have the right permissions to " "open this directory"))
def launch_error_message(self, error_type, error=None): """Launch a message box with a predefined error message. Parameters ---------- error_type : int [CLOSE_ERROR, RESET_ERROR, RESTART_ERROR] Possible error codes when restarting/reseting spyder. error : Exception Actual Python exception error caught. """ messages = {CLOSE_ERROR: _("It was not possible to close the previous " "Spyder instance.\nRestart aborted."), RESET_ERROR: _("Spyder could not reset to factory " "defaults.\nRestart aborted."), RESTART_ERROR: _("It was not possible to restart Spyder.\n" "Operation aborted.")} titles = {CLOSE_ERROR: _("Spyder exit error"), RESET_ERROR: _("Spyder reset error"), RESTART_ERROR: _("Spyder restart error")} if error: e = error.__repr__() message = messages[error_type] + "\n\n{0}".format(e) else: message = messages[error_type] title = titles[error_type] self.splash.hide() QMessageBox.warning(self, title, message, QMessageBox.Ok) raise RuntimeError(message)
def help(self): """Help on Spyder console""" QMessageBox.about( self, _("Help"), """<b>%s</b> <p><i>%s</i><br> edit foobar.py <p><i>%s</i><br> xedit foobar.py <p><i>%s</i><br> run foobar.py <p><i>%s</i><br> clear x, y <p><i>%s</i><br> !ls <p><i>%s</i><br> object? <p><i>%s</i><br> result = oedit(object) """ % ( _("Shell special commands:"), _("Internal editor:"), _("External editor:"), _("Run script:"), _("Remove references:"), _("System commands:"), _("Python help:"), _("GUI-based editor:"), ), )
def change_format(self): """ Ask user for display format for floats and use it. This function also checks whether the format is valid and emits `sig_option_changed`. """ format, valid = QInputDialog.getText(self, _('Format'), _("Float formatting"), QLineEdit.Normal, self.dataModel.get_format()) if valid: format = str(format) try: format % 1.1 except: msg = _("Format ({}) is incorrect").format(format) QMessageBox.critical(self, _("Error"), msg) return if not format.startswith('%'): msg = _("Format ({}) should start with '%'").format(format) QMessageBox.critical(self, _("Error"), msg) return self.dataModel.set_format(format) self.sig_option_changed.emit('dataframe_format', format)
def sort(self, column, order=Qt.AscendingOrder): """Overriding sort method""" if self.complex_intran is not None: if self.complex_intran.any(axis=0).iloc[column-1]: QMessageBox.critical(self.dialog, "Error", "TypeError error: no ordering " "relation is defined for complex numbers") return False try: ascending = order == Qt.AscendingOrder if column > 0: try: self.df.sort_values(by=self.df.columns[column-1], ascending=ascending, inplace=True, kind='mergesort') except AttributeError: # for pandas version < 0.17 self.df.sort(columns=self.df.columns[column-1], ascending=ascending, inplace=True, kind='mergesort') self.update_df_index() else: self.df.sort_index(inplace=True, ascending=ascending) self.update_df_index() except TypeError as e: QMessageBox.critical(self.dialog, "Error", "TypeError error: %s" % str(e)) return False self.reset() return True
def save_loader_script(self, event=None, output_directory=None): """ oputput_directory parameter is strictly for use in tests. """ if not self.save_loader_check(): return specutils_dir = os.path.join(os.path.expanduser('~'), '.specutils') if not os.path.exists(specutils_dir): os.mkdir(specutils_dir) loader_name = self.ui.loader_name.text() # If the loader name already exists in the registry, raise a warning # and ask the user to pick another name if loader_name in registry.get_formats(Spectrum1D, 'Read')['Format']: QMessageBox.information( self, "Loader name already exists.", "A loader with the name '{}' already exists in the registry. " "Please choose a different name.".format(loader_name)) return out_path = os.path.join(specutils_dir, loader_name) filename = compat.getsavefilename(parent=self, caption='Export loader to .py file', basedir=out_path)[0] if filename == '': return self.save_register_new_loader(filename)
def action_released(self): """ """ model = self.source_model model_index = self._model_index_clicked if model_index: column = model_index.column() if column == const.INSTALL and model.is_removable(model_index): column = const.REMOVE self.source_model.update_row_icon(model_index.row(), column) if self.valid: row_data = self.source_model.row(model_index.row()) type_ = row_data[const.PACKAGE_TYPE] name = row_data[const.NAME] versions = self.source_model.get_package_versions(name) version = self.source_model.get_package_version(name) if type_ == const.CONDA: self._parent._run_action(name, column, version, versions) elif type_ == const.PIP: QMessageBox.information(self, "Remove pip package: " "{0}".format(name), "This functionality is not yet " "available.") else: pass
def set_user_env(reg, parent=None): """Set HKCU (current user) environment variables""" reg = listdict2envdict(reg) types = dict() key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Environment") for name in reg: try: _x, types[name] = winreg.QueryValueEx(key, name) except WindowsError: types[name] = winreg.REG_EXPAND_SZ key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Environment", 0, winreg.KEY_SET_VALUE) for name in reg: winreg.SetValueEx(key, name, 0, types[name], reg[name]) try: from win32gui import SendMessageTimeout from win32con import (HWND_BROADCAST, WM_SETTINGCHANGE, SMTO_ABORTIFHUNG) SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, "Environment", SMTO_ABORTIFHUNG, 5000) except ImportError: QMessageBox.warning(parent, _("Warning"), _("Module <b>pywin32 was not found</b>.<br>" "Please restart this Windows <i>session</i> " "(not the computer) for changes to take effect."))
def save_register_new_loader(self, filename): """ Save and register new loader file to specutils loader directory. If a loader with the current name already exists it will be deleted. Parameters ---------- filename: str Loader filename. If filename does not end in ".py", ".py" will be appended to the end of the string. """ filename = "{}.py".format(filename) if not filename.endswith(".py") else filename string = self.as_new_loader() with open(filename, 'w') as f: f.write(string) # If a loader by this name exists, delete it if self.new_loader_dict['name'] in registry.get_formats()['Format']: registry.unregister_reader(self.new_loader_dict['name'], Spectrum1D) registry.unregister_identifier(self.new_loader_dict['name'], Spectrum1D) # Add new loader to registry spec = importlib.util.spec_from_file_location(os.path.basename(filename)[:-3], filename) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) QMessageBox.information(self, "Loader saved successful.", "Custom loader was saved successfully.")
def save_data(self, filename=None): """Save data""" if filename is None: filename = self.filename if filename is None: filename = getcwd_or_home() filename, _selfilter = getsavefilename(self, _("Save data"), filename, iofunctions.save_filters) if filename: self.filename = filename else: return False QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() error_message = self.shellwidget.save_namespace(self.filename) self.shellwidget._kernel_reply = None QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: QMessageBox.critical(self, _("Save data"), _("<b>Unable to save current workspace</b>" "<br><br>Error message:<br>%s") % error_message) self.save_button.setEnabled(self.filename is not None)
def save_data(self, filename=None): """Save data""" if filename is None: filename = self.filename if filename is None: filename = getcwd() filename, _selfilter = getsavefilename(self, _("Save data"), filename, iofunctions.save_filters) if filename: self.filename = filename else: return False QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() if self.is_internal_shell: wsfilter = self.get_internal_shell_filter('picklable', check_all=True) namespace = wsfilter(self.shellwidget.interpreter.namespace).copy() error_message = iofunctions.save(namespace, filename) else: settings = self.get_view_settings() error_message = monitor_save_globals(self._get_sock(), settings, filename) QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: QMessageBox.critical(self, _("Save data"), _("<b>Unable to save current workspace</b>" "<br><br>Error message:<br>%s") % error_message) self.save_button.setEnabled(self.filename is not None)
def mirror_navi(self, uisignals=None, shared_nav=False): # Select signals if uisignals is None: uisignals = self.ui.get_selected_wrappers() if len(uisignals) < 2: mb = QMessageBox(QMessageBox.Information, tr("Select two or more"), tr("You need to select two or more signals" + " to mirror"), QMessageBox.Ok) mb.exec_() return signals = [s.signal for s in uisignals] # hyperspy closes, and then recreates figures when mirroring # the navigators. To keep UI from flickering, we suspend updates. # SignalWrapper also saves and then restores window geometry self.ui.setUpdatesEnabled(False) try: if shared_nav: navs = ["auto"] navs.extend([None] * (len(signals)-1)) hyperspy.utils.plot.plot_signals(signals, sync=True, navigator_list=navs) else: hyperspy.utils.plot.plot_signals(signals, sync=True) finally: self.ui.setUpdatesEnabled(True) # Continue updating UI
def start(self): filename = to_text_string(self.filecombo.currentText()) self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setWorkingDirectory(osp.dirname(filename)) self.process.readyReadStandardOutput.connect(self.read_output) self.process.readyReadStandardError.connect( lambda: self.read_output(error=True)) self.process.finished.connect(lambda ec, es=QProcess.ExitStatus: self.finished(ec, es)) self.stop_button.clicked.connect(self.process.kill) self.output = '' self.error_output = '' plver = PYLINT_VER if plver is not None: if plver.split('.')[0] == '0': p_args = ['-i', 'yes'] else: # Option '-i' (alias for '--include-ids') was removed in pylint # 1.0 p_args = ["--msg-template='{msg_id}:{line:3d},"\ "{column}: {obj}: {msg}"] p_args += [osp.basename(filename)] else: p_args = [osp.basename(filename)] self.process.start(PYLINT_PATH, p_args) running = self.process.waitForStarted() self.set_running_state(running) if not running: QMessageBox.critical(self, _("Error"), _("Process failed to start"))
def save_data(self, filename=None): """Save data""" if filename is None: filename = self.filename if filename is None: filename = getcwd_or_home() filename, _selfilter = getsavefilename(self, _("Save data"), filename, iofunctions.save_filters) if filename: self.filename = filename else: return False QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() error_message = self.shellwidget.save_namespace(self.filename) self.shellwidget._kernel_reply = None QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: if 'Some objects could not be saved:' in error_message: save_data_message = ( _('<b>Some objects could not be saved:</b>') + '<br><br><code>{obj_list}</code>'.format( obj_list=error_message.split(': ')[1])) else: save_data_message = _( '<b>Unable to save current workspace</b>' '<br><br>Error message:<br>') + error_message QMessageBox.critical(self, _("Save data"), save_data_message) self.save_button.setEnabled(self.filename is not None)
def open_project(self, path=None, restart_consoles=True, save_previous_files=True): """Open the project located in `path`""" if path is None: basedir = get_home_dir() path = getexistingdirectory(parent=self, caption=_("Open project"), basedir=basedir) if not self.is_valid_project(path): if path: QMessageBox.critical(self, _('Error'), _("<b>%s</b> is not a Spyder project!") % path) return else: self.add_to_recent(path) # A project was not open before if self.current_active_project is None: if save_previous_files: self.editor.save_open_files() self.editor.set_option('last_working_dir', getcwd_or_home()) self.show_explorer() else: # we are switching projects self.set_project_filenames(self.editor.get_open_filenames()) self.current_active_project = EmptyProject(path) self.latest_project = EmptyProject(path) self.set_option('current_project_path', self.get_active_project_path()) self.setup_menu_actions() self.sig_project_loaded.emit(path) self.pythonpath_changed.emit() if restart_consoles: self.restart_consoles()
def _sel_to_text(self, cell_range): """Copy an array portion to a unicode string""" if not cell_range: return row_min, row_max, col_min, col_max = get_idx_rect(cell_range) if col_min == 0 and col_max == (self.model().cols_loaded-1): # we've selected a whole column. It isn't possible to # select only the first part of a column without loading more, # so we can treat it as intentional and copy the whole thing col_max = self.model().total_cols-1 if row_min == 0 and row_max == (self.model().rows_loaded-1): row_max = self.model().total_rows-1 _data = self.model().get_data() if PY3: output = io.BytesIO() else: output = io.StringIO() try: np.savetxt(output, _data[row_min:row_max+1, col_min:col_max+1], delimiter='\t') except: QMessageBox.warning(self, _("Warning"), _("It was not possible to copy values for " "this array")) return contents = output.getvalue().decode('utf-8') output.close() return contents
def setData(self, index, value, role=Qt.EditRole, change_type=None): """Cell content change""" column = index.column() row = index.row() if change_type is not None: try: value = self.data(index, role=Qt.DisplayRole) val = from_qvariant(value, str) if change_type is bool: val = bool_false_check(val) self.df.iloc[row, column - 1] = change_type(val) except ValueError: self.df.iloc[row, column - 1] = change_type('0') else: val = from_qvariant(value, str) current_value = self.get_value(row, column-1) if isinstance(current_value, bool): val = bool_false_check(val) supported_types = (bool,) + REAL_NUMBER_TYPES + COMPLEX_NUMBER_TYPES if (isinstance(current_value, supported_types) or is_text_string(current_value)): try: self.df.iloc[row, column-1] = current_value.__class__(val) except ValueError as e: QMessageBox.critical(self.dialog, "Error", "Value error: %s" % str(e)) return False else: QMessageBox.critical(self.dialog, "Error", "The type of the cell is not a supported " "type") return False self.max_min_col_update() return True
def create_new_folder(self, current_path, title, subtitle, is_package): """Create new folder""" if current_path is None: current_path = '' if osp.isfile(current_path): current_path = osp.dirname(current_path) name, valid = QInputDialog.getText(self, title, subtitle, QLineEdit.Normal, "") if valid: dirname = osp.join(current_path, to_text_string(name)) try: os.mkdir(dirname) except EnvironmentError as error: QMessageBox.critical(self, title, _("<b>Unable " "to create folder <i>%s</i></b>" "<br><br>Error message:<br>%s" ) % (dirname, to_text_string(error))) finally: if is_package: fname = osp.join(dirname, '__init__.py') try: with open(fname, 'wb') as f: f.write(to_binary_string('#')) return dirname except EnvironmentError as error: QMessageBox.critical(self, title, _("<b>Unable " "to create file <i>%s</i></b>" "<br><br>Error message:<br>%s" ) % (fname, to_text_string(error)))
def _scatter_artist(self, axes, state, layer=None, layer_state=None): if len(self._layer_artist_container) == 0: QMessageBox.critical(self, "Error", "Can only add a scatter plot " "overlay once an image is present", buttons=QMessageBox.Ok) return None return ScatterLayerArtist(axes, state, layer=layer, layer_state=None)
def rename_file(self, fname): """Rename file""" path, valid = QInputDialog.getText(self, _('Rename'), _('New name:'), QLineEdit.Normal, osp.basename(fname)) if valid: path = osp.join(osp.dirname(fname), to_text_string(path)) if path == fname: return if osp.exists(path): if QMessageBox.warning(self, _("Rename"), _("Do you really want to rename <b>%s</b> and " "overwrite the existing file <b>%s</b>?" ) % (osp.basename(fname), osp.basename(path)), QMessageBox.Yes|QMessageBox.No) == QMessageBox.No: return try: misc.rename_file(fname, path) self.parent_widget.renamed.emit(fname, path) return path except EnvironmentError as error: QMessageBox.critical(self, _("Rename"), _("<b>Unable to rename file <i>%s</i></b>" "<br><br>Error message:<br>%s" ) % (osp.basename(fname), to_text_string(error)))
def converter(self, parent=None, convert_data=False): """ Launch Converter GUI :param parent: application :param values: convert data values if True. Only displayed units if False. :return: ConvertFluxUnitGUI instance :raise: Exception: If wavelength info is missing """ if self.wavelengths is None: message = "Could not launch conversion ui because" \ "wavelength information is missing." info = QMessageBox.critical(parent, "Error", message) raise Exception(message) if convert_data: message = "You are about to launch the data flux units converter. " \ "This will modify the actual values stored in components " \ "according to the unit conversions selected. If you would rather" \ " change the displayed units, please select the Convert" \ " Displayed Units option." info = QMessageBox.warning(parent, "Info", message) if hasattr(u.spectral_density, "pixel_area"): u.spectral_density.pixel_area = self.pixel_area ex = ConvertFluxUnitGUI(self, parent, convert_data) return ex
def delete_file(self, fname, multiple, yes_to_all): """Delete file""" if multiple: buttons = QMessageBox.Yes|QMessageBox.YesAll| \ QMessageBox.No|QMessageBox.Cancel else: buttons = QMessageBox.Yes|QMessageBox.No if yes_to_all is None: answer = QMessageBox.warning(self, _("Delete"), _("Do you really want " "to delete <b>%s</b>?" ) % osp.basename(fname), buttons) if answer == QMessageBox.No: return yes_to_all elif answer == QMessageBox.Cancel: return False elif answer == QMessageBox.YesAll: yes_to_all = True try: if osp.isfile(fname): misc.remove_file(fname) self.parent_widget.removed.emit(fname) else: self.remove_tree(fname) self.parent_widget.removed_tree.emit(fname) return yes_to_all except EnvironmentError as error: action_str = _('delete') QMessageBox.critical(self, _("Project Explorer"), _("<b>Unable to %s <i>%s</i></b>" "<br><br>Error message:<br>%s" ) % (action_str, fname, to_text_string(error))) return False
def delete_project(self): """ Delete the current project without deleting the files in the directory. """ if self.current_active_project: self.switch_to_plugin() path = self.current_active_project.root_path buttons = QMessageBox.Yes | QMessageBox.No answer = QMessageBox.warning( self, _("Delete"), _("Do you really want to delete <b>{filename}</b>?<br><br>" "<b>Note:</b> This action will only delete the project. " "Its files are going to be preserved on disk." ).format(filename=osp.basename(path)), buttons) if answer == QMessageBox.Yes: try: self.close_project() shutil.rmtree(osp.join(path, '.spyproject')) except EnvironmentError as error: QMessageBox.critical( self, _("Project Explorer"), _("<b>Unable to delete <i>{varpath}</i></b>" "<br><br>The error message was:<br>{error}" ).format(varpath=path, error=to_text_string(error)))
def call_cutout(self): self.spec_path = self.spectra_user_input.text() if self.spec_path == "": self.spectra_user_input.setStyleSheet("background-color: rgba(255, 0, 0, 128);") info = QMessageBox.information(self, "Error", "Please provide directory containing NIRSpec spectra files.") return else: self.spectra_user_input.setStyleSheet("") if not os.path.isdir(self.spec_path): self.spectra_user_input.setStyleSheet("background-color: rgba(255, 0, 0, 128);") info = QMessageBox.information(self, "Error", "Broken path:\n\n"+self.spec_path) return if self.CutoutTool is not None: if self.CutoutTool.isVisible(): info = QMessageBox.information(self, "Status", "Error: Cutout tool is still running.") self.CutoutTool.raise_() return else: self.CutoutTool = None try: self.CutoutTool = NIRSpecCutoutTool(self.parent.session, parent=self, spec_path=self.spec_path, TableGen=self) except Exception as e: info = QMessageBox.critical(self, "Error", "Cutout tool failed: "+str(e))
def finished(self, exit_code, exit_status): self.set_running_state(False) if not self.output: if self.error_output: QMessageBox.critical(self, _("Error"), self.error_output) print("pylint error:\n\n" + self.error_output, file=sys.stderr) return # Convention, Refactor, Warning, Error results = {'C:': [], 'R:': [], 'W:': [], 'E:': []} txt_module = '************* Module ' module = '' # Should not be needed - just in case something goes wrong for line in self.output.splitlines(): if line.startswith(txt_module): # New module module = line[len(txt_module):] continue # Supporting option include-ids: ('R3873:' instead of 'R:') if not re.match('^[CRWE]+([0-9]{4})?:', line): continue i1 = line.find(':') if i1 == -1: continue msg_id = line[:i1] i2 = line.find(':', i1+1) if i2 == -1: continue line_nb = line[i1+1:i2].strip() if not line_nb: continue line_nb = int(line_nb.split(',')[0]) message = line[i2+1:] item = (module, line_nb, message, msg_id) results[line[0]+':'].append(item) # Rate rate = None txt_rate = 'Your code has been rated at ' i_rate = self.output.find(txt_rate) if i_rate > 0: i_rate_end = self.output.find('/10', i_rate) if i_rate_end > 0: rate = self.output[i_rate+len(txt_rate):i_rate_end] # Previous run previous = '' if rate is not None: txt_prun = 'previous run: ' i_prun = self.output.find(txt_prun, i_rate_end) if i_prun > 0: i_prun_end = self.output.find('/10', i_prun) previous = self.output[i_prun+len(txt_prun):i_prun_end] filename = to_text_string(self.filecombo.currentText()) self.set_data(filename, (time.localtime(), rate, previous, results)) self.output = self.error_output + self.output self.show_data(justanalyzed=True)
def show_message(is_checked): if is_checked or not msg_if_enabled: if msg_warning is not None: QMessageBox.warning(self, self.get_name(), msg_warning, QMessageBox.Ok) if msg_info is not None: QMessageBox.information(self, self.get_name(), msg_info, QMessageBox.Ok)
def restart_message(self): """ Print a restart message when the client is connected to an external kernel """ message = _("Kernel process is either remote or unspecified. " "Cannot restart.") QMessageBox.information(self, "IPython", message)
def __init__(self, *args, **kwargs): super(VispyVolumeViewer, self).__init__(*args, **kwargs) if not OPENGL_INSTALLED: self.close() QMessageBox.critical(self, "Error", "The PyOpenGL package is required for the " "3D volume rendering viewer", buttons=QMessageBox.Ok)
def warn_box(self, message: str, title: str, one_option=False): """ Display a warning box """ box = QMessageBox() box.setText(message) box.setWindowTitle(title) box.setStyleSheet(get_stylesheet(self.viewer.get_theme())) if one_option: box.setStandardButtons(QMessageBox.Cancel) else: box.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) return box.exec_()
def __about_qt(self) -> None: """Open Qt about.""" QMessageBox.aboutQt(self)
def error(self, message): """An error occurred, closing the dialog box""" QMessageBox.critical(self, _("Array editor"), message) self.setAttribute(Qt.WA_DeleteOnClose) self.reject()
class Console(SpyderPluginWidget): """ Console widget """ CONF_SECTION = 'internal_console' focus_changed = Signal() redirect_stdio = Signal(bool) edit_goto = Signal(str, int, str) def __init__(self, parent=None, namespace=None, commands=[], message=None, exitfunc=None, profile=False, multithreaded=False): if PYQT5: SpyderPluginWidget.__init__(self, parent, main = parent) else: SpyderPluginWidget.__init__(self, parent) debug_print(" ..internal console: initializing") self.dialog_manager = DialogManager() # Shell light_background = self.get_option('light_background') self.shell = InternalShell(parent, namespace, commands, message, self.get_option('max_line_count'), self.get_plugin_font(), exitfunc, profile, multithreaded, light_background=light_background) self.shell.status.connect(lambda msg: self.show_message.emit(msg, 0)) self.shell.go_to_error.connect(self.go_to_error) self.shell.focus_changed.connect(lambda: self.focus_changed.emit()) # Redirecting some signals: self.shell.redirect_stdio.connect(lambda state: self.redirect_stdio.emit(state)) # Initialize plugin self.initialize_plugin() # Find/replace widget self.find_widget = FindReplace(self) self.find_widget.set_editor(self.shell) self.find_widget.hide() self.register_widget_shortcuts(self.find_widget) # Main layout layout = QVBoxLayout() layout.addWidget(self.shell) layout.addWidget(self.find_widget) self.setLayout(layout) # Parameters self.shell.toggle_wrap_mode(self.get_option('wrap')) # Accepting drops self.setAcceptDrops(True) # Traceback MessageBox self.msgbox_traceback= None self.error_traceback = "" #------ Private API -------------------------------------------------------- def set_historylog(self, historylog): """Bind historylog instance to this console Not used anymore since v2.0""" historylog.add_history(self.shell.history_filename) self.shell.append_to_history.connect(historylog.append_to_history) def set_help(self, help_plugin): """Bind help instance to this console""" self.shell.help = help_plugin #------ SpyderPluginWidget API --------------------------------------------- def get_plugin_title(self): """Return widget title""" return _('Internal console') def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self.shell def update_font(self): """Update font from Preferences""" font = self.get_plugin_font() self.shell.set_font(font) def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" self.dialog_manager.close_all() self.shell.exit_interpreter() return True def refresh_plugin(self): pass def get_plugin_actions(self): """Return a list of actions related to plugin""" quit_action = create_action(self, _("&Quit"), icon=ima.icon('exit'), tip=_("Quit"), triggered=self.quit) self.register_shortcut(quit_action, "_", "Quit", "Ctrl+Q") run_action = create_action(self, _("&Run..."), None, ima.icon('run_small'), _("Run a Python script"), triggered=self.run_script) environ_action = create_action(self, _("Environment variables..."), icon=ima.icon('environ'), tip=_("Show and edit environment variables" " (for current session)"), triggered=self.show_env) syspath_action = create_action(self, _("Show sys.path contents..."), icon=ima.icon('syspath'), tip=_("Show (read-only) sys.path"), triggered=self.show_syspath) buffer_action = create_action(self, _("Buffer..."), None, tip=_("Set maximum line count"), triggered=self.change_max_line_count) exteditor_action = create_action(self, _("External editor path..."), None, None, _("Set external editor executable path"), triggered=self.change_exteditor) wrap_action = create_action(self, _("Wrap lines"), toggled=self.toggle_wrap_mode) wrap_action.setChecked(self.get_option('wrap')) calltips_action = create_action(self, _("Display balloon tips"), toggled=self.toggle_calltips) calltips_action.setChecked(self.get_option('calltips')) codecompletion_action = create_action(self, _("Automatic code completion"), toggled=self.toggle_codecompletion) codecompletion_action.setChecked(self.get_option('codecompletion/auto')) codecompenter_action = create_action(self, _("Enter key selects completion"), toggled=self.toggle_codecompletion_enter) codecompenter_action.setChecked(self.get_option( 'codecompletion/enter_key')) option_menu = QMenu(_('Internal console settings'), self) option_menu.setIcon(ima.icon('tooloptions')) add_actions(option_menu, (buffer_action, wrap_action, calltips_action, codecompletion_action, codecompenter_action, exteditor_action)) plugin_actions = [None, run_action, environ_action, syspath_action, option_menu, None, quit_action] # Add actions to context menu add_actions(self.shell.menu, plugin_actions) return plugin_actions def register_plugin(self): """Register plugin in Spyder's main window""" self.focus_changed.connect(self.main.plugin_focus_changed) self.main.add_dockwidget(self) # Connecting the following signal once the dockwidget has been created: self.shell.exception_occurred.connect(self.exception_occurred) def exception_occurred(self, text, is_traceback): """Exception ocurred in the internal console. Show a QMessageBox or the internal console to warn the user""" # Skip errors without traceback if not is_traceback and self.msgbox_traceback is None: return if CONF.get('main', 'show_internal_console_if_traceback', False): self.dockwidget.show() self.dockwidget.raise_() else: if self.msgbox_traceback is None: self.msgbox_traceback = QMessageBox( QMessageBox.Critical, _('Error'), _("<b>Spyder has encountered a problem.</b><br>" "Sorry for the inconvenience." "<br><br>" "You can automatically submit this error to our Github " "issues tracker.<br><br>" "<i>Note:</i> You need a Github account for that."), QMessageBox.Ok, parent=self) self.submit_btn = self.msgbox_traceback.addButton( _('Submit to Github'), QMessageBox.YesRole) self.submit_btn.pressed.connect(self.press_submit_btn) self.msgbox_traceback.setWindowModality(Qt.NonModal) self.error_traceback = "" self.msgbox_traceback.show() self.msgbox_traceback.finished.connect(self.close_msg) self.msgbox_traceback.setDetailedText(' ') # open show details (iterate over all buttons and click it) for button in self.msgbox_traceback.buttons(): if (self.msgbox_traceback.buttonRole(button) == QMessageBox.ActionRole): button.click() break self.error_traceback += text self.msgbox_traceback.setDetailedText(self.error_traceback) def close_msg(self): self.msgbox_traceback = None def press_submit_btn(self): self.main.report_issue(self.error_traceback) self.msgbox_traceback = None #------ Public API --------------------------------------------------------- @Slot() def quit(self): """Quit mainwindow""" self.main.close() @Slot() def show_env(self): """Show environment variables""" self.dialog_manager.show(EnvDialog()) @Slot() def show_syspath(self): """Show sys.path""" editor = CollectionsEditor() editor.setup(sys.path, title="sys.path", readonly=True, width=600, icon=ima.icon('syspath')) self.dialog_manager.show(editor) @Slot() def run_script(self, filename=None, silent=False, set_focus=False, args=None): """Run a Python script""" if filename is None: self.shell.interpreter.restore_stds() filename, _selfilter = getopenfilename( self, _("Run Python script"), getcwd_or_home(), _("Python scripts")+" (*.py ; *.pyw ; *.ipy)") self.shell.interpreter.redirect_stds() if filename: os.chdir( osp.dirname(filename) ) filename = osp.basename(filename) else: return debug_print(args) filename = osp.abspath(filename) rbs = remove_backslashes command = "runfile('%s', args='%s')" % (rbs(filename), rbs(args)) if set_focus: self.shell.setFocus() if self.dockwidget and not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.raise_() self.shell.write(command+'\n') self.shell.run_command(command) def go_to_error(self, text): """Go to error if relevant""" match = get_error_match(to_text_string(text)) if match: fname, lnb = match.groups() self.edit_script(fname, int(lnb)) def edit_script(self, filename=None, goto=-1): """Edit script""" # Called from InternalShell if not hasattr(self, 'main') \ or not hasattr(self.main, 'editor'): self.shell.external_editor(filename, goto) return if filename is not None: self.edit_goto.emit(osp.abspath(filename), goto, '') def execute_lines(self, lines): """Execute lines and give focus to shell""" self.shell.execute_lines(to_text_string(lines)) self.shell.setFocus() @Slot() def change_max_line_count(self): "Change maximum line count""" mlc, valid = QInputDialog.getInt(self, _('Buffer'), _('Maximum line count'), self.get_option('max_line_count'), 0, 1000000) if valid: self.shell.setMaximumBlockCount(mlc) self.set_option('max_line_count', mlc) @Slot() def change_exteditor(self): """Change external editor path""" path, valid = QInputDialog.getText(self, _('External editor'), _('External editor executable path:'), QLineEdit.Normal, self.get_option('external_editor/path')) if valid: self.set_option('external_editor/path', to_text_string(path)) @Slot(bool) def toggle_wrap_mode(self, checked): """Toggle wrap mode""" self.shell.toggle_wrap_mode(checked) self.set_option('wrap', checked) @Slot(bool) def toggle_calltips(self, checked): """Toggle calltips""" self.shell.set_calltips(checked) self.set_option('calltips', checked) @Slot(bool) def toggle_codecompletion(self, checked): """Toggle automatic code completion""" self.shell.set_codecompletion_auto(checked) self.set_option('codecompletion/auto', checked) @Slot(bool) def toggle_codecompletion_enter(self, checked): """Toggle Enter key for code completion""" self.shell.set_codecompletion_enter(checked) self.set_option('codecompletion/enter_key', checked) #----Drag and drop def dragEnterEvent(self, event): """Reimplement Qt method Inform Qt about the types of data that the widget accepts""" source = event.mimeData() if source.hasUrls(): if mimedata2url(source): event.acceptProposedAction() else: event.ignore() elif source.hasText(): event.acceptProposedAction() def dropEvent(self, event): """Reimplement Qt method Unpack dropped data and handle it""" source = event.mimeData() if source.hasUrls(): pathlist = mimedata2url(source) self.shell.drop_pathlist(pathlist) elif source.hasText(): lines = to_text_string(source.text()) self.shell.set_cursor_position('eof') self.shell.execute_lines(lines) event.acceptProposedAction()
def critical_message(self, title, message): """Expose a QMessageBox.critical dialog to be used from the plugin.""" QMessageBox.critical(self, title, message)
def _dialog_create(self, title, text, info_text, callback, *, icon='Warning', buttons=[], modal=True, window=None): window = self._window if window is None else window widget = QMessageBox(window) widget.setWindowTitle(title) widget.setText(text) # icon is one of _QtDialog.supported_icon_names icon_id = getattr(QMessageBox, icon) widget.setIcon(icon_id) widget.setInformativeText(info_text) if not buttons: buttons = ["Ok"] button_ids = list() for button in buttons: # button is one of _QtDialog.supported_button_names button_id = getattr(QMessageBox, button) button_ids.append(button_id) standard_buttons = default_button = button_ids[0] for button_id in button_ids[1:]: standard_buttons |= button_id widget.setStandardButtons(standard_buttons) widget.setDefaultButton(default_button) @safe_event def func(button): button_id = widget.standardButton(button) for button_name in _QtDialog.supported_button_names: if button_id == getattr(QMessageBox, button_name): widget.setCursor(QCursor(Qt.WaitCursor)) try: callback(button_name) finally: widget.unsetCursor() break widget.buttonClicked.connect(func) return _QtDialogWidget(widget, modal)
def start(self, wdir=None, args=None, pythonpath=None): filename = to_text_string(self.filecombo.currentText()) if wdir is None: wdir = self._last_wdir if wdir is None: wdir = osp.basename(filename) if args is None: args = self._last_args if args is None: args = [] if pythonpath is None: pythonpath = self._last_pythonpath self._last_wdir = wdir self._last_args = args self._last_pythonpath = pythonpath self.datelabel.setText(_('Profiling, please wait...')) self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setWorkingDirectory(wdir) self.process.readyReadStandardOutput.connect(self.read_output) self.process.readyReadStandardError.connect( lambda: self.read_output(error=True)) self.process.finished.connect( lambda ec, es=QProcess.ExitStatus: self.finished(ec, es)) self.stop_button.clicked.connect(self.process.kill) if pythonpath is not None: env = [ to_text_string(_pth) for _pth in self.process.systemEnvironment() ] add_pathlist_to_PYTHONPATH(env, pythonpath) processEnvironment = QProcessEnvironment() for envItem in env: envName, separator, envValue = envItem.partition('=') processEnvironment.insert(envName, envValue) self.process.setProcessEnvironment(processEnvironment) self.output = '' self.error_output = '' p_args = ['-m', 'cProfile', '-o', self.DATAPATH] if os.name == 'nt': # On Windows, one has to replace backslashes by slashes to avoid # confusion with escape characters (otherwise, for example, '\t' # will be interpreted as a tabulation): p_args.append(osp.normpath(filename).replace(os.sep, '/')) else: p_args.append(filename) if args: p_args.extend(shell_split(args)) executable = sys.executable if executable.endswith("spyder.exe"): # py2exe distribution executable = "python.exe" self.process.start(executable, p_args) running = self.process.waitForStarted() self.set_running_state(running) if not running: QMessageBox.critical(self, _("Error"), _("Process failed to start"))
def createEditor(self, parent, option, index, object_explorer=False): """Overriding method createEditor""" val_type = index.sibling(index.row(), 1).data() self.sig_open_editor.emit() if index.column() < 3: return None if self.show_warning(index): answer = QMessageBox.warning( self.parent(), _("Warning"), _("Opening this variable can be slow\n\n" "Do you want to continue anyway?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.No: return None try: value = self.get_value(index) if value is None: return None except ImportError as msg: self.sig_editor_shown.emit() module = str(msg).split("'")[1] if module in ['pandas', 'numpy']: if module == 'numpy': val_type = 'array' else: val_type = 'dataframe, series' QMessageBox.critical( self.parent(), _("Error"), _("Spyder is unable to show the {val_type} or object " "you're trying to view because <tt>{module}</tt> was " "not installed alongside Spyder. Please install " "this package in your Spyder environment." "<br>").format(val_type=val_type, module=module)) return else: QMessageBox.critical( self.parent(), _("Error"), _("Spyder is unable to show the variable you're " "trying to view because the module " "<tt>{module}</tt> was not found in your " "Spyder environment. Please install " "this package in your Spyder environment." "<br>").format(module=module)) return except Exception as msg: QMessageBox.critical( self.parent(), _("Error"), _("Spyder was unable to retrieve the value of " "this variable from the console.<br><br>" "The error message was:<br>" "%s") % to_text_string(msg)) return key = index.model().get_key(index) readonly = (isinstance(value, (tuple, set)) or self.parent().readonly or not is_known_type(value)) # CollectionsEditor for a list, tuple, dict, etc. if isinstance(value, (list, set, tuple, dict)) and not object_explorer: from spyder.widgets.collectionseditor import CollectionsEditor editor = CollectionsEditor(parent=parent) editor.setup(value, key, icon=self.parent().windowIcon(), readonly=readonly) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # ArrayEditor for a Numpy array elif (isinstance(value, (ndarray, MaskedArray)) and ndarray is not FakeObject and not object_explorer): editor = ArrayEditor(parent=parent) if not editor.setup_and_check(value, title=key, readonly=readonly): return self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # ArrayEditor for an images elif (isinstance(value, Image) and ndarray is not FakeObject and Image is not FakeObject and not object_explorer): arr = array(value) editor = ArrayEditor(parent=parent) if not editor.setup_and_check(arr, title=key, readonly=readonly): return conv_func = lambda arr: Image.fromarray(arr, mode=value.mode) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly, conv=conv_func)) return None # DataFrameEditor for a pandas dataframe, series or index elif (isinstance(value, (DataFrame, Index, Series)) and DataFrame is not FakeObject and not object_explorer): editor = DataFrameEditor(parent=parent) if not editor.setup_and_check(value, title=key): return editor.dataModel.set_format(index.model().dataframe_format) editor.sig_option_changed.connect(self.change_option) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # QDateEdit and QDateTimeEdit for a dates or datetime respectively elif isinstance(value, datetime.date) and not object_explorer: if readonly: self.sig_editor_shown.emit() return None else: if isinstance(value, datetime.datetime): editor = QDateTimeEdit(value, parent=parent) # Needed to handle NaT values # See spyder-ide/spyder#8329 try: value.time() except ValueError: self.sig_editor_shown.emit() return None else: editor = QDateEdit(value, parent=parent) editor.setCalendarPopup(True) editor.setFont(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) self.sig_editor_shown.emit() return editor # TextEditor for a long string elif is_text_string(value) and len(value) > 40 and not object_explorer: te = TextEditor(None, parent=parent) if te.setup_and_check(value): editor = TextEditor(value, key, readonly=readonly, parent=parent) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # QLineEdit for an individual value (int, float, short string, etc) elif is_editable_type(value) and not object_explorer: if readonly: self.sig_editor_shown.emit() return None else: editor = QLineEdit(parent=parent) editor.setFont(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) editor.setAlignment(Qt.AlignLeft) # This is making Spyder crash because the QLineEdit that it's # been modified is removed and a new one is created after # evaluation. So the object on which this method is trying to # act doesn't exist anymore. # editor.returnPressed.connect(self.commitAndCloseEditor) self.sig_editor_shown.emit() return editor # ObjectExplorer for an arbitrary Python object else: show_callable_attributes = index.model().show_callable_attributes show_special_attributes = index.model().show_special_attributes dataframe_format = index.model().dataframe_format if show_callable_attributes is None: show_callable_attributes = False if show_special_attributes is None: show_special_attributes = False from spyder.plugins.variableexplorer.widgets.objectexplorer \ import ObjectExplorer editor = ObjectExplorer( value, name=key, parent=parent, show_callable_attributes=show_callable_attributes, show_special_attributes=show_special_attributes, dataframe_format=dataframe_format, readonly=readonly) editor.sig_option_changed.connect(self.change_option) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None
def exception_occurred(exc: Exception): if isinstance(exc, SegmentationLimitException): mess = QMessageBox() mess.setIcon(QMessageBox.Critical) mess.setText("During segmentation process algorithm meet limitations:\n" + "\n".join(exc.args)) mess.setWindowTitle("Segmentation limitations") mess.exec() return if isinstance(exc, RuntimeError) and exc.args[0].startswith( "Exception thrown in SimpleITK KittlerIllingworthThreshold" ): mess = QMessageBox() mess.setIcon(QMessageBox.Critical) mess.setText("Fail to apply Kittler Illingworth to current data\n" + exc.args[0].split("\n")[1]) mess.setWindowTitle("Segmentation limitations") mess.exec() return dial = ErrorDialog(exc, "Error during segmentation", f"{QApplication.instance().applicationName()}") dial.exec()
class PosAngCorr(SiriusMainWindow): """Main Class.""" def __init__(self, parent=None, prefix='', tl=None): """Class construc.""" super(PosAngCorr, self).__init__(parent) if not prefix: self._prefix = _VACA_PREFIX else: self._prefix = prefix self._tl = tl.upper() base_name = _PVName('TL-Glob:AP-PosAng') self.posang_prefix = base_name.substitute( prefix=self._prefix, sec=self._tl) self.setObjectName(self._tl+'App') self.setWindowTitle(self._tl + ' Position and Angle Correction Window') if self._tl == 'TS': self._is_chsept = False ch3_pv = _PV(self.posang_prefix.substitute(propty='CH3-Cte'), connection_timeout=1) if not ch3_pv.wait_for_connection(): self._is_chsept = True if tl == 'ts': corr_h = (Const.TS_CORRH_POSANG_CHSEPT if self._is_chsept else Const.TS_CORRH_POSANG_SEPTSEPT) corr_v = Const.TS_CORRV_POSANG elif tl == 'tb': corr_h = Const.TB_CORRH_POSANG corr_v = Const.TB_CORRV_POSANG self.corrs = dict() self.corrs['CH1'] = _PVName(corr_h[0]) self.corrs['CH2'] = _PVName(corr_h[1]) if len(corr_h) == 3: self.corrs['CH3'] = _PVName(corr_h[2]) self.corrs['CV1'] = _PVName(corr_v[0]) self.corrs['CV2'] = _PVName(corr_v[1]) if len(corr_v) == 4: self.corrs['CV3'] = _PVName(corr_v[2]) self.corrs['CV4'] = _PVName(corr_v[3]) self._just_need_update = False self._update_ref_action = False self._my_input_widgets = list() self._setupUi() self.setFocus(True) self.setFocusPolicy(Qt.StrongFocus) self._ask_message = QMessageBox(self) self._ask_message.setWindowTitle('Message') self._ask_message.setText( 'The '+self._tl+' PosAng IOC indicates reference needs to ' 'be updated! Do you want to update the reference?') self._ask_message.setStandardButtons(QMessageBox.No | QMessageBox.Yes) self._ask_message.setDefaultButton(QMessageBox.No) self.app = QApplication.instance() self.app.focusChanged.connect(self._spinbox_onfocus) def _setupUi(self): cwt = QWidget(self) self.setCentralWidget(cwt) # label lab = QLabel( '<h3>'+self._tl+' Position and Angle Correction</h3>', cwt) lab.setStyleSheet(""" min-height:1.55em; max-height: 1.55em; qproperty-alignment: 'AlignVCenter | AlignRight'; background-color: qlineargradient(spread:pad, x1:1, y1:0.0227273, x2:0, y2:0, stop:0 rgba(173, 190, 207, 255), stop:1 rgba(213, 213, 213, 255));""") # apply button self.pb_updateref = PyDMPushButton( self, 'Update Reference', pressValue=1, init_channel=self.posang_prefix.substitute( propty='SetNewRefKick-Cmd')) self.pb_updateref.setStyleSheet( 'min-height: 2.4em; max-height: 2.4em;') self.led_needrefupdt = SiriusLedAlert( self, self.posang_prefix.substitute(propty='NeedRefUpdate-Mon')) self.ch_needrefupdt = SiriusConnectionSignal( self.posang_prefix.substitute(propty='NeedRefUpdate-Mon')) self.ch_needrefupdt.new_value_signal[int].connect( self._handle_need_update_ref_led) self.led_needrefupdt.setStyleSheet( 'QLed{min-width: 1.29em; max-width: 1.29em;}') box_ref = QHBoxLayout() box_ref.setContentsMargins(0, 0, 0, 0) box_ref.addWidget(self.pb_updateref) box_ref.addWidget(self.led_needrefupdt) # delta setters self.hgbox = QGroupBox('Horizontal', self) self.hgbox.setLayout(self._setupDeltaControlLayout('x')) self.vgbox = QGroupBox('Vertical', self) self.vgbox.setLayout(self._setupDeltaControlLayout('y')) # correctors self.corrgbox = QGroupBox('Correctors', self) self.corrgbox.setLayout(self._setupCorrectorsLayout()) # status self.statgbox = QGroupBox('Correction Status', self) self.statgbox.setLayout(self._setupStatusLayout()) glay = QGridLayout(cwt) glay.setHorizontalSpacing(12) glay.setVerticalSpacing(12) glay.addWidget(lab, 0, 0, 1, 2) glay.addLayout(box_ref, 1, 0, 1, 2) glay.addWidget(self.hgbox, 2, 0) glay.addWidget(self.vgbox, 2, 1) glay.addWidget(self.corrgbox, 3, 0, 1, 2) glay.addWidget(self.statgbox, 4, 0, 1, 2) # menu act_settings = self.menuBar().addAction('Settings') _hlautil.connect_window(act_settings, CorrParamsDetailWindow, parent=self, tl=self._tl, prefix=self._prefix) # stlesheet self.setStyleSheet(""" PyDMSpinbox{ min-width: 5em; max-width: 5em; } PyDMLabel, PyDMSpinboxScrollbar{ min-width: 6em; max-width: 6em; } QPushButton{ min-width: 8em; } QLabel{ min-height: 1.35em; qproperty-alignment: AlignCenter; } """) def _setupDeltaControlLayout(self, axis=''): # pos label_pos = QLabel("<h4>Δ"+axis+"</h4>", self) sb_deltapos = PyDMSpinbox(self, self.posang_prefix.substitute( propty='DeltaPos'+axis.upper()+'-SP')) sb_deltapos.step_exponent = -2 sb_deltapos.update_step_size() sb_deltapos.showStepExponent = False lb_deltapos = PyDMLabel(self, self.posang_prefix.substitute( propty='DeltaPos'+axis.upper()+'-RB')) lb_deltapos.showUnits = True self._my_input_widgets.append(sb_deltapos) # ang label_ang = QLabel("<h4>Δ"+axis+"'</h4>", self) sb_deltaang = PyDMSpinbox(self, self.posang_prefix.substitute( propty='DeltaAng'+axis.upper()+'-SP')) sb_deltaang.step_exponent = -2 sb_deltaang.update_step_size() sb_deltaang.showStepExponent = False lb_deltaang = PyDMLabel(self, self.posang_prefix.substitute( propty='DeltaAng'+axis.upper()+'-RB')) lb_deltaang.showUnits = True self._my_input_widgets.append(sb_deltaang) lay = QGridLayout() lay.setVerticalSpacing(12) lay.setHorizontalSpacing(12) lay.addItem( QSpacerItem(10, 0, QSzPlcy.Expanding, QSzPlcy.Ignored), 0, 0) lay.addWidget(label_pos, 0, 1) lay.addWidget(sb_deltapos, 0, 2) lay.addWidget(lb_deltapos, 0, 3) lay.addWidget(label_ang, 1, 1) lay.addWidget(sb_deltaang, 1, 2) lay.addWidget(lb_deltaang, 1, 3) lay.addItem( QSpacerItem(10, 0, QSzPlcy.Expanding, QSzPlcy.Ignored), 0, 4) return lay def _setupCorrectorsLayout(self): lay = QGridLayout() lay.setVerticalSpacing(9) lay.setHorizontalSpacing(9) label_kicksp = QLabel('<h4>Kick-SP</h4>', self) label_kickrb = QLabel('<h4>Kick-RB</h4>', self) label_kickref = QLabel('<h4>RefKick-Mon</h4>', self) lay.addWidget(label_kicksp, 0, 2) lay.addWidget(label_kickrb, 0, 3) lay.addWidget(label_kickref, 0, 4) idx = 1 for corrid, corr in self.corrs.items(): pbt = QPushButton(qta.icon('fa5s.list-ul'), '', self) pbt.setObjectName('pbt') pbt.setStyleSheet(""" #pbt{ min-width:25px; max-width:25px; min-height:25px; max-height:25px; icon-size:20px;} """) if corr.dis == 'PU': _hlautil.connect_window( pbt, _PUDetailWindow, self, devname=corr) else: _hlautil.connect_window( pbt, _PSDetailWindow, self, psname=corr) lb_name = QLabel(corr, self) le_sp = PyDMSpinboxScrollbar( self, corr.substitute(prefix=self._prefix, propty='Kick-SP')) le_sp.spinbox.setAlignment(Qt.AlignCenter) le_sp.scrollbar.limitsFromPV = True lb_rb = PyDMLabel(self, corr.substitute( prefix=self._prefix, propty='Kick-RB')) lb_ref = PyDMLabel(self, self.posang_prefix.substitute( propty='RefKick'+corrid+'-Mon')) lay.addWidget(pbt, idx, 0, alignment=Qt.AlignTop) lay.addWidget( lb_name, idx, 1, alignment=Qt.AlignLeft | Qt.AlignTop) lay.addWidget(le_sp, idx, 2, alignment=Qt.AlignTop) lay.addWidget(lb_rb, idx, 3, alignment=Qt.AlignTop) lay.addWidget(lb_ref, idx, 4, alignment=Qt.AlignTop) idx += 1 if self._tl == 'TB': pref = self._prefix + ('-' if self._prefix else '') lay.addItem(QSpacerItem(0, 8, QSzPlcy.Ignored, QSzPlcy.Fixed)) label_voltsp = QLabel('<h4>Amplitude-SP</h4>', self) label_voltrb = QLabel('<h4>Amplitude-RB</h4>', self) lay.addWidget(label_voltsp, idx+2, 2) lay.addWidget(label_voltrb, idx+2, 3) lb_kly2_name = QLabel('Klystron 2', self) le_kly2_sp = PyDMSpinboxScrollbar( self, pref+'LA-RF:LLRF:KLY2:SET_AMP') le_kly2_sp.spinbox.precisionFromPV = False le_kly2_sp.spinbox.precision = 2 le_kly2_sp.spinbox.setAlignment(Qt.AlignCenter) le_kly2_sp.scrollbar.limitsFromPV = True lb_kly2_rb = PyDMLabel(self, pref+'LA-RF:LLRF:KLY2:GET_AMP') lb_kly2_rb.precisionFromPV = False lb_kly2_rb.precision = 2 lay.addWidget(lb_kly2_name, idx+3, 1, alignment=Qt.AlignLeft | Qt.AlignTop) lay.addWidget(le_kly2_sp, idx+3, 2, alignment=Qt.AlignTop) lay.addWidget(lb_kly2_rb, idx+3, 3, alignment=Qt.AlignTop) self._kckr_name = _PVName('BO-01D:PU-InjKckr') else: self._kckr_name = _PVName('SI-01SA:PU-InjNLKckr') label_voltsp = QLabel('<h4>Voltage-SP</h4>', self) label_voltrb = QLabel('<h4>Voltage-RB</h4>', self) lay.addWidget(label_voltsp, idx+4, 2) lay.addWidget(label_voltrb, idx+4, 3) lay.addItem(QSpacerItem(0, 8, QSzPlcy.Ignored, QSzPlcy.Fixed)) pb_kckr = QPushButton(qta.icon('fa5s.list-ul'), '', self) pb_kckr.setObjectName('pb') pb_kckr.setStyleSheet(""" #pb{ min-width:25px; max-width:25px; min-height:25px; max-height:25px; icon-size:20px;} """) lb_kckr_name = QLabel(self._kckr_name, self) _hlautil.connect_window( pb_kckr, _PUDetailWindow, self, devname=self._kckr_name) lb_kckr_sp = PyDMSpinboxScrollbar( self, self._kckr_name.substitute( prefix=self._prefix, propty='Voltage-SP')) lb_kckr_sp.scrollbar.limitsFromPV = True lb_kckr_rb = PyDMLabel(self, self._kckr_name.substitute( prefix=self._prefix, propty='Voltage-RB')) lay.addWidget(pb_kckr, idx+5, 0, alignment=Qt.AlignTop) lay.addWidget( lb_kckr_name, idx+5, 1, alignment=Qt.AlignLeft | Qt.AlignTop) lay.addWidget(lb_kckr_sp, idx+5, 2, alignment=Qt.AlignTop) lay.addWidget(lb_kckr_rb, idx+5, 3, alignment=Qt.AlignTop) return lay def _setupStatusLayout(self): self.log = PyDMLogLabel( self, self.posang_prefix.substitute(propty='Log-Mon')) self.lb_sts0 = QLabel(Const.STATUSLABELS[0], self) self.led_sts0 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=0) self.lb_sts1 = QLabel(Const.STATUSLABELS[1], self) self.led_sts1 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=1) self.lb_sts2 = QLabel(Const.STATUSLABELS[2], self) self.led_sts2 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=2) self.lb_sts3 = QLabel(Const.STATUSLABELS[3], self) self.led_sts3 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=3) self.pb_config = PyDMPushButton( self, label='Config Correctors', pressValue=1, init_channel=self.posang_prefix.substitute(propty='ConfigPS-Cmd')) lay = QGridLayout() lay.setVerticalSpacing(12) lay.setHorizontalSpacing(12) lay.addWidget(self.log, 0, 0, 6, 1) lay.addWidget(self.lb_sts0, 1, 2) lay.addWidget(self.led_sts0, 1, 1) lay.addWidget(self.lb_sts1, 2, 2) lay.addWidget(self.led_sts1, 2, 1) lay.addWidget(self.lb_sts2, 3, 2) lay.addWidget(self.led_sts2, 3, 1) lay.addWidget(self.lb_sts3, 4, 2) lay.addWidget(self.led_sts3, 4, 1) lay.addWidget(self.pb_config, 5, 1, 1, 2) if self._tl == 'TS': self.led_corrtype = PyDMLedMultiChannel( self, {self.posang_prefix.substitute( propty='CH1-Cte'): self.corrs['CH1']}) self.lb_corrtype = QLabel( 'Control ' + ('CH-Sept' if self._is_chsept else 'Sept-Sept')) lay.addWidget(self.led_corrtype, 0, 1) lay.addWidget(self.lb_corrtype, 0, 2) return lay def _set_correctors_channels(self, corrs): self.centralwidget.pushButton_CH1.setText(corrs[0]) _hlautil.connect_window( self.centralwidget.pushButton_CH1, _PSDetailWindow, self, psname=corrs[0]) self.centralwidget.PyDMLabel_KickRBCH1.channel = ( corrs[0].substitute(prefix=self._prefix, propty='Kick-RB')) self.centralwidget.pushButton_CH2.setText(corrs[1]) if corrs[1].dis == 'PU': _hlautil.connect_window( self.centralwidget.pushButton_CH2, _PUDetailWindow, self, devname=corrs[1]) else: _hlautil.connect_window( self.centralwidget.pushButton_CH2, _PSDetailWindow, self, psname=corrs[1]) self.centralwidget.PyDMLabel_KickRBCH2.channel = ( corrs[1].substitute(prefix=self._prefix, propty='Kick-RB')) self.centralwidget.pushButton_CV1.setText(corrs[2]) _hlautil.connect_window( self.centralwidget.pushButton_CV1, _PSDetailWindow, self, psname=corrs[2]) self.centralwidget.PyDMLabel_KickRBCV1.channel = ( corrs[2].substitute(prefix=self._prefix, propty='Kick-RB')) self.centralwidget.pushButton_CV2.setText(corrs[3]) _hlautil.connect_window( self.centralwidget.pushButton_CV2, _PSDetailWindow, self, psname=corrs[3]) self.centralwidget.PyDMLabel_KickRBCV2.channel = ( corrs[3].substitute(prefix=self._prefix, propty='Kick-RB')) def _handle_need_update_ref_led(self, value): self._just_need_update = bool(value) def _spinbox_onfocus(self, old_focus, new_focus): if not self._update_ref_action and not self._just_need_update: return if self.led_needrefupdt.value != 0: if new_focus in self._my_input_widgets and self._just_need_update: ans = self._ask_message.exec_() if ans == QMessageBox.No: self._update_ref_action = False else: self._update_ref_action = True self.pb_updateref.sendValue() self._just_need_update = False
def ask_before_close(self): reply = QMessageBox.question(self, self.presenter.ASK_BEFORE_CLOSE_TITLE, self.presenter.ASK_BEFORE_CLOSE_MESSAGE, QMessageBox.Yes, QMessageBox.No) return True if reply == QMessageBox.Yes else False
def create_process(self): self.shell.clear() self.process = QProcess(self) if self.merge_output_channels: self.process.setProcessChannelMode(QProcess.MergedChannels) else: self.process.setProcessChannelMode(QProcess.SeparateChannels) self.shell.wait_for_ready_read.connect( lambda: self.process.waitForReadyRead(250)) # Working directory if self.wdir is not None: self.process.setWorkingDirectory(self.wdir) #-------------------------Python specific------------------------------ # Python arguments p_args = ['-u'] if DEBUG >= 3: p_args += ['-v'] p_args += get_python_args(self.fname, self.python_args, self.interact_action.isChecked(), self.debug_action.isChecked(), self.arguments) env = [to_text_string(_path) for _path in self.process.systemEnvironment()] if self.pythonstartup: env.append('PYTHONSTARTUP=%s' % self.pythonstartup) #-------------------------Python specific------------------------------- # Post mortem debugging if self.post_mortem_action.isChecked(): env.append('SPYDER_EXCEPTHOOK=True') # Set standard input/output encoding for Python consoles # See http://stackoverflow.com/q/26312400/438386, specifically # the comments of Martijn Pieters env.append('PYTHONIOENCODING=UTF-8') # Monitor if self.monitor_enabled: env.append('SPYDER_SHELL_ID=%s' % id(self)) from spyder.widgets.externalshell import introspection introspection_server = introspection.start_introspection_server() introspection_server.register(self) notification_server = introspection.start_notification_server() self.notification_thread = notification_server.register(self) self.notification_thread.sig_pdb.connect( lambda fname, lineno: self.sig_pdb.emit(fname, lineno)) self.notification_thread.open_file.connect( lambda fname, lineno: self.open_file.emit(fname, lineno)) if self.namespacebrowser is not None: self.configure_namespacebrowser() env.append('SPYDER_I_PORT=%d' % introspection_server.port) env.append('SPYDER_N_PORT=%d' % notification_server.port) # External modules options env.append('ETS_TOOLKIT=%s' % self.ets_backend) if self.mpl_backend is not None: backends = {0: 'Automatic', 1: 'None', 2: 'TkAgg'} env.append('SPY_MPL_BACKEND=%s' % backends[self.mpl_backend]) if self.qt_api: env.append('QT_API=%s' % self.qt_api) env.append('COLORIZE_SYS_STDERR=%s' % self.colorize_sys_stderr) # # Socket-based alternative (see input hook in sitecustomize.py): # if self.install_qt_inputhook: # from PyQt4.QtNetwork import QLocalServer # self.local_server = QLocalServer() # self.local_server.listen(str(id(self))) # User Module Deleter if self.is_interpreter: env.append('UMR_ENABLED=%r' % self.umr_enabled) env.append('UMR_NAMELIST=%s' % ','.join(self.umr_namelist)) env.append('UMR_VERBOSE=%r' % self.umr_verbose) env.append('MATPLOTLIB_ION=True') else: if self.interact: env.append('MATPLOTLIB_ION=True') else: env.append('MATPLOTLIB_ION=False') # External interpreter env.append('EXTERNAL_INTERPRETER=%r' % self.external_interpreter) # Add sitecustomize path to path list pathlist = [] spy_path = get_module_source_path('spyder') sc_path = osp.join(spy_path, 'utils', 'site') pathlist.append(sc_path) # Adding Spyder path pathlist += self.path # Adding path list to PYTHONPATH environment variable add_pathlist_to_PYTHONPATH(env, pathlist) #-------------------------Python specific------------------------------ self.process.readyReadStandardOutput.connect(self.write_output) self.process.readyReadStandardError.connect(self.write_error) self.process.finished.connect(lambda ec, es=QProcess.ExitStatus: self.finished(ec, es)) self.sig_finished.connect(self.dialog_manager.close_all) self.terminate_button.clicked.connect(self.process.terminate) self.kill_button.clicked.connect(self.process.kill) #-------------------------Python specific------------------------------ # Fixes for our Mac app: # 1. PYTHONPATH and PYTHONHOME are set while bootstrapping the app, # but their values are messing sys.path for external interpreters # (e.g. EPD) so we need to remove them from the environment. # 2. Set PYTHONPATH again but without grabbing entries defined in the # environment (Fixes Issue 1321) # 3. Remove PYTHONOPTIMIZE from env so that we can have assert # statements working with our interpreters (See Issue 1281) if running_in_mac_app(): if MAC_APP_NAME not in self.pythonexecutable: env = [p for p in env if not (p.startswith('PYTHONPATH') or \ p.startswith('PYTHONHOME'))] # 1. add_pathlist_to_PYTHONPATH(env, pathlist, drop_env=True) # 2. env = [p for p in env if not p.startswith('PYTHONOPTIMIZE')] # 3. processEnvironment = QProcessEnvironment() for envItem in env: envName, separator, envValue = envItem.partition('=') processEnvironment.insert(envName, envValue) self.process.setProcessEnvironment(processEnvironment) self.process.start(self.pythonexecutable, p_args) #-------------------------Python specific------------------------------ running = self.process.waitForStarted(3000) self.set_running_state(running) if not running: QMessageBox.critical(self, _("Error"), _("A Python console failed to start!")) else: self.shell.setFocus() self.started.emit() return self.process
def show_help(self): """Show help message.""" # logger.warning(self.HELP_BODY) QMessageBox.information(self, self.HELP_HEAD, self.HELP_BODY)
def _show_compatibility_message(self, message): """Show a compatibility message.""" messageBox = QMessageBox(self) messageBox.setWindowModality(Qt.NonModal) messageBox.setAttribute(Qt.WA_DeleteOnClose) messageBox.setWindowTitle('Compatibility Check') messageBox.setText(message) messageBox.setStandardButtons(QMessageBox.Ok) messageBox.show()
def restart_failed_realizations(self): msg = QMessageBox(self) msg.setIcon(QMessageBox.Information) msg.setText( "Note that workflows will only be executed on the restarted realizations and that this might have unexpected consequences." ) msg.setWindowTitle("Restart Failed Realizations") msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) result = msg.exec_() if result == QMessageBox.Ok: self.restart_button.setVisible(False) self.kill_button.setVisible(True) self.done_button.setVisible(False) active_realizations = self.create_mask_from_failed_realizations() self._simulations_argments[ 'active_realizations'] = active_realizations self._simulations_argments[ 'prev_successful_realizations'] = self._simulations_argments.get( 'prev_successful_realizations', 0) self._simulations_argments[ 'prev_successful_realizations'] += self.count_successful_realizations( ) self.startSimulation()
def createEditor(self, parent, option, index): """Overriding method createEditor""" if self.show_warning(index): answer = QMessageBox.warning( self.parent(), _("Warning"), _("Opening this variable can be slow\n\n" "Do you want to continue anyway?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.No: return None try: value = self.get_value(index) try: self.old_obj = value.copy() except AttributeError: self.old_obj = copy.deepcopy(value) if value is None: return None except Exception as msg: QMessageBox.critical( self.parent(), _("Error"), _("Spyder was unable to retrieve the value of " "this variable from the console.<br><br>" "The error message was:<br>" "<i>%s</i>") % to_text_string(msg)) return self.current_index = index key = index.model().get_key(index).obj_name readonly = (isinstance(value, (tuple, set)) or self.parent().readonly or not is_known_type(value)) # CollectionsEditor for a list, tuple, dict, etc. if isinstance(value, (list, set, tuple, dict)): from spyder.widgets.collectionseditor import CollectionsEditor editor = CollectionsEditor(parent=parent) editor.setup(value, key, icon=self.parent().windowIcon(), readonly=readonly) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # ArrayEditor for a Numpy array elif (isinstance(value, (ndarray, MaskedArray)) and ndarray is not FakeObject): editor = ArrayEditor(parent=parent) if not editor.setup_and_check(value, title=key, readonly=readonly): return self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # ArrayEditor for an images elif (isinstance(value, Image) and ndarray is not FakeObject and Image is not FakeObject): arr = array(value) editor = ArrayEditor(parent=parent) if not editor.setup_and_check(arr, title=key, readonly=readonly): return conv_func = lambda arr: Image.fromarray(arr, mode=value.mode) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly, conv=conv_func)) return None # DataFrameEditor for a pandas dataframe, series or index elif (isinstance(value, (DataFrame, Index, Series)) and DataFrame is not FakeObject): editor = DataFrameEditor(parent=parent) if not editor.setup_and_check(value, title=key): return editor.dataModel.set_format(index.model().dataframe_format) editor.sig_option_changed.connect(self.change_option) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # QDateEdit and QDateTimeEdit for a dates or datetime respectively elif isinstance(value, datetime.date): if readonly: return None else: if isinstance(value, datetime.datetime): editor = QDateTimeEdit(value, parent=parent) else: editor = QDateEdit(value, parent=parent) editor.setCalendarPopup(True) editor.setFont(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) return editor # TextEditor for a long string elif is_text_string(value) and len(value) > 40: te = TextEditor(None, parent=parent) if te.setup_and_check(value): editor = TextEditor(value, key, readonly=readonly, parent=parent) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) return None # QLineEdit for an individual value (int, float, short string, etc) elif is_editable_type(value): if readonly: return None else: editor = QLineEdit(parent=parent) editor.setFont(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) editor.setAlignment(Qt.AlignLeft) # This is making Spyder crash because the QLineEdit that it's # been modified is removed and a new one is created after # evaluation. So the object on which this method is trying to # act doesn't exist anymore. # editor.returnPressed.connect(self.commitAndCloseEditor) return editor # An arbitrary Python object. # Since we are already in the Object Explorer no editor is needed else: return None
def pasteCellFromClipboard(self): """Paste text from clipboard into the table. :return: *True* in case of success, *False* if pasting data failed. """ selected_idx = self.table.selectedIndexes() if len(selected_idx) != 1: msgBox = QMessageBox(parent=self.table) msgBox.setText(_PASTE1) msgBox.exec_() return False data_model = self.table.model() selected_row = selected_idx[0].row() selected_col = selected_idx[0].column() qapp = QApplication.instance() clipboard_text = qapp.clipboard().text() table_data = _parseTextAsTable(clipboard_text) protected_cells = 0 out_of_range_cells = 0 # paste table data into cells, using selected cell as origin for row_offset in range(len(table_data)): for col_offset in range(len(table_data[row_offset])): target_row = selected_row + row_offset target_col = selected_col + col_offset if target_row >= data_model.rowCount() or\ target_col >= data_model.columnCount(): out_of_range_cells += 1 continue index = data_model.index(target_row, target_col) flags = data_model.flags(index) # ignore empty strings if table_data[row_offset][col_offset] != "": if not flags & Qt.ItemIsEditable: protected_cells += 1 continue data_model.setData(index, table_data[row_offset][col_offset]) # item.setText(table_data[row_offset][col_offset]) if protected_cells or out_of_range_cells: msgBox = QMessageBox(parent=self.table) msgBox.setText(_PASTEFAIL) msgBox.exec_() return False return True
def remove_rows(self, rows): """ We just hide the row to delete things to prevent refreshing the window and changing which items have been expanded Parameters ---------- rows : List[int] the trace on the data/form block form = [ ['Geometry', None, [ ('NodeID', 0, []), ('ElementID', 1, []), ('PropertyID', 2, []), ('MaterialID', 3, []), ('E', 4, []), ('Element Checks', None, [ ('ElementDim', 5, []), ('Min Edge Length', 6, []), ('Min Interior Angle', 7, []), ('Max Interior Angle', 8, [])], ),], ], ] # delete Geometry data[0] = ('Geometry', None, [...]) >>> remove_rows([0]) # delete MaterialID data[0][3] = ('MaterialID', 3, []) >>> remove_rows([0, 3]) # delete ElementChecks data[0][5] = ('Element Checks', None, [...]) >>> remove_rows([0, 5]) # delete Min Edge Length data[0][5][1] = ('Min Edge Length', 6, []) >>> remove_rows([0, 5, 1]) """ # find the row the user wants to delete data = self.data for row in rows[:-1]: data = data[row][2] # we got our data block # now we need to get 1+ results last_row = rows[-1] cases_to_delete = get_many_cases(data[last_row]) cases_to_delete = list(set(cases_to_delete) - self.cases_deleted) cases_to_delete.sort() if len(cases_to_delete) == 0: # can this happen? # this happens when you cleared out a data block by # deleting to entries, but not the parent # # we'll just hide the row now msg = '' return elif len(cases_to_delete) == 1: msg = 'Are you sure you want to delete 1 result case load_case=%s' % cases_to_delete[ 0] else: msg = 'Are you sure you want to delete %s result cases %s' % ( len(cases_to_delete), str(cases_to_delete)) if msg: widget = QMessageBox() title = 'Delete Cases' result = QMessageBox.question(widget, title, msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if result != QMessageBox.Yes: return self.cases_deleted.update(set(cases_to_delete)) self.on_delete_parent_cases(cases_to_delete) # hide the line the user wants to delete row = rows[-1] indexes = self.selectedIndexes() self.setRowHidden(row, indexes[-1].parent(), True) self.update()
def start(self, fname, wdir=None, args='', interact=False, debug=False, python=True, python_args='', post_mortem=True): """ Start new console fname: string: filename of script to run None: open an interpreter wdir: working directory args: command line options of the Python script interact: inspect script interactively after its execution debug: run pdb python: True: Python interpreter, False: terminal python_args: additionnal Python interpreter command line options (option "-u" is mandatory, see widgets.externalshell package) """ # Note: fname is None <=> Python interpreter if fname is not None and not is_text_string(fname): fname = to_text_string(fname) if wdir is not None and not is_text_string(wdir): wdir = to_text_string(wdir) if fname is not None and fname in self.filenames: index = self.filenames.index(fname) if self.get_option('single_tab'): old_shell = self.shellwidgets[index] if old_shell.is_running(): runconfig = get_run_configuration(fname) if runconfig is None or runconfig.show_kill_warning: answer = QMessageBox.question(self, self.get_plugin_title(), _("%s is already running in a separate process.\n" "Do you want to kill the process before starting " "a new one?") % osp.basename(fname), QMessageBox.Yes | QMessageBox.Cancel) else: answer = QMessageBox.Yes if answer == QMessageBox.Yes: old_shell.process.kill() old_shell.process.waitForFinished() else: return self.close_console(index) else: index = self.tabwidget.count() # Creating a new external shell pythonpath = self.main.get_spyder_pythonpath() light_background = self.get_option('light_background') show_elapsed_time = self.get_option('show_elapsed_time') if python: if CONF.get('main_interpreter', 'default'): pythonexecutable = get_python_executable() external_interpreter = False else: pythonexecutable = CONF.get('main_interpreter', 'executable') external_interpreter = True if self.get_option('pythonstartup/default'): pythonstartup = None else: pythonstartup = self.get_option('pythonstartup', None) monitor_enabled = self.get_option('monitor/enabled') mpl_backend = self.get_option('matplotlib/backend/value') ets_backend = self.get_option('ets_backend') qt_api = self.get_option('qt/api') if qt_api not in ('pyqt', 'pyside', 'pyqt5'): qt_api = None merge_output_channels = self.get_option('merge_output_channels') colorize_sys_stderr = self.get_option('colorize_sys_stderr') umr_enabled = CONF.get('main_interpreter', 'umr/enabled') umr_namelist = CONF.get('main_interpreter', 'umr/namelist') umr_verbose = CONF.get('main_interpreter', 'umr/verbose') sa_settings = None shellwidget = ExternalPythonShell(self, fname, wdir, interact, debug, post_mortem=post_mortem, path=pythonpath, python_args=python_args, arguments=args, stand_alone=sa_settings, pythonstartup=pythonstartup, pythonexecutable=pythonexecutable, external_interpreter=external_interpreter, umr_enabled=umr_enabled, umr_namelist=umr_namelist, umr_verbose=umr_verbose, ets_backend=ets_backend, monitor_enabled=monitor_enabled, mpl_backend=mpl_backend, qt_api=qt_api, merge_output_channels=merge_output_channels, colorize_sys_stderr=colorize_sys_stderr, light_background=light_background, menu_actions=self.menu_actions, show_buttons_inside=False, show_elapsed_time=show_elapsed_time) shellwidget.sig_pdb.connect( lambda fname, lineno, shellwidget=shellwidget: self.pdb_has_stopped(fname, lineno, shellwidget)) self.register_widget_shortcuts(shellwidget.shell) else: if os.name == 'posix': cmd = 'gnome-terminal' args = [] if programs.is_program_installed(cmd): if wdir: args.extend(['--working-directory=%s' % wdir]) programs.run_program(cmd, args) return cmd = 'konsole' if programs.is_program_installed(cmd): if wdir: args.extend(['--workdir', wdir]) programs.run_program(cmd, args) return shellwidget = ExternalSystemShell(self, wdir, path=pythonpath, light_background=light_background, menu_actions=self.menu_actions, show_buttons_inside=False, show_elapsed_time=show_elapsed_time) # Code completion / calltips shellwidget.shell.setMaximumBlockCount( self.get_option('max_line_count') ) shellwidget.shell.set_font( self.get_plugin_font() ) shellwidget.shell.toggle_wrap_mode( self.get_option('wrap') ) shellwidget.shell.set_calltips( self.get_option('calltips') ) shellwidget.shell.set_codecompletion_auto( self.get_option('codecompletion/auto') ) shellwidget.shell.set_codecompletion_case( self.get_option('codecompletion/case_sensitive') ) shellwidget.shell.set_codecompletion_enter( self.get_option('codecompletion/enter_key') ) if python and self.help is not None: shellwidget.shell.set_help(self.help) shellwidget.shell.set_help_enabled( CONF.get('help', 'connect/python_console')) if self.historylog is not None: self.historylog.add_history(shellwidget.shell.history_filename) shellwidget.shell.append_to_history.connect( self.historylog.append_to_history) shellwidget.shell.go_to_error.connect(self.go_to_error) shellwidget.shell.focus_changed.connect( lambda: self.focus_changed.emit()) if python: if self.main.editor is not None: shellwidget.open_file.connect(self.open_file_in_spyder) if fname is None: self.python_count += 1 tab_name = "Python %d" % self.python_count tab_icon1 = ima.icon('python') tab_icon2 = ima.icon('python_t') else: tab_name = osp.basename(fname) tab_icon1 = ima.icon('run') tab_icon2 = ima.icon('terminated') else: fname = id(shellwidget) if os.name == 'nt': tab_name = _("Command Window") else: tab_name = _("Terminal") self.terminal_count += 1 tab_name += (" %d" % self.terminal_count) tab_icon1 = ima.icon('cmdprompt') tab_icon2 = ima.icon('cmdprompt_t') self.shellwidgets.insert(index, shellwidget) self.filenames.insert(index, fname) self.icons.insert(index, (tab_icon1, tab_icon2)) if index is None: index = self.tabwidget.addTab(shellwidget, tab_name) else: self.tabwidget.insertTab(index, shellwidget, tab_name) shellwidget.started.connect( lambda sid=id(shellwidget): self.process_started(sid)) shellwidget.sig_finished.connect( lambda sid=id(shellwidget): self.process_finished(sid)) self.find_widget.set_editor(shellwidget.shell) self.tabwidget.setTabToolTip(index, fname if wdir is None else wdir) self.tabwidget.setCurrentIndex(index) if self.dockwidget and not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.raise_() shellwidget.set_icontext_visible(self.get_option('show_icontext')) # Start process and give focus to console shellwidget.start_shell()
def errormessage(self, message): msg = QMessageBox() msg.setText(str(message)) msg.setStandardButtons(QMessageBox.Ok) msg.exec_()
def add_path(self, directory=None): """ Add path to list widget. If `directory` is provided, the folder dialog is overriden. """ if directory is None: self.redirect_stdio.emit(False) directory = getexistingdirectory(self, _("Select directory"), self.last_path) self.redirect_stdio.emit(True) if PY2: is_unicode = False try: directory.decode('ascii') except (UnicodeEncodeError, UnicodeDecodeError): is_unicode = True if is_unicode: QMessageBox.warning( self, _("Add path"), _("You are using Python 2 and the selected path has " "Unicode characters." "<br> " "Therefore, this path will not be added."), QMessageBox.Ok) return directory = osp.abspath(directory) self.last_path = directory if directory in self.get_path_dict(): item = self.listwidget.findItems(directory, Qt.MatchExactly)[0] item.setCheckState(Qt.Checked) answer = QMessageBox.question( self, _("Add path"), _("This directory is already included in the list." "<br> " "Do you want to move it to the top of it?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: item = self.listwidget.takeItem(self.listwidget.row(item)) self.listwidget.insertItem(0, item) self.listwidget.setCurrentRow(0) else: if self.check_path(directory): item = self._create_item(directory) self.listwidget.insertItem(0, item) self.listwidget.setCurrentRow(0) else: answer = QMessageBox.warning( self, _("Add path"), _("This directory cannot be added to the path!" "<br><br>" "If you want to set a different Python interpreter, " "please go to <tt>Preferences > Main interpreter</tt>" "."), QMessageBox.Ok) self.refresh()
def show_mongo_query_help(self): "Launch a Message Box with instructions for custom queries." msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText( "For advanced search capability, enter a valid Mongo query.") msg.setInformativeText(""" Examples: {'plan_name': 'scan'} {'proposal': 1234}, {'$and': ['proposal': 1234, 'sample_name': 'Ni']} """) msg.setWindowTitle("Custom Mongo Query") msg.setStandardButtons(QMessageBox.Ok) msg.exec_()
def inform_user_not_possible(): return QMessageBox().information(None, "That action is not possible!", "You cannot exit workbench whilst it is saving or loading a " "project")
def show_warning_message(self, msg, problems): """Show warning message.""" text = msg + '\n\nVerify PVs:\n' for problem in problems: text += problem + '\n' mb = QMessageBox() mb.setMinimumSize(300, 150) mb.setWindowTitle('Message') mb.setIcon(QMessageBox.Warning) mb.setText(text) mb.exec()
def set_state(self, state): """ Populate the UI elements with the data from the given state. @param state: Transmission object """ popup_warning = "" # Beam finder if state.x_position is not None and state.y_position is not None: self._content.x_pos_edit.setText(str("%6.4f" % state.x_position)) self._content.y_pos_edit.setText(str("%6.4f" % state.y_position)) self._content.use_beam_finder_checkbox.setChecked(state.use_finder) self._content.beam_data_file_edit.setText(state.beam_file) self._content.beam_radius_edit.setText(str(state.beam_radius)) if not self._settings.debug and not self._settings.advanced and not state.use_direct_beam: # Warn the user if we're about to set an option that is not seen! popup_warning += "The reduction you are loading has advanced options for finding the beam center.\n" popup_warning += "Use the advanced interface to see all option. Those options will now be skipped." state.use_direct_beam = True self._content.direct_beam.setChecked(state.use_direct_beam) self._content.scattering_data.setChecked(not state.use_direct_beam) self._content.beam_radius_edit.setEnabled(not state.use_direct_beam) self._use_beam_finder_changed(state.use_finder) # Sensitivity self._content.sensitivity_file_edit.setText(state.sensitivity_data) self._content.sensitivity_chk.setChecked(state.sensitivity_corr) self._sensitivity_clicked(state.sensitivity_corr) self._content.min_sensitivity_edit.setText(str(state.min_sensitivity)) self._content.max_sensitivity_edit.setText(str(state.max_sensitivity)) if not self._use_sample_dc: self._content.sensitivity_dark_file_edit.setText( state.sensitivity_dark) if not self._settings.debug and not self._settings.advanced and not state.use_sample_beam_center: # Warn the user if we're about to set an option that is not seen! popup_warning += "The reduction you are loading has advanced options for the flood field beam center.\n" popup_warning += "Use the advanced interface to see all option. Those options will now be skipped." state.use_sample_beam_center = True self._content.use_sample_center_checkbox.setChecked( state.use_sample_beam_center) self._content.x_pos_edit_2.setText( str("%6.4f" % state.flood_x_position)) self._content.y_pos_edit_2.setText( str("%6.4f" % state.flood_y_position)) self._content.use_beam_finder_checkbox_2.setChecked( state.flood_use_finder) self._content.beam_data_file_edit_2.setText(state.flood_beam_file) self._content.beam_radius_edit_2.setText(str(state.flood_beam_radius)) self._content.direct_beam_2.setChecked(state.flood_use_direct_beam) self._content.scattering_data_2.setChecked( not state.flood_use_direct_beam) self._content.beam_radius_edit_2.setEnabled( not state.flood_use_direct_beam) self._sensitivity_clicked(self._content.sensitivity_chk.isChecked()) self._use_sample_center_changed( self._content.use_sample_center_checkbox.isChecked()) if len(popup_warning) > 0: QMessageBox.warning(self, "Turn ON advanced interface", popup_warning)
def displayMessage(self, message): from qtpy.QtWidgets import QMessageBox QMessageBox.information(self, self.translation[0], message)
def apply_changes(self, dialog_parent=None): if self.ramp_config is None: return if dialog_parent is None: dialog_parent = self sender_name = self.sender().objectName() psnames = list() if not self.ramp_config.ps_normalized_configs: mb = QMessageBox() mb.setIcon(QMessageBox.Warning) mb.setWindowTitle('Message') if 'Dipole' in sender_name or 'All' in sender_name: psnames = ['BO-Fam:PS-B-1', 'BO-Fam:PS-B-2'] msg = 'Only Dipole will be applied because there is no '\ 'normalized configuration defined!' mb.setText(msg) mb.exec_() elif 'Multipoles' in sender_name: msg = 'Nothing applied! No normalized configuration defined!' mb.setText(msg) mb.exec_() return else: psnames = self.conn_ps.psnames if 'Dipole' in sender_name: self._apply_ps(psnames, dialog_parent) self._apply_ti(dialog_parent) elif 'Multipoles' in sender_name: self._apply_ps(psnames, dialog_parent) elif 'RF' in sender_name: self._apply_rf(dialog_parent) self._apply_ti(dialog_parent) elif 'All' in sender_name: self._apply_ps(psnames, dialog_parent) self._apply_rf(dialog_parent) self._apply_ti(dialog_parent)
def __init__(self, parent=None, window_flags=None, instrument=None, instrument_list=None): QMainWindow.__init__(self, parent) if window_flags: self.setWindowFlags(window_flags) self.ui = load_ui(__file__, 'ui/reduction_main.ui', baseinstance=self) if STARTUP_WARNING: message = "The reduction application has problems starting:\n\n" message += STARTUP_WARNING QMessageBox.warning(self, "WARNING", message) # Application settings settings = QSettings() # Name handle for the instrument if instrument is None: instrument = settings.value("instrument_name", '', type=unicode) if instrument_list is not None and instrument not in instrument_list: instrument = None self._instrument = instrument self._facility = None # List of allowed instrument self._instrument_list = instrument_list # Reduction interface self._interface = None # Recent files self._recent_files = settings.value("recent_files", [], type=list) if self._recent_files is None: # An empty list saved to QSettings comes back as 'None' self._recent_files = [] # Folder to open files in self._last_directory = settings.value("last_directory", '.', type=unicode) self._last_export_directory = settings.value("last_export_directory", '.', type=unicode) # Current file name self._filename = None # Internal flag for clearing all settings and restarting the application self._clear_and_restart = False # General settings shared by all widgets self.general_settings = GeneralSettings(settings) # Event connections if not CAN_REDUCE: self.reduce_button.hide() self.export_button.clicked.connect(self._export) self.reduce_button.clicked.connect(self.reduce_clicked) self.save_button.clicked.connect(self._save) self.interface_chk.clicked.connect(self._interface_choice) self.interface_chk.setChecked(self.general_settings.advanced) self.general_settings.progress.connect(self._progress_updated)
class MainWindow(QMainWindow): """ Class of Main Window (top) """ _errMsgWindow = None def __init__(self, parent=None, window_flags=None): """ Initialization and set up """ # Base class QMainWindow.__init__(self, parent) if window_flags: self.setWindowFlags(window_flags) # Mantid configuration config = ConfigService.Instance() self._instrument = config["default.instrument"] # Central widget self.centralwidget = QWidget(self) # UI Window (from Qt Designer) self.ui = load_ui(__file__, 'MainWindow.ui', baseinstance=self) mpl_layout = QVBoxLayout() self.ui.graphicsView.setLayout(mpl_layout) self.fig = Figure() self.canvas = FigureCanvas(self.fig) self.ui.mainplot = self.fig.add_subplot(111, projection='mantid') mpl_layout.addWidget(self.canvas) # Do initialize plotting vecx, vecy, xlim, ylim = self.computeMock() self.mainline = self.ui.mainplot.plot(vecx, vecy, 'r-') leftx = [xlim[0], xlim[0]] lefty = [ylim[0], ylim[1]] self.leftslideline = self.ui.mainplot.plot(leftx, lefty, 'b--') rightx = [xlim[1], xlim[1]] righty = [ylim[0], ylim[1]] self.rightslideline = self.ui.mainplot.plot(rightx, righty, 'g--') upperx = [xlim[0], xlim[1]] uppery = [ylim[1], ylim[1]] self.upperslideline = self.ui.mainplot.plot(upperx, uppery, 'b--') lowerx = [xlim[0], xlim[1]] lowery = [ylim[0], ylim[0]] self.lowerslideline = self.ui.mainplot.plot(lowerx, lowery, 'g--') self.canvas.mpl_connect('button_press_event', self.on_mouseDownEvent) # Set up horizontal slide (integer) and string value self._leftSlideValue = 0 self._rightSlideValue = 99 self.ui.horizontalSlider.setRange(0, 100) self.ui.horizontalSlider.setValue(self._leftSlideValue) self.ui.horizontalSlider.setTracking(True) self.ui.horizontalSlider.setTickPosition(QSlider.NoTicks) self.ui.horizontalSlider.valueChanged.connect(self.move_leftSlider) self.ui.horizontalSlider_2.setRange(0, 100) self.ui.horizontalSlider_2.setValue(self._rightSlideValue) self.ui.horizontalSlider_2.setTracking(True) self.ui.horizontalSlider_2.setTickPosition(QSlider.NoTicks) self.ui.horizontalSlider_2.valueChanged.connect(self.move_rightSlider) self.ui.lineEdit_3.editingFinished.connect(self.set_startTime) self.ui.pushButton_setT0.clicked.connect(self.set_startTime) self.ui.lineEdit_4.editingFinished.connect(self.set_stopTime) self.ui.pushButton_setTf.clicked.connect(self.set_stopTime) # File loader self.scanEventWorkspaces() self.ui.pushButton_refreshWS.clicked.connect(self.scanEventWorkspaces) self.ui.pushButton_browse.clicked.connect(self.browse_File) self.ui.pushButton_load.clicked.connect(self.load_File) self.ui.pushButton_3.clicked.connect(self.use_existWS) # validates any number, but does not accept comma, contrary to QDoubleValidator # this way, it is possible to cast to float without checking for stray commas. regexp = QRegExp("[-+]?((\d+\.?\d*)|(\.\d+))(e[-+]?\d+)?") # noqa # noqa because flake is not happy about regex escape sequences regexp_val = QRegExpValidator(regexp, self) # Set up time self.ui.lineEdit_3.setValidator(regexp_val) self.ui.lineEdit_4.setValidator(regexp_val) # Filter by time self.ui.pushButton_filterTime.clicked.connect(self.filterByTime) self.ui.lineEdit_timeInterval.returnPressed.connect(self.filterByTime) # Filter by log value self.ui.lineEdit_5.setValidator(regexp_val) self.ui.lineEdit_6.setValidator(regexp_val) self.ui.lineEdit_7.setValidator(regexp_val) self.ui.lineEdit_8.setValidator(regexp_val) self.ui.lineEdit_9.setValidator(regexp_val) self.ui.lineEdit_5.textChanged.connect(self.set_minLogValue) self.ui.lineEdit_6.textChanged.connect(self.set_maxLogValue) dirchangeops = ["Both", "Increase", "Decrease"] self.ui.comboBox_4.addItems(dirchangeops) logboundops = ["Centre", "Left"] self.ui.comboBox_5.addItems(logboundops) self.ui.pushButton_4.clicked.connect(self.plotLogValue) self.ui.pushButton_filterLog.clicked.connect(self.filterByLogValue) # Set up help button self.ui.helpBtn.clicked.connect(self.helpClicked) # Set up vertical slide self._upperSlideValue = 99 self._lowerSlideValue = 0 self.ui.verticalSlider.setRange(0, 100) self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.verticalSlider.setTracking(True) self.ui.verticalSlider.valueChanged.connect(self.move_upperSlider) self.ui.verticalSlider_2.setRange(0, 100) self.ui.verticalSlider_2.setValue(self._lowerSlideValue) self.ui.verticalSlider_2.setTracking(True) self.ui.verticalSlider_2.valueChanged.connect(self.move_lowerSlider) # Set up for filtering (advanced setup) self._tofcorrection = False self.ui.checkBox_fastLog.setChecked(False) self.ui.checkBox_filterByPulse.setChecked(False) self.ui.checkBox_from1.setChecked(False) self.ui.checkBox_groupWS.setChecked(True) self.ui.comboBox_tofCorr.currentIndexChanged.connect(self.showHideEi) self.ui.pushButton_refreshCorrWSList.clicked.connect( self._searchTableWorkspaces) self.ui.lineEdit_Ei.setValidator(regexp_val) self.ui.label_Ei.hide() self.ui.lineEdit_Ei.hide() self.ui.label_Ei_2.hide() self.ui.comboBox_corrWS.hide() self.ui.pushButton_refreshCorrWSList.hide() # Set up for workspaces self._dataWS = None self._sampleLogNames = [] self._sampleLog = None # Side information self.ui.label_mean.hide() self.ui.label_meanvalue.hide() self.ui.label_avg.hide() self.ui.label_timeAvgValue.hide() self.ui.label_freq.hide() self.ui.label_freqValue.hide() self.ui.label_logname.hide() self.ui.label_lognamevalue.hide() self.ui.label_logsize.hide() self.ui.label_logsizevalue.hide() # Default self._defaultdir = os.getcwd() # register startup mantid.UsageService.registerFeatureUsage( mantid.kernel.FeatureType.Interface, "EventFilter", False) def on_mouseDownEvent(self, event): """ Respond to pick up a value with mouse down event """ x = event.xdata y = event.ydata if x is not None and y is not None: msg = "You've clicked on a bar with coords:\n %f, %f" % (x, y) QMessageBox.information(self, "Click!", msg) def computeMock(self): """ Compute vecx and vecy as mocking """ x0 = 0. xf = 1. dx = 0.1 vecx = [] vecy = [] x = x0 while x < xf: y = 0.0 vecx.append(x) vecy.append(y) x += dx xlim = [x0, xf] ylim = [-1., 1] return (vecx, vecy, xlim, ylim) def move_leftSlider(self): """ Re-setup left range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ newx = self.ui.horizontalSlider.value() if newx <= self._rightSlideValue and newx != self._leftSlideValue: # Allowed value: move the value bar self._leftSlideValue = newx # Move the vertical line xlim = self.ui.mainplot.get_xlim() if self.ui.lineEdit_4.text(): newx = min(xlim[0] + newx * (xlim[1] - xlim[0]) * 0.01, float(self.ui.lineEdit_4.text())) else: newx = xlim[0] + newx * (xlim[1] - xlim[0]) * 0.01 leftx = [newx, newx] lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Change value self.ui.lineEdit_3.setText(str(newx)) else: # Reset the value to original value self.ui.horizontalSlider.setValue(self._leftSlideValue) def set_startTime(self): """ Set the starting time and left slide bar """ inps = str(self.ui.lineEdit_3.text()) info_msg = "Starting time = %s" % (inps) Logger("Filter_Events").information(info_msg) xlim = self.ui.mainplot.get_xlim() if inps == "": # Empty. Use default newtime0 = xlim[0] else: newtime0 = float(inps) # Convert to integer slide value ileftvalue = int((newtime0 - xlim[0]) / (xlim[1] - xlim[0]) * 100) debug_msg = "iLeftSlide = %s" % str(ileftvalue) Logger("Filter_Events").debug(debug_msg) # Skip if same as original if ileftvalue == self._leftSlideValue: return # Set the value if out of range resetT = True if ileftvalue < 0: # Minimum value as 0 ileftvalue = 0 elif ileftvalue > self._rightSlideValue: # Maximum value as right slide value ileftvalue = self._rightSlideValue else: resetT = False if resetT is True: newtime0 = xlim[0] + ileftvalue * (xlim[1] - xlim[0]) * 0.01 info_msg = 'Corrected iLeftSlide = {} (vs. right = {})'.format( ileftvalue, self._rightSlideValue) Logger("Filter_Events").information(info_msg) # Move the slide bar (left) self._leftSlideValue = ileftvalue # Move the vertical line leftx = [newtime0, newtime0] lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Set the value to left slider self.ui.horizontalSlider.setValue(self._leftSlideValue) # Reset the value of line edit if resetT is True: self.ui.lineEdit_3.setText(str(newtime0)) def move_rightSlider(self): """ Re-setup left range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ newx = self.ui.horizontalSlider_2.value() if newx >= self._leftSlideValue and newx != self._rightSlideValue: # Allowed value: move the value bar self._rightSlideValue = newx xlim = self.ui.mainplot.get_xlim() if self.ui.lineEdit_3.text(): # that is not entirely fool proof, as the user could still remove the value in the field after putting # a non round percent, but this a) is unlikely and b) will not crash mantid, only show an artifact newx = max(xlim[0] + newx * (xlim[1] - xlim[0]) * 0.01, float(self.ui.lineEdit_3.text())) else: newx = xlim[0] + newx * (xlim[1] - xlim[0]) * 0.01 leftx = [newx, newx] lefty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Change value self.ui.lineEdit_4.setText(str(newx)) else: # Reset the value self.ui.horizontalSlider_2.setValue(self._rightSlideValue) def set_stopTime(self): """ Set the stopping time and right slide bar """ inps = str(self.ui.lineEdit_4.text()) Logger("Filter_Events").information('Stopping time = {}'.format(inps)) xlim = self.ui.mainplot.get_xlim() if inps == "": # Empty. Use default newtimef = xlim[1] else: # Parse newtimef = float(inps) # Convert to integer slide value irightvalue = int((newtimef - xlim[0]) / (xlim[1] - xlim[0]) * 100) Logger("Filter_Events").information( 'iRightSlide = {}'.format(irightvalue)) # Return if no change if irightvalue == self._rightSlideValue: return # Correct value resetT = True if irightvalue > 100: irightvalue = 100 elif irightvalue < self._leftSlideValue: irightvalue = self._leftSlideValue else: resetT = False if resetT: newtimef = xlim[0] + irightvalue * (xlim[1] - xlim[0]) * 0.01 # Move the slide bar (right) self._rightSlideValue = irightvalue # Move the vertical line rightx = [newtimef, newtimef] righty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=rightx, ydata=righty) self.canvas.draw() # Set the value to left slider self.ui.horizontalSlider_2.setValue(self._rightSlideValue) # Reset to line edit if resetT: self.ui.lineEdit_4.setText(str(newtimef)) def move_lowerSlider(self): """ Re-setup upper range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ inewy = self.ui.verticalSlider_2.value() debug_msg = 'LowerSlFider is set with value {} vs. class variable {}'.format( inewy, self._lowerSlideValue) Logger("Filter_Events").debug(debug_msg) # Return with no change if inewy == self._lowerSlideValue: # No change return if inewy >= self._upperSlideValue: # Out of upper range inewy = self._upperSlideValue - 1 setLineEdit = inewy != 0 or self._lowerSlideValue >= 0 # Move the lower vertical bar ylim = self.ui.mainplot.get_ylim() newy = ylim[0] + inewy * (ylim[1] - ylim[0]) * 0.01 lowerx = self.ui.mainplot.get_xlim() lowery = [newy, newy] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) self.canvas.draw() # Set line edit input if setLineEdit is True: # Change value to line edit (5) self.ui.lineEdit_5.setText(str(newy)) # Reset the class variable self._lowerSlideValue = inewy def set_minLogValue(self): """ Set the starting time and left slide bar """ debug_msg = 'Minimum Log Value = {}'.format(self.ui.lineEdit_5.text()) Logger("Filter_Events").debug(debug_msg) ylim = self.ui.mainplot.get_ylim() if str(self.ui.lineEdit_5.text()) == "": # Empty. Default to minY newminY = ylim[0] else: # Non empty. Parse newminY = float(self.ui.lineEdit_5.text()) # Convert to integer slide value iminlogval = int((newminY - ylim[0]) / (ylim[1] - ylim[0]) * 100) Logger("Filter_Events").debug('ilowerSlide = {}'.format(iminlogval)) # Return if no change if iminlogval == self._lowerSlideValue: return # Set value if out of range resetL = True if iminlogval >= self._upperSlideValue: iminlogval = self._upperSlideValue - 1 else: resetL = False if resetL: newminY = ylim[0] + iminlogval * (ylim[1] - ylim[0]) * 0.01 # Move the vertical line lowerx = self.ui.mainplot.get_xlim() lowery = [newminY, newminY] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) self.canvas.draw() # Move the slide bar (lower) self._lowerSlideValue = iminlogval debug_msg = 'LineEdit5 set slide to {}'.format(self._lowerSlideValue) Logger("Filter_Events").debug(debug_msg) self.ui.verticalSlider_2.setValue(self._lowerSlideValue) # Reset line Edit if using default if resetL is True: self.ui.lineEdit_5.setText(str(newminY)) def move_upperSlider(self): """ Re-setup upper range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ inewy = self.ui.verticalSlider.value() # Return w/o change if inewy == self._upperSlideValue: return # Set to boundary value if inewy <= self._lowerSlideValue: inewy = self._lowerSlideValue + 1 # Reset line editor? if inewy == 100 and self._upperSlideValue > 100: setLineEdit = False else: setLineEdit = True # Move the upper value bar: upperx and uppery are # real value (float but not (0,100)) of the figure ylim = self.ui.mainplot.get_ylim() newy = ylim[0] + inewy * (ylim[1] - ylim[0]) * 0.01 upperx = self.ui.mainplot.get_xlim() uppery = [newy, newy] setp(self.upperslideline, xdata=upperx, ydata=uppery) self.canvas.draw() # Change value if setLineEdit: self.ui.lineEdit_6.setText(str(newy)) self._upperSlideValue = inewy def set_maxLogValue(self): """ Set maximum log value from line-edit """ inps = str(self.ui.lineEdit_6.text()) debug_msg = 'Maximum Log Value = {}'.format(inps) Logger("Filter_Events").debug(debug_msg) ylim = self.ui.mainplot.get_ylim() if inps == "": # Empty. Default to minY newmaxY = ylim[1] else: # Parse newmaxY = float(inps) # Convert to integer slide value imaxlogval = int((newmaxY - ylim[0]) / (ylim[1] - ylim[0]) * 100) debug_msg = 'iUpperSlide = {}'.format(imaxlogval) Logger("Filter_Events").debug(debug_msg) # Return if no change if imaxlogval == self._upperSlideValue: return # Set to default if out of range resetL = True # if imaxlogval >= 100: # imaxlogval = 100 if imaxlogval < self._lowerSlideValue: imaxlogval = self._lowerSlideValue + 1 else: resetL = False # Set newmaxY if necessary if resetL is True: newmaxY = ylim[0] + imaxlogval * (ylim[1] - ylim[0]) * 0.01 # Move the vertical line upperx = self.ui.mainplot.get_xlim() uppery = [newmaxY, newmaxY] setp(self.upperslideline, xdata=upperx, ydata=uppery) self.canvas.draw() # Set the value to upper slider self._upperSlideValue = imaxlogval self.ui.verticalSlider.setValue(self._upperSlideValue) # Set the value to editor if necessary if resetL is True: self.ui.lineEdit_6.setText(str(newmaxY)) def browse_File(self): """ Open a file dialog to get file """ filename = QFileDialog.getOpenFileName( self, 'Input File Dialog', self._defaultdir, "Data (*.nxs *.dat);;All files (*)") if isinstance(filename, tuple): filename = filename[0] self.ui.lineEdit.setText(filename) Logger("Filter_Events").information( 'Selected file: "{}"'.format(filename)) def load_File(self): """ Load the file by file name or run number """ # Get file name from line editor filename = str(self.ui.lineEdit.text()) dataws = self._loadFile(str(filename)) if dataws is None: error_msg = 'Unable to locate run {} in default directory {}.'.format( filename, self._defaultdir) Logger("Filter_Events").error(error_msg) self._setErrorMsg(error_msg) else: self._importDataWorkspace(dataws) self._defaultdir = os.path.dirname(str(filename)) # Reset GUI self._resetGUI(resetfilerun=False) def use_existWS(self): """ Set up workspace to an existing one """ wsname = str(self.ui.comboBox.currentText()) try: dataws = AnalysisDataService.retrieve(wsname) self._importDataWorkspace(dataws) except KeyError: pass # Reset GUI self._resetGUI(resetfilerun=True) def plotLogValue(self): """ Plot log value """ # Get log value logname = str(self.ui.comboBox_2.currentText()) if len(logname) == 0: # return due to the empty one is chozen return samplelog = self._dataWS.getRun().getProperty(logname) vectimes = samplelog.times vecvalue = samplelog.value # check if len(vectimes) == 0: error_msg = "Empty log!" Logger("Filter_Events").error(error_msg) # Convert absolute time to relative time in seconds t0 = self._dataWS.getRun().getProperty("proton_charge").times[0] # append 1 more log if original log only has 1 value tf = self._dataWS.getRun().getProperty("proton_charge").times[-1] vectimes = numpy.append(vectimes, tf) vecvalue = numpy.append(vecvalue, vecvalue[-1]) vecreltimes = (vectimes - t0) / numpy.timedelta64(1, 's') # Set to plot xlim = [vecreltimes.min(), vecreltimes.max()] ylim = [vecvalue.min(), vecvalue.max()] self.ui.mainplot.set_xlim(xlim[0], xlim[1]) self.ui.mainplot.set_ylim(ylim[0], ylim[1]) setp(self.mainline, xdata=vecreltimes, ydata=vecvalue) samunit = samplelog.units if len(samunit) == 0: ylabel = logname else: ylabel = "%s (%s)" % (logname, samunit) self.ui.mainplot.set_ylabel(ylabel, fontsize=13) # assume that all logs are on almost same X-range. Only Y need to be reset setp(self.leftslideline, ydata=ylim) setp(self.rightslideline, ydata=ylim) # reset the log value limit as previous one does not make any sense setp(self.lowerslideline, xdata=xlim, ydata=[ylim[0], ylim[0]]) self._lowerSlideValue = 0 self.ui.verticalSlider_2.setValue(self._lowerSlideValue) self.ui.lineEdit_5.setText("") setp(self.upperslideline, xdata=xlim, ydata=[ylim[1], ylim[1]]) self._upperSlideValue = 100 self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.lineEdit_6.setText("") self.canvas.draw() # Load property's statistic and give suggestion on parallel and fast log timeavg = samplelog.timeAverageValue() numentries = samplelog.size() stat = samplelog.getStatistics() duration = stat.duration mean = stat.mean freq = float(numentries) / float(duration) self.ui.label_mean.show() self.ui.label_meanvalue.show() self.ui.label_avg.show() self.ui.label_timeAvgValue.show() self.ui.label_freq.show() self.ui.label_freqValue.show() self.ui.label_logname.show() self.ui.label_lognamevalue.show() self.ui.label_logsize.show() self.ui.label_logsizevalue.show() self.ui.label_meanvalue.setText("%.5e" % (mean)) self.ui.label_timeAvgValue.setText("%.5e" % (timeavg)) self.ui.label_freqValue.setText("%.5e" % (freq)) self.ui.label_lognamevalue.setText(logname) self.ui.label_logsizevalue.setText(str(numentries)) # Set suggested processing scheme if numentries > HUGE_FAST: self.ui.checkBox_fastLog.setCheckState(True) if numentries > HUGE_PARALLEL: self.ui.checkBox_doParallel.setCheckState(True) else: self.ui.checkBox_doParallel.setCheckState(False) else: self.ui.checkBox_fastLog.setCheckState(False) self.ui.checkBox_doParallel.setCheckState(False) return def _importDataWorkspace(self, dataws): """ Import data workspace for filtering """ if dataws is None: return # Plot time counts errmsg = self._plotTimeCounts(dataws) if errmsg is not None: errmsg = 'Workspace {} has invalid sample logs for splitting. Loading \ failure! \n{}\n'.format(dataws, errmsg) self._setErrorMsg(errmsg) return False # Import log self._sampleLogNames = [""] run = dataws.getRun() plist = run.getProperties() for p in plist: try: times = p.times if len(times) > 1 and numpy.isreal(p.value[0]): self._sampleLogNames.append(p.name) # This is here for FloatArrayProperty. If a log value is of this type it does not have times except AttributeError: pass # ENDFOR(p) # Set up sample log self.ui.comboBox_2.clear() self.ui.comboBox_2.addItems(self._sampleLogNames) # Side information self.ui.label_mean.hide() self.ui.label_meanvalue.hide() self.ui.label_avg.hide() self.ui.label_timeAvgValue.hide() self.ui.label_freq.hide() self.ui.label_freqValue.hide() # Hide 'log name' above the graphic view self.ui.label_logname.hide() self.ui.label_lognamevalue.hide() # Set dataws to class variable self._dataWS = dataws return True def scanEventWorkspaces(self): """ """ wsnames = AnalysisDataService.getObjectNames() eventwsnames = [] for wsname in wsnames: wksp = AnalysisDataService.retrieve(wsname) if wksp.__class__.__name__.count("Event") == 1: eventwsnames.append(wsname) # ENDFOR if len(eventwsnames) > 0: self.ui.comboBox.clear() self.ui.comboBox.addItems(eventwsnames) def _loadFile(self, filename): """ Load file or run File will be loaded to a workspace shown in MantidPlot """ config = ConfigService # Check input file name and output workspace name if filename.isdigit() is True: # Construct a file name from run number runnumber = int(filename) if runnumber <= 0: error_msg = 'Run number cannot be less or equal to zero. User gives {}.'.format( filename) Logger("Filter_Events").error(error_msg) return None else: ishort = config.getInstrument(self._instrument).shortName() filename = '{}_{}'.format(ishort, filename) wsname = filename + "_event" elif filename.count(".") > 0: # A proper file name wsname = os.path.splitext(os.path.split(filename)[1])[0] elif filename.count("_") == 1: # A short one as instrument_runnumber iname = filename.split("_")[0] str_runnumber = filename.split("_")[1] if str_runnumber.isdigit() is True and int(str_runnumber) > 0: # Accepted format ishort = config.getInstrument(iname).shortName() wsname = '{}_{}_event'.format(ishort, str_runnumber) else: # Non-supported error_msg = 'File name / run number in such format {} is not supported.'.format( filename) Logger("Filter_Events").error(error_msg) return None else: # Unsupported format error_msg = 'File name / run number in such format {} is not supported.'.format( filename) Logger("Filter_Events").error(error_msg) return None # Load try: ws = api.Load(Filename=filename, OutputWorkspace=wsname) except RuntimeError as e: return str(e) return ws def _plotTimeCounts(self, wksp): """ Plot time/counts """ import datetime # Rebin events by pulse time try: # Get run start if wksp.getRun().hasProperty("run_start"): runstart = wksp.getRun().getProperty("run_start").value elif wksp.getRun().hasProperty("proton_charge"): runstart = wksp.getRun().getProperty("proton_charge").times[0] else: runstart = wksp.getRun().getProperty("start_time").value # get run stop if wksp.getRun().hasProperty("proton_charge"): runstop = wksp.getRun().getProperty("proton_charge").times[-1] runstop = str(runstop).split(".")[0].strip() tf = datetime.datetime.strptime(runstop, "%Y-%m-%dT%H:%M:%S") else: last_pulse = wksp.getPulseTimeMax().toISO8601String() tf = datetime.datetime.strptime(last_pulse[:19], "%Y-%m-%dT%H:%M:%S") tf += datetime.timedelta(0, wksp.getTofMax() / 1000000) runstart = str(runstart).split(".")[0].strip() t0 = datetime.datetime.strptime(runstart, "%Y-%m-%dT%H:%M:%S") # Calculate dt = tf - t0 timeduration = dt.days * 3600 * 24 + dt.seconds timeres = float(timeduration) / MAXTIMEBINSIZE if timeres < 1.0: timeres = 1.0 sumwsname = '_Summed_{}'.format(wksp) if not AnalysisDataService.doesExist(sumwsname): sumws = api.SumSpectra(InputWorkspace=wksp, OutputWorkspace=sumwsname) sumws = api.RebinByPulseTimes(InputWorkspace=sumws, OutputWorkspace=sumwsname, Params='{}'.format(timeres)) sumws = api.ConvertToPointData(InputWorkspace=sumws, OutputWorkspace=sumwsname) else: sumws = AnalysisDataService.retrieve(sumwsname) except RuntimeError as e: return str(e) vecx = sumws.readX(0) vecy = sumws.readY(0) # if there is only one xbin in the summed workspace, that means we have an evetn file without pulse, # and in this case we use the original workspace time limits if len(vecx) == 1: xmin = min(wksp.readX(0)) / 1000000 xmax = max(wksp.readX(0)) / 1000000 else: xmin = min(vecx) xmax = max(vecx) ymin = min(vecy) ymax = max(vecy) # Reset graph self.ui.mainplot.set_xlim(xmin, xmax) self.ui.mainplot.set_ylim(ymin, ymax) self.ui.mainplot.set_xlabel('Time (seconds)', fontsize=13) self.ui.mainplot.set_ylabel('Counts', fontsize=13) # Set up main line setp(self.mainline, xdata=vecx, ydata=vecy) # Reset slide newslidery = [min(vecy), max(vecy)] newleftx = xmin + (xmax - xmin) * self._leftSlideValue * 0.01 setp(self.leftslideline, xdata=[newleftx, newleftx], ydata=newslidery) newrightx = xmin + (xmax - xmin) * self._rightSlideValue * 0.01 setp(self.rightslideline, xdata=[newrightx, newrightx], ydata=newslidery) self.canvas.draw() def filterByTime(self): """ Filter by time """ # Generate event filters if not self._dataWS: error_msg = "No workspace has been loaded for use!" Logger("Filter_Events").error(error_msg) return kwargs = {} xlim = self.ui.mainplot.get_xlim() kwargs["StartTime"] = self.ui.lineEdit_3.text( ) if self.ui.lineEdit_3.text() != "" else str(xlim[0]) kwargs["StopTime"] = self.ui.lineEdit_4.text( ) if self.ui.lineEdit_4.text() != "" else str(xlim[1]) if self.ui.lineEdit_timeInterval.text() != "": kwargs["TimeInterval"] = self.ui.lineEdit_timeInterval.text() kwargs[ "useReverseLogarithmic"] = self.ui.useReverseLogarithmic.isChecked( ) splitwsname = str(self._dataWS) + "_splitters" splitinfowsname = str(self._dataWS) + "_info" title = str(self.ui.lineEdit_title.text()) fastLog = self.ui.checkBox_fastLog.isChecked() try: splitws, infows = api.GenerateEventsFilter( InputWorkspace=self._dataWS, UnitOfTime="Seconds", TitleOfSplitters=title, OutputWorkspace=splitwsname, FastLog=fastLog, InformationWorkspace=splitinfowsname, **kwargs) except (RuntimeError, ValueError) as e: Logger("Filter_Events").error( "Splitting failed ! \n {0}".format(e)) return self.splitWksp(splitws, infows) def filterByLogValue(self): """ Filter by log value """ # Generate event filter kwargs = {} samplelog = str(self.ui.comboBox_2.currentText()) if len(samplelog) == 0: error_msg = "No sample log is selected!" Logger("Filter_Events").error(error_msg) return if self.ui.lineEdit_3.text() != "": rel_starttime = float(self.ui.lineEdit_3.text()) kwargs["StartTime"] = str(rel_starttime) if self.ui.lineEdit_4.text() != "": rel_stoptime = float(self.ui.lineEdit_4.text()) kwargs["StopTime"] = str(rel_stoptime) if self.ui.lineEdit_5.text() != "": minlogvalue = float(self.ui.lineEdit_5.text()) kwargs["MinimumLogValue"] = minlogvalue if self.ui.lineEdit_6.text() != "": maxlogvalue = float(self.ui.lineEdit_6.text()) kwargs["MaximumLogValue"] = maxlogvalue if self.ui.lineEdit_7.text() != "": logvalueintv = float(self.ui.lineEdit_7.text()) kwargs["LogValueInterval"] = logvalueintv logvalchangedir = str(self.ui.comboBox_4.currentText()) kwargs["FilterLogValueByChangingDirection"] = logvalchangedir if self.ui.lineEdit_9.text() != "": logvalueintv = float(self.ui.lineEdit_9.text()) kwargs["TimeTolerance"] = logvalueintv logboundtype = str(self.ui.comboBox_5.currentText()) kwargs["LogBoundary"] = logboundtype if self.ui.lineEdit_8.text() != "": logvaluetol = float(self.ui.lineEdit_8.text()) kwargs["LogValueTolerance"] = logvaluetol splitwsname = str(self._dataWS) + "_splitters" splitinfowsname = str(self._dataWS) + "_info" fastLog = self.ui.checkBox_fastLog.isChecked() title = str(self.ui.lineEdit_title.text()) try: splitws, infows = api.GenerateEventsFilter( InputWorkspace=self._dataWS, UnitOfTime="Seconds", TitleOfSplitters=title, OutputWorkspace=splitwsname, LogName=samplelog, FastLog=fastLog, InformationWorkspace=splitinfowsname, **kwargs) self.splitWksp(splitws, infows) except RuntimeError as e: self._setErrorMsg("Splitting Failed!\n %s" % (str(e))) def splitWksp(self, splitws, infows): """ Run FilterEvents """ dogroupws = self.ui.checkBox_groupWS.isChecked() filterbypulse = self.ui.checkBox_filterByPulse.isChecked() startfrom1 = self.ui.checkBox_from1.isChecked() splitsamplelog = self.ui.checkBox_splitLog.isChecked() corr2sample = str(self.ui.comboBox_tofCorr.currentText()) how2skip = str(self.ui.comboBox_skipSpectrum.currentText()) kwargs = {} if corr2sample == "Direct": ei = float(self.ui.lineEdit_Ei.text()) kwargs["IncidentEnergy"] = ei elif corr2sample == "Customized": corrws = str(self.ui.comboBox_corrWS.currentText()) kwargs["DetectorTOFCorrectionWorkspace"] = corrws # Output workspace name outbasewsname = str(self.ui.lineEdit_outwsname.text()) if len(outbasewsname) == 0: outbasewsname = "tempsplitted" self.ui.lineEdit_outwsname.setText(outbasewsname) api.FilterEvents(InputWorkspace=self._dataWS, SplitterWorkspace=splitws, InformationWorkspace=infows, OutputWorkspaceBaseName=outbasewsname, GroupWorkspaces=dogroupws, FilterByPulseTime=filterbypulse, CorrectionToSample=corr2sample, SpectrumWithoutDetector=how2skip, SplitSampleLogs=splitsamplelog, OutputWorkspaceIndexedFrom1=startfrom1, OutputTOFCorrectionWorkspace='TOFCorrTable', **kwargs) def showHideEi(self): """ """ corrtype = str(self.ui.comboBox_tofCorr.currentText()) # Incident energy if corrtype == "Direct": self.ui.label_Ei.show() self.ui.lineEdit_Ei.show() else: self.ui.label_Ei.hide() self.ui.lineEdit_Ei.hide() # Workspace if corrtype == "Customized": self.ui.label_Ei_2.show() self.ui.comboBox_corrWS.show() self.ui.pushButton_refreshCorrWSList.show() # Search for table workspace self._searchTableWorkspaces() else: self.ui.label_Ei_2.hide() self.ui.comboBox_corrWS.hide() self.ui.pushButton_refreshCorrWSList.hide() def _searchTableWorkspaces(self): """ Search table workspaces and add to 'comboBox_corrWS' """ wsnames = AnalysisDataService.getObjectNames() tablewsnames = [] for wsname in wsnames: wksp = AnalysisDataService.retrieve(wsname) if isinstance(wksp, mantid.api.ITableWorkspace): tablewsnames.append(wsname) # ENDFOR self.ui.comboBox_corrWS.clear() if len(tablewsnames) > 0: self.ui.comboBox_corrWS.addItems(tablewsnames) def _setErrorMsg(self, errmsg): """ Clear error message """ self._errMsgWindow = QMessageBox() self._errMsgWindow.setIcon(QMessageBox.Critical) self._errMsgWindow.setWindowTitle('Error') self._errMsgWindow.setStandardButtons(QMessageBox.Ok) self._errMsgWindow.setText(errmsg) result = self._errMsgWindow.exec_() return result def helpClicked(self): try: import mantidqt mantidqt.interfacemanager.InterfaceManager( ).showCustomInterfaceHelp("Filter Events", "utility") except ImportError: url = ("http://docs.mantidproject.org/nightly/interfaces/{}.html" "".format("Filter Events")) QDesktopServices.openUrl(QUrl(url)) def _resetGUI(self, resetfilerun=False): """ Reset GUI including all text edits and etc. """ if resetfilerun is True: self.ui.lineEdit.clear() # Plot related self.ui.lineEdit_3.clear() self.ui.lineEdit_4.clear() self.ui.horizontalSlider.setValue(0) self.ui.horizontalSlider_2.setValue(100) self.ui.lineEdit_outwsname.clear() self.ui.lineEdit_title.clear() # Filter by log value self.ui.lineEdit_5.clear() self.ui.lineEdit_6.clear() self.ui.verticalSlider_2.setValue(0) self.ui.verticalSlider.setValue(100) ylim = self.ui.mainplot.get_ylim() miny = ylim[0] maxy = ylim[1] xlim = self.ui.mainplot.get_xlim() setp(self.lowerslideline, xdata=xlim, ydata=[miny, miny]) setp(self.upperslideline, xdata=xlim, ydata=[maxy, maxy]) self.ui.lineEdit_7.clear() self.ui.lineEdit_8.clear() self.ui.lineEdit_9.clear() # Filter by time self.ui.lineEdit_timeInterval.clear() # Advanced setup self.ui.comboBox_tofCorr.setCurrentIndex(0) self.ui.lineEdit_Ei.clear() self.ui.checkBox_fastLog.setCheckState(False) self.ui.checkBox_doParallel.setCheckState(False) self.ui.comboBox_skipSpectrum.setCurrentIndex(0) self.ui.checkBox_filterByPulse.setCheckState(False) self.ui.checkBox_from1.setCheckState(False) self.ui.checkBox_groupWS.setCheckState(True) self.ui.checkBox_splitLog.setCheckState(False) self.canvas.draw()
def import_data(self, filenames=None): """Import data from text file.""" title = _("Import data") if filenames is None: if self.filename is None: basedir = getcwd_or_home() else: basedir = osp.dirname(self.filename) filenames, _selfilter = getopenfilenames(self, title, basedir, iofunctions.load_filters) if not filenames: return elif isinstance(filenames, str): filenames = [filenames] for filename in filenames: self.filename = str(filename) if os.name == "nt": self.filename = remove_backslashes(self.filename) ext = osp.splitext(self.filename)[1].lower() if ext not in iofunctions.load_funcs: buttons = QMessageBox.Yes | QMessageBox.Cancel answer = QMessageBox.question(self, title, _("<b>Unsupported file extension '%s'</b><br><br>" "Would you like to import it anyway " "(by selecting a known file format)?" ) % ext, buttons) if answer == QMessageBox.Cancel: return formats = list(iofunctions.load_extensions.keys()) item, ok = QInputDialog.getItem(self, title, _('Open file as:'), formats, 0, False) if ok: ext = iofunctions.load_extensions[str(item)] else: return load_func = iofunctions.load_funcs[ext] # 'import_wizard' (self.setup_io) if isinstance(load_func, str): # Import data with import wizard error_message = None try: text, _encoding = encoding.read(self.filename) base_name = osp.basename(self.filename) editor = ImportWizard(self, text, title=base_name, varname=fix_reference_name(base_name)) if editor.exec_(): var_name, clip_data = editor.get_data() self.editor.new_value(var_name, clip_data) except Exception as error: error_message = str(error) else: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() error_message = self.shellwidget.load_data(self.filename, ext) QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: QMessageBox.critical(self, title, _("<b>Unable to load '%s'</b>" "<br><br>" "The error message was:<br>%s" ) % (self.filename, error_message)) self.refresh_table()