def ask_confirmation(self, message, title="Mantid Workbench"): """ :param message: :return: """ reply = QMessageBox.question(self, title, message, QMessageBox.Yes, QMessageBox.No) return True if reply == QMessageBox.Yes else False
def closeEvent(self, event): if self.dirty: res = QMessageBox.question( self, QCoreApplication.applicationName(), self.tr("Save changes to file '%s'?" % self.filename if self.filename is not None else "unknown"), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel ) if res == QMessageBox.Cancel: event.ignore() return elif res == QMessageBox.Yes: self.save_file() self.save_settings() try: self.worker.quit() except AttributeError: pass try: self.serial.close() except (SerialException, AttributeError): pass
def _run_pip_action(self, package_name, action): """ DEPRECATED """ prefix = self.prefix if prefix == self.root_prefix: name = 'root' elif self.api.conda_environment_exists(prefix=prefix): name = osp.basename(prefix) else: name = prefix if action == C.ACTION_REMOVE: msgbox = QMessageBox.question(self, "Remove pip package: " "{0}".format(package_name), "Do you want to proceed?", QMessageBox.Yes | QMessageBox.No) if msgbox == QMessageBox.Yes: self.update_status() worker = self.api.pip_remove(prefix=self.prefix, pkgs=[package_name]) worker.sig_finished.connect(self._pip_process_ready) status = (_('Removing pip package <b>') + package_name + '</b>' + _(' from <i>') + name + '</i>') self.update_status(hide=True, message=status, progress=[0, 0])
def closeEvent(self, event): """ Executed when the application closes """ if False: reply = QMessageBox.question(self, 'Message', "Are you sure you want to quit this application?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore() # Save application settings if self._clear_and_restart: self._clear_and_restart = False QSettings().clear() else: settings = QSettings() settings.setValue("instrument_name", self._instrument) settings.setValue("last_file", self._filename) settings.setValue("recent_files", self._recent_files) settings.setValue("last_directory", str(self._last_directory)) settings.setValue("last_export_directory", str(self._last_export_directory))
def synchronize(self): """ Synchronize Spyder's path list with PYTHONPATH environment variable Only apply to: current user, on Windows platforms """ answer = QMessageBox.question(self, _("Synchronize"), _("This will synchronize Spyder's path list with " "<b>PYTHONPATH</b> environment variable for current user, " "allowing you to run your Python modules outside Spyder " "without having to configure sys.path. " "<br>Do you want to clear contents of PYTHONPATH before " "adding Spyder's path list?"), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if answer == QMessageBox.Cancel: return elif answer == QMessageBox.Yes: remove = True else: remove = False from spyder.utils.environ import (get_user_env, set_user_env, listdict2envdict) env = get_user_env() if remove: ppath = self.active_pathlist+self.ro_pathlist else: ppath = env.get('PYTHONPATH', []) if not isinstance(ppath, list): ppath = [ppath] ppath = [path for path in ppath if path not in (self.active_pathlist+self.ro_pathlist)] ppath.extend(self.active_pathlist+self.ro_pathlist) env['PYTHONPATH'] = ppath set_user_env(listdict2envdict(env), parent=self)
def save_if_required(self, prompt_for_confirm=True, force_save=False): """ Save the editor's contents to a file. The function has the following options: - if prompt_for_confirmation is True -> then show the yes/no dialog - if force_save is True, and prompt_for_confirmation is False -> then save the file anyway - if prompt_for_confirmation and force_save are both False -> then do NOT save the file, discard all changes :param prompt_for_confirmation: If this is True, then the user will be prompted with a yes/no dialog to decide whether to save or discard the file. If this parameter is True, force_save will be ignored! :param force_save: If this is True, then if the user is NOT being prompted, the file will be saved anyway! This is used for the File > Save Script (Ctrl + S) action. :returns: True if either saving was successful or no save was requested. Returns False if the operation should be cancelled """ if prompt_for_confirm: button = QMessageBox.question(self.editor, "", "Save changes to document before closing?", buttons=(QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel), defaultButton=QMessageBox.Cancel) if button == QMessageBox.Yes: return self.write() elif button == QMessageBox.No: return True else: # Cancelled return False elif force_save: return self.write() else: # pretend the user clicked No on the dialog return True
def restart_kernel(self): """ Restart the associanted kernel Took this code from the qtconsole project Licensed under the BSD license """ message = _('Are you sure you want to restart the kernel?') buttons = QMessageBox.Yes | QMessageBox.No result = QMessageBox.question(self, _('Restart kernel?'), message, buttons) if result == QMessageBox.Yes: sw = self.shellwidget if sw.kernel_manager: try: sw.kernel_manager.restart_kernel() except RuntimeError as e: sw._append_plain_text( _('Error restarting kernel: %s\n') % e, before_prompt=True ) else: sw._append_html(_("<br>Restarting kernel...\n<hr><br>"), before_prompt=True, ) else: sw._append_plain_text( _('Cannot restart a kernel not started by Spyder\n'), before_prompt=True )
def _offer_overwriting_gui(): """ Offers up a overwriting QMessageBox giving the option to overwrite a project, and returns the reply. :return: QMessaageBox.Yes or QMessageBox.No; The value is the value selected by the user. """ return QMessageBox.question(None, "Overwrite project?", "Would you like to overwrite the selected project?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
def send_report(self, title, body, application_log=None): _logger().debug('sending bug report on github\ntitle=%s\nbody=%s', title, body) # Credentials credentials = self.get_user_credentials() username = credentials['username'] password = credentials['password'] remember = credentials['remember'] token = credentials['token'] remember_token = credentials['remember_token'] if username is None and password is None and token is None: return False _logger().debug('got user credentials') # upload log file as a gist if application_log: url = self.upload_log_file(application_log) body += '\nApplication log: %s' % url try: if token: gh = github.GitHub(access_token=token) else: gh = github.GitHub(username=username, password=password) repo = gh.repos(self.gh_owner)(self.gh_repo) ret = repo.issues.post(title=title, body=body) except github.ApiError as e: _logger().warning('Failed to send bug report on Github. ' 'response=%r', e.response) # invalid credentials if e.response.code == 401: if self._show_msgbox: QMessageBox.warning( self.parent_widget, _('Invalid credentials'), _('Failed to create Github issue, ' 'invalid credentials...')) else: # other issue if self._show_msgbox: QMessageBox.warning( self.parent_widget, _('Failed to create issue'), _('Failed to create Github issue. Error %d') % e.response.code) return False else: issue_nbr = ret['number'] if self._show_msgbox: ret = QMessageBox.question( self.parent_widget, _('Issue created on Github'), _('Issue successfully created. Would you like to open the ' 'issue in your web browser?')) if ret in [QMessageBox.Yes, QMessageBox.Ok]: webbrowser.open( 'https://github.com/%s/%s/issues/%d' % ( self.gh_owner, self.gh_repo, issue_nbr)) return True
def _offer_save_message_box(self, parent): if self.prompt_save_on_close: return QMessageBox.question(parent, 'Unsaved Project', "The project is currently unsaved. Would you like to " "save before closing?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, QMessageBox.Yes) else: return QMessageBox.No
def _submit_to_github(self): """Action to take when pressing the submit button.""" # Get reference to the main window if self.parent() is not None: if getattr(self.parent(), 'main', False): # This covers the case when the dialog is attached # to the internal console main = self.parent().main else: # Else the dialog is attached to the main window # directly main = self.parent() else: main = None # Getting description and traceback title = self.title.text() description = self.input_description.toPlainText() traceback = self.error_traceback[:-1] # Remove last EOL # Render issue if main is not None: issue_text = main.render_issue(description=description, traceback=traceback) else: issue_text = description try: if main is None: org = 'ccordoba12' else: org = 'spyder-ide' github_backend = GithubBackend(org, 'spyder', parent_widget=main) github_report = github_backend.send_report(title, issue_text) if github_report: self.close() except Exception: ret = QMessageBox.question( self, _('Error'), _("An error occurred while trying to send the issue to " "Github automatically. Would you like to open it " "manually?<br><br>" "If so, please make sure to paste your clipboard " "into the issue report box that will appear in a new " "browser tab before clicking <i>Submit</i> on that " "page.")) if ret in [QMessageBox.Yes, QMessageBox.Ok]: QApplication.clipboard().setText(issue_text) issue_body = ( " \n<!--- *** BEFORE SUBMITTING: PASTE CLIPBOARD HERE " "TO COMPLETE YOUR REPORT *** ---!>\n") if main is not None: main.report_issue(body=issue_body, title=title, open_webpage=True) else: pass
def reset_namespace(self): """Resets the namespace by removing all names defined by the user""" reply = QMessageBox.question( self, _("Reset IPython namespace"), _("All user-defined variables will be removed." "<br>Are you sure you want to reset the namespace?"), QMessageBox.Yes | QMessageBox.No, ) if reply == QMessageBox.Yes: self.execute("%reset -f")
def _check_unsaved_comments(self): if self.textChangedAt is None: return #Nothing to be changed i = self.toolbar.source_select.currentIndex() i = self._index_hash(i) if self.textChangedAt == i: self.textChangedAt = None return #This is a refresh info = "Comments or flags changed but were not saved. Would you like to save them?" reply = QMessageBox.question(self, '', info, QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: self.update_comments(True) self.textChangedAt = None
def reject(self): """ """ if self.busy: answer = QMessageBox.question( self, 'Quit Conda Manager?', 'Conda is still busy.\n\nDo you want to quit?', buttons=QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: QDialog.reject(self) # Do some cleanup? else: QDialog.reject(self)
def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed.""" if self.busy: answer = QMessageBox.question( self, 'Conda Manager', 'Conda Manager is still busy.\n\nDo you want to quit?', buttons=QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: return True else: return False else: return True
def closeEvent(self, event): """ """ if self.packages.busy: answer = QMessageBox.question( self, 'Quit Conda Manager?', 'Conda is still busy.\n\nDo you want to quit?', buttons=QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: QMainWindow.closeEvent(self, event) # Do some cleanup? else: event.ignore() else: QMainWindow.closeEvent(self, event)
def close(self): while self.dirty is True: # While avoids data loss, in case save operation is aborted if self.filename == "": text = "Save unsaved changes?" else: text = "Save %s?" % self.filename ans = QMessageBox.question(self, 'Save', text, QMessageBox.Yes, QMessageBox.Cancel, QMessageBox.No) if ans == QMessageBox.Cancel: return elif ans == QMessageBox.Yes: self.parent.actionSave(False) elif ans == QMessageBox.No: break self.tabWidget.removeTab(self.index())
def restart_kernel(self): """ Restart the associated kernel. Took this code from the qtconsole project Licensed under the BSD license """ sw = self.shellwidget if not running_under_pytest() and self.ask_before_restart: message = _('Are you sure you want to restart the kernel?') buttons = QMessageBox.Yes | QMessageBox.No result = QMessageBox.question(self, _('Restart kernel?'), message, buttons) else: result = None if (result == QMessageBox.Yes or running_under_pytest() or not self.ask_before_restart): if sw.kernel_manager: if self.infowidget.isVisible(): self.infowidget.hide() sw.show() try: sw.kernel_manager.restart_kernel( stderr=self.stderr_handle) except RuntimeError as e: sw._append_plain_text( _('Error restarting kernel: %s\n') % e, before_prompt=True ) else: # For issue 6235. IPython was changing the setting of # %colors on windows by assuming it was using a dark # background. This corrects it based on the scheme. self.set_color_scheme(sw.syntax_style) sw._append_html(_("<br>Restarting kernel...\n<hr><br>"), before_prompt=False) else: sw._append_plain_text( _('Cannot restart a kernel not started by Spyder\n'), before_prompt=True )
def path_selection_changed(self): """Handles when the current index of the combobox changes.""" idx = self.currentIndex() if idx == SELECT_OTHER: external_path = self.select_directory() if len(external_path) > 0: self.add_external_path(external_path) self.setCurrentIndex(self.count() - 1) else: self.setCurrentIndex(CWD) elif idx == CLEAR_LIST: reply = QMessageBox.question( self, _("Clear other directories"), _("Do you want to clear the list of other directories?"), QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: self.clear_external_paths() self.setCurrentIndex(CWD) elif idx >= EXTERNAL_PATHS: self.external_path = to_text_string(self.itemText(idx))
def add_path(self): self.redirect_stdio.emit(False) directory = getexistingdirectory(self, _("Select directory"), self.last_path) self.redirect_stdio.emit(True) if directory: directory = osp.abspath(directory) self.last_path = directory if directory in self.pathlist: answer = QMessageBox.question(self, _("Add path"), _("This directory is already included in Spyder path " "list.<br>Do you want to move it to the top of " "the list?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.pathlist.remove(directory) else: return self.pathlist.insert(0, directory) self.update_list()
def save_if_required(self, confirm=True): """Asks the user if the contents should be saved. :param confirm: If True then show a confirmation dialog first to check we should save :returns: True if either saving was successful or no save was requested. Returns False if the operation should be cancelled """ if confirm: button = QMessageBox.question(self.editor, "", "Save changes to document before closing?", buttons=(QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel), defaultButton=QMessageBox.Cancel) if button == QMessageBox.Yes: return self.write() elif button == QMessageBox.No: return True else: # Cancelled return False else: return self.write()
def main(self): """ Main metod that will take input from the user, make a MOSViz Table and save it to a file. It will use the information in the headers of the spectra files to fill in rows of the table. If the user has cutout, it will look for an image file with the corresponding object name and add it to the Table. """ success = self.verify_input() if not success: self.statusBar().showMessage("Input error") return self.generate_table_button.setDisabled(True) self.statusBar().showMessage("Making Table") QApplication.processEvents() output_path = os.path.join(self.save_file_dir, self.save_file_name) source_catalog = nirspec_table_generator(self.spec_path, cutout_path=self.cutout_path, output_path=output_path) self.statusBar().showMessage("DONE!") info = QMessageBox.information(self, "Status", "Catalog saved at:\n"+output_path) if self.session is not None: usr_ans = QMessageBox.question(self, '', "Would you like to open {}?".format(self.save_file_name), QMessageBox.Yes | QMessageBox.No) if usr_ans == QMessageBox.Yes: self.hide() data = load_data(output_path) self.session.data_collection.append(data) self.session.application.new_data_viewer(MOSVizViewer, data=self.session.data_collection[-1]) self.close() return
def add_path(self): self.redirect_stdio.emit(False) directory = getexistingdirectory(self, _("Select directory"), self.last_path) self.redirect_stdio.emit(True) if directory: is_unicode = False if PY2: try: directory.decode('ascii') except UnicodeEncodeError: is_unicode = True if is_unicode: QMessageBox.warning(self, _("Add path"), _("You are using Python 2 and the path" " selected has Unicode characters. " "The new path will not be added."), QMessageBox.Ok) return directory = osp.abspath(directory) self.last_path = directory if directory in self.pathlist: item = self.listwidget.findItems(directory, Qt.MatchExactly)[0] item.setCheckState(Qt.Checked) answer = QMessageBox.question( self, _("Add path"), _("This directory is already included in Spyder " "path list.<br>Do you want to move it to the " "top of the list?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.pathlist.remove(directory) else: return self.pathlist.insert(0, directory) self.update_list()
def process_files(self): ''' Creates the output content. ''' self.__preferences.set(BEQ_CONFIG_FILE, self.configFile.text()) self.__preferences.set(BEQ_MERGE_DIR, self.outputDirectory.text()) self.__preferences.set(BEQ_MINIDSP_TYPE, self.dspType.currentText()) self.__preferences.set(BEQ_EXTRA_DIR, self.userSourceDir.text()) selected_channels = [ item.text() for item in self.outputChannels.selectedItems() ] self.__preferences.set(BEQ_OUTPUT_CHANNELS, "|".join(selected_channels)) if self.outputMode.isVisible(): self.__preferences.set(BEQ_OUTPUT_MODE, self.outputMode.currentText()) if self.__clear_output_directory(): self.filesProcessed.setValue(0) optimise_filters = False dsp_type = DspType.parse(self.dspType.currentText()) should_process = True if dsp_type.is_minidsp and dsp_type.is_fixed_point_hardware(): result = QMessageBox.question( self, 'Are you feeling lucky?', f"Do you want to automatically optimise filters to fit in the 6 biquad limit? \n\n" f"Note this feature is experimental. \n" f"You are strongly encouraged to review the generated filters to ensure they are safe to use.\n" f"USE AT YOUR OWN RISK!\n\n" f"Are you sure you want to continue?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) optimise_filters = result == QMessageBox.Yes elif dsp_type.is_experimental: result = QMessageBox.question( self, 'Generate HTP-1 Config Files?', f"Support for HTP-1 config files is experimental and currently untested on an actual device. \n\n" f"USE AT YOUR OWN RISK!\n\n" f"Are you sure you want to continue?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) should_process = result == QMessageBox.Yes if should_process: self.__start_spinning() self.errors.clear() self.errors.setEnabled(False) self.copyErrorsButton.setEnabled(False) self.optimised.clear() self.optimised.setEnabled(False) self.copyOptimisedButton.setEnabled(False) self.optimised.setVisible(optimise_filters) self.copyOptimisedButton.setVisible(optimise_filters) self.optimisedLabel.setVisible(optimise_filters) in_out_split = None if self.outputMode.isVisible( ) and not self.outputChannels.isVisible(): import re m = re.search('Input ([1-9]) / Output ([1-9])', self.outputMode.currentText()) if m: in_out_split = (m.group(1), m.group(2)) QThreadPool.globalInstance().start( XmlProcessor(self.__beq_dir, self.userSourceDir.text(), self.outputDirectory.text(), self.configFile.text(), dsp_type, self.__on_file_fail, self.__on_file_ok, self.__on_complete, self.__on_optimised, optimise_filters, selected_channels, in_out_split))
def main(self): """ Construct a catalog and make cutouts. """ success = self.verify_input() if not success: self.statusBar().showMessage("Please fill in all fields") return # self.start_button.setText("Abort") # self.start_button.clicked.disconnect() # self.start_button.clicked.connect(self.abort) # temporary fix for non-existing abort functionality. self.start_button.setText("Working...") self.start_button.setEnabled(False) self.statusBar().showMessage("Making a list of files") QApplication.processEvents() t = self.make_catalog_table() #Change working path to save path cwd = os.getcwd() os.chdir(self.save_path) self.statusBar().showMessage("Making catalog") programName, file_extension = os.path.splitext(self.img_path) programName = os.path.basename(programName) #Make cutouts using info in catalog. self.statusBar().showMessage("Making cutouts") fits_cutouts, success_counter, success_table = go_make_cutouts( t, self.img_path, programName, output_file_format=self.output_file_format, output_dir_format=self.output_dir_format, clobber=True, apply_rotation=True, report=self.report) if self.kill: self.kill = False self.progress_bar.reset() self.statusBar().showMessage("Waiting for user input") return self.statusBar().showMessage("DONE!") directory = self.output_dir_format.format(programName) output_path = os.path.abspath(os.path.join(self.save_path, directory)) #Give notice to user on status. string = "Cutouts were made for %s out of %s files\n\nSaved at: %s" % ( success_counter, len(t), output_path) #If some spectra files do not have a cutout, a list of their names will be saved to # 'skipped_cutout_files.txt' in the save dir as the MOSViz Table file. if success_counter != len(t): self.write_skipped(t) string += "\n\nA list of spectra files" string += "without cutouts is saved in" string += "'skipped_cutout_files.txt'" string += "\n\nSaved at: %s" % os.path.join( self.save_path, "skipped_cutout_files.txt") info = QMessageBox.information(self, "Status:", string) #Change back dir. os.chdir(cwd) usr_ans = QMessageBox.question( self, '', "Would you like to load all generated cutouts into glue?", QMessageBox.Yes | QMessageBox.No) if usr_ans == QMessageBox.Yes: os.chdir(self.save_path) data = [] for i, flag in enumerate(success_table): if flag: path = self.output_dir_format.format(programName) this_id = t["id"][i] fname = os.path.join( path, self.output_file_format.format(this_id, programName)) data.append(load_data(fname)) self.session.data_collection.merge(*data, label="%s_Cutouts" % programName) os.chdir(cwd) self.close() return
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 verify_input(self): """ Process information in the input boxes. Checks if user inputs are functional. Returns ------- success : bool True if no input errors, False otherwise. """ self.statusBar().showMessage("Reading input") success = True self.spec_path = self.spectra_user_input.text() self.save_file_name = self.filename_user_input.text() if self.spec_path == "": self.spectra_user_input.setStyleSheet("background-color: rgba(255, 0, 0, 128);") success = False else: self.spectra_user_input.setStyleSheet("") if self.save_file_name == "" or "/" in self.save_file_name or "\\" in self.save_file_name: self.filename_user_input.setStyleSheet("background-color: rgba(255, 0, 0, 128);") success = False else: self.filename_user_input.setStyleSheet("") if self.add_cutout_radio.isChecked(): self.cutout_path = self.cutout_path_display.text() if self.cutout_path == "": self.cutout_path_display.setStyleSheet("background-color: rgba(255, 0, 0, 128);") success = False else: self.cutout_path_display.setStyleSheet("background-color: rgba(255, 255, 255, 0);") if success: if not os.path.isdir(self.spec_path): info = QMessageBox.information(self, "Error", "Broken path:\n\n"+self.spec_path) self.spectra_user_input.setStyleSheet("background-color: rgba(255, 0, 0, 128);") success = False else: if not self.custom_save_path: self.save_file_dir = self.spec_path if self.add_cutout_radio.isChecked(): if not os.path.isdir(self.cutout_path): info = QMessageBox.information(self, "Error", "Broken path:\n\n"+self.cutout_path) self.cutout_path_display.setStyleSheet("background-color: rgba(255, 0, 0, 128);") success = False if (not os.path.samefile(self.spec_path, os.path.dirname(self.cutout_path)) and not self.abs_path and not self.cutout_path): usr_ans = QMessageBox.question(self, "Path Warning", "The cutout directory is not in the spectra directory, " "this will generate a MOSViz Table " "that is unique to your computer " "(you will not be able to share it). Continue?", QMessageBox.Yes | QMessageBox.No) if usr_ans == QMessageBox.Yes: self.abs_path = True else: success = False return success
def __synthesis(self) -> None: """Start synthesis.""" # Check if the amount of the target points are same length = -1 for path in self.path.values(): if length < 0: length = len(path) if len(path) != length: QMessageBox.warning( self, "Target Error", "The length of target paths should be the same.") return # Get the algorithm type for option, button in self.algorithm_options.items(): if button.isChecked(): algorithm = option break else: raise ValueError("no option") mech = deepcopy(self.mech) mech['shape_only'] = self.shape_only_option.isChecked() if mech['shape_only']: if QMessageBox.question( self, "Elliptical Fourier Descriptor", "An even distribution will make the comparison more accurate.\n" "Do you make sure yet?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) == QMessageBox.No: return mech['expression'] = parse_vpoints(mech.pop('expression', [])) mech['target'] = deepcopy(self.path) def name_in_table(target_name: str) -> int: """Find a target_name and return the row from the table.""" for r in range(self.parameter_list.rowCount()): if self.parameter_list.item(r, 0).text() == target_name: return r return -1 placement: Dict[int, Tuple[float, float, float]] = mech['placement'] for name in placement: row = name_in_table(f"P{name}") placement[name] = ( self.parameter_list.cellWidget(row, 2).value(), self.parameter_list.cellWidget(row, 3).value(), self.parameter_list.cellWidget(row, 4).value(), ) # Start progress dialog dlg = ProgressDialog(algorithm, mech, self.alg_options, self) dlg.show() if not dlg.exec_(): dlg.deleteLater() return mechanisms_plot: List[Mapping[str, Any]] = [] for data in dlg.mechanisms: mechanisms_plot.append({ 'time_fitness': data.pop('time_fitness'), 'algorithm': data['algorithm'], }) self.mechanism_data.append(data) self.__add_result(data) self.__set_time(dlg.time_spend) self.project_no_save() dlg.deleteLater() dlg = ChartDialog("Convergence Data", mechanisms_plot, self) dlg.show() dlg.exec_() dlg.deleteLater()
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 main(self): """ Construct a catalog and make cutouts. """ success = self.verify_input() if not success: self.statusBar().showMessage("Please fill in all fields") return # self.start_button.setText("Abort") # self.start_button.clicked.disconnect() # self.start_button.clicked.connect(self.abort) # temporary fix for non-existing abort functionality. self.start_button.setText("Working...") self.start_button.setEnabled(False) self.statusBar().showMessage("Making a list of files") QApplication.processEvents() t = self.make_catalog_table() #Change working path to save path cwd = os.getcwd() os.chdir(self.save_path) self.statusBar().showMessage("Making catalog") programName, file_extension = os.path.splitext(self.img_path) programName = os.path.basename(programName) #Make cutouts using info in catalog. self.statusBar().showMessage("Making cutouts") fits_cutouts, success_counter, success_table = go_make_cutouts( t, self.img_path, programName, output_file_format=self.output_file_format, output_dir_format=self.output_dir_format, clobber=True, apply_rotation=True, report=self.report) if self.kill: self.kill = False self.progress_bar.reset() self.statusBar().showMessage("Waiting for user input") return self.statusBar().showMessage("DONE!") directory = self.output_dir_format.format(programName) output_path = os.path.abspath( os.path.join(self.save_path, directory)) #Give notice to user on status. string = "Cutouts were made for %s out of %s files\n\nSaved at: %s" %( success_counter, len(t), output_path) #If some spectra files do not have a cutout, a list of their names will be saved to # 'skipped_cutout_files.txt' in the save dir as the MOSViz Table file. if success_counter != len(t): self.write_skipped(t, success_table) string += "\n\nA list of spectra files" string += "without cutouts is saved in" string += "'skipped_cutout_files.txt'" string += "\n\nSaved at: %s" % os.path.join( self.save_path, "skipped_cutout_files.txt") info = QMessageBox.information(self, "Status:", string) #Change back dir. os.chdir(cwd) usr_ans = QMessageBox.question(self, '', "Would you like to load all generated cutouts into glue?", QMessageBox.Yes | QMessageBox.No) if usr_ans == QMessageBox.Yes: os.chdir(self.save_path) data = [] for i, flag in enumerate(success_table): if flag: path = self.output_dir_format.format(programName) this_id = t["id"][i] fname = os.path.join( path, self.output_file_format.format(this_id, programName)) data.append(load_data(fname)) self.session.data_collection.merge(*data, label="%s_Cutouts" %programName) os.chdir(cwd) self.close() return
def openssh_tunnel(self, lport, rport, server, remoteip='127.0.0.1', keyfile=None, password=None, timeout=0.4): """ We decided to replace pyzmq's openssh_tunnel method to work around issue https://github.com/zeromq/pyzmq/issues/589 which was solved in pyzmq https://github.com/zeromq/pyzmq/pull/615 """ ssh = "ssh " if keyfile: ssh += "-i " + keyfile if ':' in server: server, port = server.split(':') ssh += " -p %s" % port cmd = "%s -O check %s" % (ssh, server) (output, exitstatus) = pexpect.run(cmd, withexitstatus=True) if not exitstatus: pid = int(output[output.find("(pid=")+5:output.find(")")]) cmd = "%s -O forward -L 127.0.0.1:%i:%s:%i %s" % ( ssh, lport, remoteip, rport, server) (output, exitstatus) = pexpect.run(cmd, withexitstatus=True) if not exitstatus: atexit.register(_stop_tunnel, cmd.replace("-O forward", "-O cancel", 1)) return pid cmd = "%s -f -S none -L 127.0.0.1:%i:%s:%i %s sleep %i" % ( ssh, lport, remoteip, rport, server, timeout) # pop SSH_ASKPASS from env env = os.environ.copy() env.pop('SSH_ASKPASS', None) ssh_newkey = 'Are you sure you want to continue connecting' tunnel = pexpect.spawn(cmd, env=env) failed = False while True: try: i = tunnel.expect([ssh_newkey, '[Pp]assword:'], timeout=.1) if i == 0: host = server.split('@')[-1] question = _("The authenticity of host <b>%s</b> can't be " "established. Are you sure you want to continue " "connecting?") % host reply = QMessageBox.question(self, _('Warning'), question, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: tunnel.sendline('yes') continue else: tunnel.sendline('no') raise RuntimeError( _("The authenticity of the host can't be established")) if i == 1 and password is not None: tunnel.sendline(password) except pexpect.TIMEOUT: continue except pexpect.EOF: if tunnel.exitstatus: raise RuntimeError(_("Tunnel '%s' failed to start") % cmd) else: return tunnel.pid else: if failed or password is None: raise RuntimeError(_("Could not connect to remote host")) # TODO: Use this block when pyzmq bug #620 is fixed # # Prompt a passphrase dialog to the user for a second attempt # password, ok = QInputDialog.getText(self, _('Password'), # _('Enter password for: ') + server, # echo=QLineEdit.Password) # if ok is False: # raise RuntimeError('Could not connect to remote host.') tunnel.sendline(password) failed = True
def main(self): """ Main function that uses information provided by the user and in the headers of spectra files to construct a catalog and make cutouts. """ success = self.verify_input() if not success: self.statusBar().showMessage("Please fill in all fields") return self.start_button.setText("Abort") self.start_button.clicked.disconnect() self.start_button.clicked.connect(self.abort) self.statusBar().showMessage("Making a list of files") QApplication.processEvents() fb, target_names = self.get_file_base() if len(fb) == 0: return #Change working path to save path cwd = os.getcwd() os.chdir(self.save_path) self.statusBar().showMessage("Making catalog") programName = os.path.basename(fb[0]).split("_")[0] t, skipped = self.make_catalog_table(fb, target_names, programName) if t is None: raise Exception( "All input spectra files have bad WCS and/or headers.") #Make cutouts using info in catalog. self.statusBar().showMessage("Making cutouts") success_counter, success_table = self.make_cutouts(t, self.img_path, programName, clobber=True, apply_rotation=True) if self.kill: self.kill = False self.progress_bar.reset() self.statusBar().showMessage("Waiting for user input") return self.statusBar().showMessage("DONE!") #If some spectra files do not have a cutout, a list of their names will be saved to # 'skipped_cutout_files.txt' in the save dir as the MOSViz Table file. directory = self.output_dir_format.format(programName) output_path = os.path.abspath(os.path.join(self.save_path, directory)) #Give notice to user on status. string = "Cutouts were made for %s out of %s files\n\nSaved at: %s" % ( success_counter, len(fb), output_path) if success_counter != len(fb): self.write_skipped(t, success_table, skipped) string += "\n\nA list of spectra files" string += "without cutouts is saved in" string += "'skipped_cutout_files.txt'" string += "\n\nSaved at: %s" % os.path.join( self.save_path, "skipped_cutout_files.txt") info = QMessageBox.information(self, "Status:", string) #Change back dir. os.chdir(cwd) usr_ans = QMessageBox.question( self, '', "Would you like to load all generated cutouts into glue?", QMessageBox.Yes | QMessageBox.No) if usr_ans == QMessageBox.Yes: os.chdir(self.save_path) data = [] for i, flag in enumerate(success_table): if flag: path = self.output_dir_format.format(programName) this_id = t["id"][i] fname = os.path.join( path, self.output_file_format.format(this_id, programName)) data.append(load_data(fname)) self.session.data_collection.merge(*data, label="%s_Cutouts" % programName) os.chdir(cwd) if self.tableGen and self.TableGen is not None: self.TableGen.cutout_response(output_path, self.custom_save_path) self.close() return
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: if PYQT5: 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: mb = QMessageBox(self) answer = mb.question( mb, 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') self.filenames.insert(index, fname) else: self.filenames.insert(index, fname) tab_name = self.get_tab_text(fname) self.update_tabs_text() 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.filenames.insert(index, fname) self.shellwidgets.insert(index, shellwidget) 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 save_result(self): if self.settings.image_path is not None and QMessageBox.Yes == QMessageBox.question( self, "Copy", "Copy name to clipboard?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes): clipboard = QGuiApplication.clipboard() clipboard.setText( os.path.splitext(os.path.basename( self.settings.image_path))[0]) if self.settings.segmentation is None or len(self.settings.sizes) == 1: QMessageBox.warning(self, "No components", "No components to save") return dial = SaveDialog( io_functions.save_components_dict, False, history=self.settings.get_path_history(), file_mode=QFileDialog.Directory, ) dial.setDirectory( self.settings.get("io.save_components_directory", str(Path.home()))) dial.selectFile( os.path.splitext(os.path.basename(self.settings.image_path))[0]) if not dial.exec_(): return res = dial.get_result() potential_names = self.settings.get_file_names_for_save_result( res.save_destination) conflict = [] for el in potential_names: if os.path.exists(el): conflict.append(el) if len(conflict) > 0: # TODO modify because of long lists conflict_str = "\n".join(conflict) if QMessageBox.No == QMessageBox.warning( self, "Overwrite", f"Overwrite files:\n {conflict_str}", QMessageBox.Yes | QMessageBox.No, QMessageBox.No, ): self.save_result() return self.settings.set("io.save_components_directory", os.path.dirname(str(res.save_destination))) self.settings.add_path_history( os.path.dirname(str(res.save_destination))) def exception_hook(exception): QMessageBox.critical( self, "Save error", f"Error on disc operation. Text: {exception}", QMessageBox.Ok) dial = ExecuteFunctionDialog( res.save_class.save, [ res.save_destination, self.settings.get_project_info(), res.parameters ], text="Save components", exception_hook=exception_hook, ) dial.exec()
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() else: basedir = osp.dirname(self.filename) filenames, _selfilter = getopenfilenames(self, title, basedir, iofunctions.load_filters) if not filenames: return elif is_text_string(filenames): filenames = [filenames] for filename in filenames: self.filename = to_text_string(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[to_text_string(item)] else: return load_func = iofunctions.load_funcs[ext] # 'import_wizard' (self.setup_io) if is_text_string(load_func): # 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.set_value(var_name, clip_data) except Exception as error: error_message = str(error) else: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() if self.is_ipyclient: error_message = self.shellwidget.load_data( self.filename, ext) self.shellwidget._kernel_reply = None else: error_message = monitor_load_globals( self._get_sock(), 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>Error message:<br>%s") % (self.filename, error_message)) self.refresh_table()
def verify_input(self): """ Process information in the input boxes. Checks if user inputs are functional. Returns ------- success : bool True if no input errors, False otherwise. """ self.statusBar().showMessage("Reading input") success = True self.spec_path = self.spectra_user_input.text() self.save_file_name = self.filename_user_input.text() if self.spec_path == "": self.spectra_user_input.setStyleSheet( "background-color: rgba(255, 0, 0, 128);") success = False else: self.spectra_user_input.setStyleSheet("") if self.save_file_name == "" or "/" in self.save_file_name or "\\" in self.save_file_name: self.filename_user_input.setStyleSheet( "background-color: rgba(255, 0, 0, 128);") success = False else: self.filename_user_input.setStyleSheet("") if self.add_cutout_radio.isChecked(): self.cutout_path = self.cutout_path_display.text() if self.cutout_path == "": self.cutout_path_display.setStyleSheet( "background-color: rgba(255, 0, 0, 128);") success = False else: self.cutout_path_display.setStyleSheet( "background-color: rgba(255, 255, 255, 0);") if success: if not os.path.isdir(self.spec_path): info = QMessageBox.information( self, "Error", "Broken path:\n\n" + self.spec_path) self.spectra_user_input.setStyleSheet( "background-color: rgba(255, 0, 0, 128);") success = False else: if not self.custom_save_path: self.save_file_dir = self.spec_path if self.add_cutout_radio.isChecked(): if not os.path.isdir(self.cutout_path): info = QMessageBox.information( self, "Error", "Broken path:\n\n" + self.cutout_path) self.cutout_path_display.setStyleSheet( "background-color: rgba(255, 0, 0, 128);") success = False if (not os.path.samefile(self.spec_path, os.path.dirname(self.cutout_path)) and not self.abs_path and not self.cutout_path): usr_ans = QMessageBox.question( self, "Path Warning", "The cutout directory is not in the spectra directory, " "this will generate a MOSViz Table " "that is unique to your computer " "(you will not be able to share it). Continue?", QMessageBox.Yes | QMessageBox.No) if usr_ans == QMessageBox.Yes: self.abs_path = True else: success = False return success
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 main(self): """ Main function that uses information provided by the user and in the headers of spectra files to construct a catalog and make cutouts. """ success = self.verify_input() if not success: self.statusBar().showMessage("Please fill in all fields") return # self.start_button.setText("Abort") # self.start_button.clicked.disconnect() # self.start_button.clicked.connect(self.abort) # temporary fix for non-existing abort functionality. self.start_button.setText("Working...") self.start_button.setEnabled(False) self.statusBar().showMessage("Making a list of files") QApplication.processEvents() t = self.make_catalog_table() if t is None: raise Exception("Spectra files were not found.") # Make cutouts using info in catalog. self.statusBar().showMessage("Making cutouts") output_path = os.path.join(self.save_path, self.output_dir_format) fits_cutouts, success_counter, success_table = go_make_cutouts( t, self.img_path, "cutouts", output_file_format=self.output_file_format, output_dir_format=output_path, clobber=True, apply_rotation=True, report=self.report) self.statusBar().showMessage("DONE!") # Give notice to user on status. string = "Cutouts were made for %s out of %s files\n\nSaved at: %s" %( success_counter, len(t), output_path) # save a list of failed cutouts if success_counter != len(t): self.write_skipped(t, success_table) string += "\n\nA list of spectra files " string += "without cutouts is saved in " string += "'skipped_cutout_files.txt' " string += "\n\nSaved at: %s" %os.path.join( self.save_path, "skipped_cutout_files.txt") info = QMessageBox.information(self, "Status:", string) if success_counter == 0: usr_ans = QMessageBox.question(self, '', "Would you like to load all generated cutouts into glue?", QMessageBox.Yes | QMessageBox.No) if usr_ans == QMessageBox.Yes: data = [] for i, flag in enumerate(success_table): if flag: path = output_path this_id = t["id"][i] fname = os.path.join( path, self.output_file_format.format(this_id)) data.append(load_data(fname)) self.session.data_collection.merge(*data, label=self.output_dir_format) if self.tableGen and self.TableGen is not None: self.TableGen.cutout_response(output_path, self.custom_save_path) self.close() return
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() else: basedir = osp.dirname(self.filename) filenames, _selfilter = getopenfilenames(self, title, basedir, iofunctions.load_filters) if not filenames: return elif is_text_string(filenames): filenames = [filenames] for filename in filenames: self.filename = to_text_string(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[to_text_string(item)] else: return load_func = iofunctions.load_funcs[ext] # 'import_wizard' (self.setup_io) if is_text_string(load_func): # Import data with import wizard error_message = None try: text, _encoding = encoding.read(self.filename) if self.is_internal_shell: self.editor.import_from_string(text) else: 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() monitor_set_global(self._get_sock(), var_name, clip_data) except Exception as error: error_message = str(error) else: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() if self.is_internal_shell: namespace, error_message = load_func(self.filename) interpreter = self.shellwidget.interpreter for key in list(namespace.keys()): new_key = fix_reference_name(key, blacklist=list(interpreter.namespace.keys())) if new_key != key: namespace[new_key] = namespace.pop(key) if error_message is None: interpreter.namespace.update(namespace) else: error_message = monitor_load_globals(self._get_sock(), 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>Error message:<br>%s" ) % (self.filename, error_message)) self.refresh_table()
def ask_confirmation(self, message, title="Mantid Workbench"): reply = QMessageBox.question(self, title, message, QMessageBox.Yes, QMessageBox.No) return True if reply == QMessageBox.Yes else False
def contextMenuEvent(self, event): action = self.contextMenu.exec_(self.mapToGlobal(event.pos())) if action == self.action_update_formulas: index = self.currentIndex() if index.isValid(): item = index.internalPointer() if isinstance(item, SpaceItem): pass else: if index.parent().isValid(): item = index.parent().internalPointer() else: return self.shell.update_codelist(item.itemData['fullname']) elif action == self.action_update_properties: index = self.currentIndex() if index.isValid(): item = self.currentIndex().internalPointer() if not isinstance(item, ViewItem): self.shell.update_mxproperty(item.itemData['fullname']) elif action == self.action_import_names: index = self.currentIndex() if index.isValid(): item = self.currentIndex().internalPointer() if isinstance(item, SpaceItem): has_children = True elif isinstance(item, CellsItem) or isinstance(item, RefItem): has_children = False else: return else: return if has_children: dialog = ImportNamesDialog(self) dialog.exec() if self.reply['accepted']: import_selected = self.reply['import_selected'] import_children = self.reply['import_children'] replace_existing = self.reply['replace_existing'] self.reply = None else: self.reply = None return else: import_selected = True import_children = False replace_existing = True self.shell.import_names(item.itemData['fullname'], import_selected, import_children, replace_existing ) elif action == self.action_analyze_selected: index = self.currentIndex() if index.isValid(): item = self.currentIndex().internalPointer() if isinstance(item, CellsItem): self.shell.mxanalyzer.update_object(item.itemData) elif action == self.action_new_model: dialog = NewModelDialog(self) dialog.exec() if self.reply['accepted']: name = self.reply['name'] define_var = self.reply['define_var'] if define_var: varname = self.reply['varname'] else: varname = '' self.reply = None self.shell.new_model(name, define_var, varname) else: self.reply = None elif action == self.action_new_space: if self.model(): parentList = self.model().rootItem.getSpaceContainerList() else: parentList = [] # Find current item index = self.currentIndex() if index.isValid(): name = index.internalPointer().itemData['fullname'] try: currIndex = parentList.index(name) except ValueError: currIndex = 0 else: currIndex = 0 if self.model(): model = self.model().rootItem.itemData['name'] else: model = '' dialog = NewSpaceDialog(self, parentList, currIndex) dialog.exec() if self.reply['accepted']: name = self.reply['name'] parent = self.reply['parent'] bases = self.reply['bases'] define_var = self.reply['define_var'] if define_var: varname = self.reply['varname'] else: varname = '' self.reply = None self.shell.new_space( model, parent, name, bases, define_var, varname) else: self.reply = None elif action == self.action_new_cells: if self.model(): parentList = self.model().rootItem.getChildSpaceList() else: parentList = [] # Find current item index = self.currentIndex() if index.isValid(): name = index.internalPointer().itemData['namedid'] try: currIndex = parentList.index(name) except ValueError: currIndex = 0 else: currIndex = 0 if self.model(): model = self.model().rootItem.itemData['name'] else: model = '' dialog = NewCellsDialog(self, parentList, currIndex) dialog.exec() if self.reply['accepted']: name = self.reply['name'] parent = self.reply['parent'] formula = self.reply['formula'] define_var = self.reply['define_var'] if define_var: varname = self.reply['varname'] else: varname = '' self.reply = None self.shell.new_cells( model, parent, name, formula, define_var, varname) else: self.reply = None elif action == self.action_read_model: dialog = ReadModelDialog(self, modelpath=self.mx_widget.last_modelpath) dialog.exec() if self.reply['accepted']: modelpath = self.reply['directory'] name = self.reply['name'] define_var = self.reply['define_var'] if define_var: varname = self.reply['varname'] else: varname = '' self.reply = None self.shell.read_model(modelpath, name, define_var, varname) self.mx_widget.last_modelpath = modelpath else: self.reply = None elif action == self.action_write_model: model = self.container.current_widget().model_selector.get_selected_model() if not model: QMessageBox.critical(self, "Error", "No model exits.") return dialog = WriteModelDialog(self, modelpath=self.mx_widget.last_modelpath) dialog.exec() if self.reply['accepted']: modelpath = self.reply['directory'] + "/" + self.reply['name'] backup = self.reply['backup'] zipmodel = self.reply['zipmodel'] self.reply = None self.shell.write_model(model, modelpath, backup, zipmodel) self.mx_widget.last_modelpath = modelpath else: self.reply = None elif action == self.action_delete_model: model = self.container.current_widget().model_selector.get_selected_model() if model: answer = QMessageBox.question( self, _("Delete Model"), _("Do you want to delete %s?" % model), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.shell.del_model(model) else: return else: QMessageBox.critical(self, "Error", "No model exits.") elif action == self.action_delete_selected: index = self.currentIndex() if index.isValid(): item = index.internalPointer() if isinstance(item, ViewItem) or isinstance(item, ItemSpaceItem): pass else: if index.parent().isValid(): parent = index.parent().internalPointer().fullname else: parent = self.container.current_widget().model_selector.get_selected_model() assert parent answer = QMessageBox.question( self, _("Delete Selected"), _("Do you want to delete %s?" % item.name), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.shell.del_object(parent, item.name) QMessageBox.information( self, "Notice", "'%s' is deleted from '%s'" % (item.name, parent))
def openssh_tunnel(self, lport, rport, server, remoteip='127.0.0.1', keyfile=None, password=None, timeout=0.4): """ We decided to replace pyzmq's openssh_tunnel method to work around issue https://github.com/zeromq/pyzmq/issues/589 which was solved in pyzmq https://github.com/zeromq/pyzmq/pull/615 """ ssh = "ssh " if keyfile: ssh += "-i " + keyfile if ':' in server: server, port = server.split(':') ssh += " -p %s" % port cmd = "%s -O check %s" % (ssh, server) (output, exitstatus) = pexpect.run(cmd, withexitstatus=True) if not exitstatus: pid = int(output[output.find("(pid=") + 5:output.find(")")]) cmd = "%s -O forward -L 127.0.0.1:%i:%s:%i %s" % (ssh, lport, remoteip, rport, server) (output, exitstatus) = pexpect.run(cmd, withexitstatus=True) if not exitstatus: atexit.register(_stop_tunnel, cmd.replace("-O forward", "-O cancel", 1)) return pid cmd = "%s -f -S none -L 127.0.0.1:%i:%s:%i %s sleep %i" % ( ssh, lport, remoteip, rport, server, timeout) # pop SSH_ASKPASS from env env = os.environ.copy() env.pop('SSH_ASKPASS', None) ssh_newkey = 'Are you sure you want to continue connecting' tunnel = pexpect.spawn(cmd, env=env) failed = False while True: try: i = tunnel.expect([ssh_newkey, '[Pp]assword:'], timeout=.1) if i == 0: host = server.split('@')[-1] question = _("The authenticity of host <b>%s</b> can't be " "established. Are you sure you want to continue " "connecting?") % host reply = QMessageBox.question(self, _('Warning'), question, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: tunnel.sendline('yes') continue else: tunnel.sendline('no') raise RuntimeError( _("The authenticity of the host can't be established")) if i == 1 and password is not None: tunnel.sendline(password) except pexpect.TIMEOUT: continue except pexpect.EOF: if tunnel.exitstatus: raise RuntimeError(_("Tunnel '%s' failed to start") % cmd) else: return tunnel.pid else: if failed or password is None: raise RuntimeError(_("Could not connect to remote host")) # TODO: Use this block when pyzmq bug #620 is fixed # # Prompt a passphrase dialog to the user for a second attempt # password, ok = QInputDialog.getText(self, _('Password'), # _('Enter password for: ') + server, # echo=QLineEdit.Password) # if ok is False: # raise RuntimeError('Could not connect to remote host.') tunnel.sendline(password) failed = True
def __on_mso(self, mso): ''' Handles mso message from the device sent after a getmso is issued. :param mso: the mso. ''' version = mso['versions']['swVer'] version = version[1:] if version[0] == 'v' else version try: self.__supports_shelf = semver.parse_version_info( version) > semver.parse_version_info('1.4.0') except: logger.error(f"Unable to parse version {mso['versions']['swVer']}") result = QMessageBox.question( self, 'Supports Shelf Filters?', f"Reported software version is " f"\n\n {version}" f"\n\nDoes this version support shelf filters?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) self.__supports_shelf = result == QMessageBox.Yes speakers = mso['speakers']['groups'] channels = ['lf', 'rf'] for group in [ s for s, v in speakers.items() if 'present' in v and v['present'] is True ]: if group[0:2] == 'lr' and len(group) > 2: channels.append('l' + group[2:]) channels.append('r' + group[2:]) else: channels.append(group) peq_slots = mso['peq']['slots'] class Filters(dict): def __init__(self): super().__init__() def __missing__(self, key): self[key] = CompleteFilter(fs=HTP1_FS, sort_by_id=True) return self[key] tmp1 = Filters() tmp2 = Filters() raw_filters = {c: [] for c in channels} unknown_channels = set() for idx, s in enumerate(peq_slots): for c in channels: if c in s['channels']: tmp1[c].save( self.__convert_to_filter(s['channels'][c], idx)) tmp2[c].save( self.__convert_to_filter(s['channels'][c], idx)) raw_filters[c].append(s['channels'][c]) else: unknown_channels.add(c) if unknown_channels: peq_channels = peq_slots[0]['channels'].keys() logger.error( f"Unknown channels encountered [peq channels: {peq_channels}, unknown: {unknown_channels}]" ) from model.report import block_signals with block_signals(self.filtersetSelector): now = self.filtersetSelector.currentText() self.filtersetSelector.clear() now_idx = -1 for idx, c in enumerate(channels): self.filtersetSelector.addItem(c) if c == now: now_idx = idx if now_idx > -1: self.filtersetSelector.setCurrentIndex(now_idx) self.__filters_by_channel = tmp1 self.__current_device_filters_by_channel = tmp2 self.__filters.filter = self.__filters_by_channel[ self.filtersetSelector.itemText(0)] if not self.__channel_to_signal: self.load_from_signals() self.__magnitude_model.redraw() self.syncStatus.setIcon(qta.icon('fa5s.link')) self.__last_received_msoupdate = None self.__last_requested_msoupdate = None self.showDetailsButton.setEnabled(False)
def send_filters_to_device(self): ''' Sends the selected filters to the device ''' if self.__in_complex_mode(): ops, unsupported_filter_types_per_channel = self.__convert_filter_mappings_to_ops( ) channels_to_update = [ i.text().split(' ')[1] for i in self.filterMapping.selectedItems() ] unsynced_channels = [] for c, s in self.__channel_to_signal.items(): if s is not None: if c not in channels_to_update: if c in self.__current_device_filters_by_channel: current = s.filter device = self.__current_device_filters_by_channel[ c] if current != device: unsynced_channels.append(c) if unsynced_channels: result = QMessageBox.question( self, 'Sync all changed channels?', f"Filters in {len(unsynced_channels)} channels have changed but will not be " f"synced to the HTP-1." f"\n\nChannels: {', '.join(sorted([k for k in unsynced_channels]))}" f"\n\nDo you want to sync all changed channels? ", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if result == QMessageBox.Yes: for c in unsynced_channels: for i in range(self.filterMapping.count()): item: QListWidgetItem = self.filterMapping.item(i) if c == item.text().split(' ')[1]: item.setSelected(True) self.send_filters_to_device() return else: ops, unsupported_filter_types_per_channel = self.__convert_current_filter_to_ops( ) do_send = True if unsupported_filter_types_per_channel: printed = '\n'.join([ f"{k} - {', '.join(v)}" for k, v in unsupported_filter_types_per_channel.items() ]) result = QMessageBox.question( self, 'Unsupported Filters Detected', f"Unsupported filter types found in the filter set:" f"\n\n{printed}" f"\n\nDo you want sync the supported filters only? ", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) do_send = result == QMessageBox.Yes if do_send: from app import wait_cursor with wait_cursor(): all_ops = [op for slot_ops in ops for op in slot_ops] self.__last_requested_msoupdate = all_ops msg = f"changemso {json.dumps(self.__last_requested_msoupdate)}" logger.debug(f"Sending to {self.ipAddress.text()} -> {msg}") self.__spinner = StoppableSpin(self.syncStatus, 'sync') spin_icon = qta.icon('fa5s.spinner', color='green', animation=self.__spinner) self.syncStatus.setIcon(spin_icon) self.__ws_client.sendTextMessage(msg)
def apply_multiple_actions(self): """ """ logger.debug('') self.conda_errors = [] prefix = self.prefix if prefix == self.root_prefix: name = 'root' elif self.api.conda_environment_exists(prefix=prefix): name = osp.basename(prefix) else: name = prefix actions = self.table.get_actions() if actions is None: return self._multiple_process = deque() pip_actions = actions[C.PIP_PACKAGE] conda_actions = actions[C.CONDA_PACKAGE] pip_remove = pip_actions.get(C.ACTION_REMOVE, []) conda_remove = conda_actions.get(C.ACTION_REMOVE, []) conda_install = conda_actions.get(C.ACTION_INSTALL, []) conda_upgrade = conda_actions.get(C.ACTION_UPGRADE, []) conda_downgrade = conda_actions.get(C.ACTION_DOWNGRADE, []) message = '' template_1 = '<li><b>{0}={1}</b></li>' template_2 = '<li><b>{0}: {1} -> {2}</b></li>' if pip_remove: temp = [template_1.format(i['name'], i['version_to']) for i in pip_remove] message += ('The following pip packages will be removed: ' '<ul>' + ''.join(temp) + '</ul>') if conda_remove: temp = [template_1.format(i['name'], i['version_to']) for i in conda_remove] message += ('<br>The following conda packages will be removed: ' '<ul>' + ''.join(temp) + '</ul>') if conda_install: temp = [template_1.format(i['name'], i['version_to']) for i in conda_install] message += ('<br>The following conda packages will be installed: ' '<ul>' + ''.join(temp) + '</ul>') if conda_downgrade: temp = [template_2.format( i['name'], i['version_from'], i['version_to']) for i in conda_downgrade] message += ('<br>The following conda packages will be downgraded: ' '<ul>' + ''.join(temp) + '</ul>') if conda_upgrade: temp = [template_2.format( i['name'], i['version_from'], i['version_to']) for i in conda_upgrade] message += ('<br>The following conda packages will be upgraded: ' '<ul>' + ''.join(temp) + '</ul>') message += '<br>' if self.apply_actions_dialog: dlg = self.apply_actions_dialog(message, parent=self) dlg.update_style_sheet(style_sheet=self.style_sheet) reply = dlg.exec_() else: reply = QMessageBox.question(self, 'Proceed with the following actions?', message, buttons=QMessageBox.Ok | QMessageBox.Cancel) if reply: # Pip remove for pkg in pip_remove: status = (_('Removing pip package <b>') + pkg['name'] + '</b>' + _(' from <i>') + name + '</i>') pkgs = [pkg['name']] def trigger(prefix=prefix, pkgs=pkgs): return lambda: self.api.pip_remove(prefix=prefix, pkgs=pkgs) self._multiple_process.append([status, trigger()]) # Process conda actions if conda_remove: status = (_('Removing conda packages <b>') + '</b>' + _(' from <i>') + name + '</i>') pkgs = [i['name'] for i in conda_remove] def trigger(prefix=prefix, pkgs=pkgs): return lambda: self.api.conda_remove(pkgs=pkgs, prefix=prefix) self._multiple_process.append([status, trigger()]) if conda_install: pkgs = ['{0}={1}'.format(i['name'], i['version_to']) for i in conda_install] status = (_('Installing conda packages <b>') + '</b>' + _(' on <i>') + name + '</i>') def trigger(prefix=prefix, pkgs=pkgs): return lambda: self.api.conda_install( prefix=prefix, pkgs=pkgs, channels=self._active_channels, token=self.token) self._multiple_process.append([status, trigger()]) # Conda downgrade if conda_downgrade: status = (_('Downgrading conda packages <b>') + '</b>' + _(' on <i>') + name + '</i>') pkgs = ['{0}={1}'.format(i['name'], i['version_to']) for i in conda_downgrade] def trigger(prefix=prefix, pkgs=pkgs): return lambda: self.api.conda_install( prefix=prefix, pkgs=pkgs, channels=self._active_channels, token=self.token) self._multiple_process.append([status, trigger()]) # Conda update if conda_upgrade: status = (_('Upgrading conda packages <b>') + '</b>' + _(' on <i>') + name + '</i>') pkgs = ['{0}={1}'.format(i['name'], i['version_to']) for i in conda_upgrade] def trigger(prefix=prefix, pkgs=pkgs): return lambda: self.api.conda_install( prefix=prefix, pkgs=pkgs, channels=self._active_channels, token=self.token) self._multiple_process.append([status, trigger()]) self._run_multiple_actions()
def _confirm_quit(self, callback): quit_message = QMessageBox.question(self, 'Quitting Application', 'Exit Application?', QMessageBox.Yes | QMessageBox.No) if quit_message == QMessageBox.Yes: callback()