def do_run_file(self): """ Run a file selected by the user. """ dialog = FileDialog(wildcard=FileDialog.WILDCARD_PY) result = dialog.open() if result == OK: self.shell.execute_file(dialog.path)
# (C) Copyright 2005-2022 Enthought, Inc., Austin, TX # All rights reserved. # # This software is provided without warranty under the terms of the BSD # license included in LICENSE.txt and may be redistributed only under # the conditions described in the aforementioned license. The license # is also available online at http://www.enthought.com/licenses/BSD.txt # # Thanks for using Enthought open source! from pyface.api import FileDialog, OK # display a file dialog for saving a Python file dialog = FileDialog(parent=None, action="save as", wildcard="*.py") if dialog.open() == OK: print(f"Save to {dialog.path}")
def open_file(self, path): try: new_workflow = load_yaml(path) # a few things to take care of when reloading. # we do this in the try block to catch people who # load valid YAML files that aren't from cytoflow. for wi_idx, wi in enumerate(new_workflow): # get wi lock wi.lock.acquire() # clear the wi status wi.status = "loading" # re-link the linked list. if wi_idx > 0: wi.previous_wi = new_workflow[wi_idx - 1] if wi_idx < len(new_workflow) - 1: wi.next_wi = new_workflow[wi_idx + 1] except yaml.parser.ParserError as e: error(None, "Parser error loading {} -- is it a Cytoflow file?\n\n{}" .format(path, str(e))) return except Exception as e: error(None, "{} loading {} -- is it a Cytoflow file?\n\n{}" .format(e.__class__.__name__, path, str(e))) return # are we just running a smoke test? if 'startup_test' in new_workflow[0].metadata: def quit_app(app): app.exit(force = True) from pyface.timer.api import do_after do_after(5*1000, quit_app, self.application) return # check that the FCS files are all there wi = new_workflow[0] assert(wi.operation.id == "edu.mit.synbio.cytoflow.operations.import") missing_tubes = 0 for tube in wi.operation.tubes: file = pathlib.Path(tube.file) if not file.exists(): missing_tubes += 1 if missing_tubes == len(wi.operation.tubes): warning(self.window.control, "Cytoflow couldn't find any of the FCS files from that " "workflow. If they've been moved, please open one FCS " "file to show Cytoflow where they've been moved to.") dialog = FileDialog(parent = self.window.control, action = 'open', wildcard = (FileDialog.create_wildcard("FCS files", "*.fcs *.lmd"))) # @UndefinedVariable if dialog.open() == OK: # find the "best" file match -- ie, the one with the longest # tail match fcs_path = pathlib.Path(dialog.path).parts best_path_len = -1 for tube in wi.operation.tubes: tube_path = pathlib.Path(tube.file).parts for i in range(len(fcs_path)): if list(reversed(fcs_path))[:i] == list(reversed(tube_path))[:i] and i > best_path_len: best_path_len = i if best_path_len >= 0: for tube in wi.operation.tubes: tube_path = pathlib.Path(tube.file).parts new_path = fcs_path[:-1 * best_path_len] + tube_path[-1 * best_path_len :] tube.file = str(pathlib.Path(*new_path)) elif missing_tubes > 0: warning(self.window.control, "Cytoflow couldn't find some of the FCS files from that " "workflow. You'll need to re-load them from the Import " "operation.") # replace the current workflow with the one we just loaded if False: # for debugging the loading of things from .event_tracer import record_events with record_events() as container: self.model.workflow = new_workflow container.save_to_directory(os.getcwd()) else: self.model.workflow = new_workflow self.model.modified = False for wi in self.model.workflow: wi.lock.release() if self.model.debug: self.model.run_all() else: ret = confirm(parent = None, message = "Do you want to execute the workflow now?", title = "Run workflow?") if ret == YES: self.model.run_all()
def _save_the_image_fired(self): dlg = FileDialog(action='save as') if dlg.open() == OK: plt.savefig(dlg.path, size=(800, 800), dpi=300)
def _on_add_tubes(self): """ Handle "Add tubes..." button. Add tubes to the experiment. """ file_dialog = FileDialog() file_dialog.wildcard = "Flow cytometry files (*.fcs)|*.fcs|" file_dialog.action = 'open files' file_dialog.open() if file_dialog.return_code != PyfaceOK: return for path in file_dialog.paths: try: tube_meta = fcsparser.parse(path, meta_data_only = True, reformat_meta = True) #tube_channels = tube_meta["_channels_"].set_index("$PnN") except Exception as e: raise RuntimeError("FCS reader threw an error on tube {0}: {1}"\ .format(path, e.value)) # if we're the first tube loaded, create a dummy experiment if not self.model.dummy_experiment: self.model.dummy_experiment = ImportOp(tubes = [CytoflowTube(file = path)], coarse_events = 1).apply() # check the next tube against the dummy experiment try: check_tube(path, self.model.dummy_experiment) except util.CytoflowError as e: error(None, e.__str__(), "Error importing tube") return tube = Tube() for trait_name, trait in self.model.tube_traits.items(): tube.add_trait(trait_name, trait) # this magic makes sure the trait is actually defined # in tube.__dict__, so it shows up in trait_names etc. tube.trait_set(**{trait_name : trait.default_value}) if trait.condition: tube.on_trait_change(self._try_multiedit, trait_name) tube.trait_set(file = path, parent = self.model) if '$SRC' in tube_meta: self._add_metadata("$SRC", "$SRC", Str(condition = False)) tube.trait_set(**{"$SRC" : tube_meta['$SRC']}) if 'TUBE NAME' in tube_meta: self._add_metadata("TUBE NAME", "TUBE NAME", Str(condition = False)) tube.trait_set(**{"TUBE NAME" : tube_meta['TUBE NAME']}) if '$SMNO' in tube_meta: self._add_metadata("$SMNO", "$SMNO", Str(condition = False)) tube.trait_set(**{"$SMNO" : tube_meta['$SMNO']}) if 'WELL ID' in tube_meta: self._add_metadata("Row", "Row", Str(condition = False)) self._add_metadata("Col", "Col", Int(condition = False)) pos = tube_meta['WELL ID'] row = pos[0] col = int(pos[1:3]) tube.trait_set(**{"Row" : row, "Col" : col}) self.model.tubes.append(tube)
def get_file_path(action='save as', **kw): from pyface.api import FileDialog, OK dlg = FileDialog(action=action, **kw) if dlg.open() == OK: return dlg.path
def open(self): """ Shows a dialog to open a file. """ dialog = FileDialog(parent=self.window.control, wildcard='*.jpg') if dialog.open() == OK: self._open_file(dialog.path)
def _b_save_pipeline_fired(self): saver = FileDialog(action='save as') if saver.open() == OK: self.save_pipeline(saver.path)
def _b_load_pipeline_fired(self): loader = FileDialog(title='Open file') if loader.open() == OK: self.load_pipeline(loader.path)
def open(self): """ Shows a dialog to open a Python file. """ dialog = FileDialog(parent=self.window.control, wildcard='*.py') if dialog.open() == OK: self.create_editor(dialog.path)
def perform(self, event, cfile=None): """ Performs the action. """ logger.info('Performing open connectome file action') # helper variable to use this function not only in the menubar exec_as_funct = True if cfile is None: # get the instance of the current CFile # with the help of the Service Registry cfile = self.window.application.get_service( 'cviewer.plugins.cff2.cfile.CFile') exec_as_funct = False wildcard = "All files (*.*)|*.*|" \ "Nifti-1 (*.nii.gz)|*.nii.gz|" \ "Gifti (*.gii)|*.gii|" \ "TrackVis tracks (*.trk)|*.trk|" \ "Network Pickle (*.gpickle)|*.gpickle|" \ "Network GraphML (*.graphml)|*.graphml|" \ "Numpy Data (*.npy)|*.npy|" \ "Pickle Data (*.pkl)|*.pkl|" \ "Text Data (*.txt)|*.txt|" \ "CSV Data (*.csv)|*.csv|" dlg = FileDialog(wildcard=wildcard,title="Choose a file",\ resizeable=False, \ default_directory=preference_manager.cviewerui.cffpath,) if dlg.open() == OK: if not os.path.isfile(dlg.path): logger.error("File '%s' does not exist!" % dlg.path) return logger.info('Read file: %s' % dlg.path) fname = os.path.split(dlg.paths[0])[-1] if os.path.exists(dlg.paths[0]) and (fname.endswith('.nii.gz') or fname.endswith('.nii')): cvol = cfflib.CVolume.create_from_nifti( name=fname, nii_filename=dlg.paths[0]) cfile.obj.add_connectome_volume(cvol) elif os.path.exists(dlg.paths[0]) and fname.endswith('.gii'): csurf = cfflib.CSurface.create_from_gifti( name=fname, gii_filename=dlg.paths[0]) cfile.obj.add_connectome_surface(csurf) elif os.path.exists(dlg.paths[0]) and fname.endswith('.trk'): ctrk = cfflib.CTrack(name=fname, src=dlg.paths[0]) cfile.obj.add_connectome_track(ctrk) elif os.path.exists(dlg.paths[0]) and fname.endswith('.gpickle'): ctrk = cfflib.CNetwork(name=fname, src=dlg.paths[0], fileformat="NXGPickle") cfile.obj.add_connectome_network(ctrk) elif os.path.exists(dlg.paths[0]) and fname.endswith('.graphml'): ctrk = cfflib.CNetwork.create_from_graphml( name=fname, ml_filename=dlg.paths[0]) cfile.obj.add_connectome_network(ctrk) elif os.path.exists(dlg.paths[0]) and fname.endswith('.npy'): cdat = cfflib.CData(name=fname, src=dlg.paths[0], fileformat='NumPy') cfile.obj.add_connectome_data(cdat) elif os.path.exists(dlg.paths[0]) and fname.endswith('.csv'): cdat = cfflib.CData(name=fname, src=dlg.paths[0], fileformat='CSV') cfile.obj.add_connectome_data(cdat) elif os.path.exists(dlg.paths[0]) and fname.endswith('.txt'): cdat = cfflib.CData(name=fname, src=dlg.paths[0], fileformat='TXT') cfile.obj.add_connectome_data(cdat) elif os.path.exists(dlg.paths[0]) and fname.endswith('.pkl'): cdat = cfflib.CData(name=fname, src=dlg.paths[0], fileformat='Pickle') cfile.obj.add_connectome_data(cdat) else: logger.info('Could not load file: ' + dlg.paths) cfile.update_children()
def _get_user_location(self, project, parent_window): """ Prompt the user for a new location for the specified project. Returns the chosen location or, if the user cancelled, an empty string. """ # The dialog to use depends on whether we're prompting for a file or # a directory. if self.model_service.are_projects_files(): dialog = FileDialog( parent=parent_window, title="Save Project As", default_path=project.location, action="save as", ) title_type = "File" else: dialog = DirectoryDialog( parent=parent_window, message="Choose a Directory for the Project", default_path=project.location, action="open", ) title_type = "Directory" # Prompt the user for a new location and then validate we're not # overwriting something without getting confirmation from the user. result = "" while dialog.open() == OK: location = dialog.path.strip() # If the chosen location doesn't exist yet, we're set. if not os.path.exists(location): logger.debug("Location [%s] does not exist yet.", location) result = location break # Otherwise, confirm with the user that they want to overwrite the # existing files or directories. If they don't want to, then loop # back and prompt them for a new location. else: logger.debug( "Location [%s] exists. Prompting for overwrite " "permission.", location, ) message = "Overwrite %s?" % location title = "Project %s Exists" % title_type action = confirm(parent_window, message, title) if action == YES: # Only use the location if we successfully remove the # existing files or directories at that location. try: self.model_service.clean_location(location) result = location break # Otherwise, display the remove error to the user and give # them another chance to pick another location except Exception as e: msg = str(e) title = "Unable To Overwrite %s" % location information(parent_window, msg, title) logger.debug("Returning user location [%s]", result) return result
def _single_load(self): dialog = FileDialog(action="open", wildcard=self.file_wildcard) dialog.open() if dialog.return_code == OK: return dialog.path
def _do_convert_fired(self): dialog = FileDialog(action = 'open files', wildcard = (FileDialog.create_wildcard("FCS files", "*.fcs"))) #@UndefinedVariable if dialog.open() == OK: self.model.input_files = dialog.paths
def save_data_file(sourceFile, destination=None, subdirectory=None, user=None, verbose=True): """ Function used to save (i.e copy) a data file into a directory of choice after an experimental session Parameters: sourceFile - the path of the file that was generated by the experimental session and that resides in the local file system. destination - An optional destination path where to save the file. File name may be included or not at the end of the path. subdirectory - An optional subdirectory, i.e folder, to add to the destination path. For example, if the destination path is a folder called "experiments", the subdirectory can be a child folder of "experiments", named after the experiment type ("behaviour" for instance). user - An optional parameter to indicate which user is conducting the experiments. If supplied, and if no destination is passed, a configuration file is looked up to retrieve the folder into which the user is usually copying data files. If no destination and no user is provided, a default directory is looked up in the configuration file as the default destination of the file to be copied. Either way, a save as dialog box will appear and the user will have final say. """ # Validate file parameter passed. Also check to see if the path provided is lacking the default .h5 extension if not os.path.exists(sourceFile): if not os.path.exists(sourceFile + ".h5"): # Error message if the source file path could not be found in the system error(None,"Woah there!\n\n1. Couldn't find the file that you want to copy.\ \n2. Check to see if it exists in the file system and the path provided is correct"\ , "File Finding Police report") return else: # File exists but has an extension and one was not provided in the path given. # Add it to file path descriptor sourceFile += ".h5" # information(None, "the filename of source provided lacked the \".h5\" extension.\ # \n\nA file with the extension was found and presumed to be the source meant"\ # ,"Path Police report") # Get file extension fileExtension = os.path.splitext(sourceFile)[-1] # Get the destination file name from the path provided destinationFile = os.path.split(sourceFile)[-1] destinationFolder = "" # If file has no extension, add the default .h5 extension to destination file name if fileExtension == "": warning(None, "The file you are trying to save has no extension\n\nAdding \".h5\" to the name of destination file"\ , ".h5 Extension Police") destinationFile = file + ".h5" # The file provided has different extension. Display a warning but do nothing. elif fileExtension != ".h5": warning(None, "Your file to be copied does not have an \".h5\" extension\n\nNo action taken."\ , "h5 Extension Police") # Display confirmation dialog for copying the file dlg = ConfirmationDialog( title="You there!", yes_label="Yes Please!", no_label="Nah...", message= "Would you like to copy the data file generated after the session?\ \n\nIf you say Nah... and change your mind, you'll have to copy it manually later" ) # Open the dialog GUI dlg.open() # User provided a destination path if destination: # Check to see if destination is a file name with an extension. destinationExtension = os.path.splitext(destination)[-1] if destinationExtension: # Is it .h5? If not, warn but don't override. if destinationExtension != ".h5": warning(None, "Your destination filename does not have an \".h5\" extension\n\nNo action taken."\ , "h5 Extension Police") destinationFolder, destinationFile = os.path.split(destination) # Assume destination is directory since there is no extension. else: destinationFolder = destination # Look up a default destination from the config file since no <destination> parameter was provided. else: configFile = os.environ.get("Voyeur_config") config = ConfigObj(configFile) # A user specific folder was provided. if user: destinationFolder = config['server']['folder']['data']['user'] # Use default data folder as read from the config file. else: destinationFolder = config['server']['folder']['data']['default'] # User provided a subdirectory, i.e subfolder, into which to place the file. if subdirectory: # The subdirectory provided has common path with the directory provided. Display warning but do nothing. if os.path.commonprefix((destination, subdirectory)): warning(None, "Friendly warning!\n<subdirectory> parameter provided has a common path with the <destination>\ path parameter\n\n1. No action taken.\n2. Check your final destination path to make sure it is what you want"\ , "Path Police report") destinationFolder = os.path.join(destinationFolder, subdirectory) # Path of the destination of file to be copied. destinationPath = os.path.join(destinationFolder, destinationFile) if dlg.return_code == YES: # A file with same name exists. if os.path.isfile(destinationPath): warning( None, "A file with given path already exists!\n\n1. No action taken\ \n2. Make sure to either rename file or choose different folder", "Path Police report") # Provided folder does not exist. Make one and inform the user. elif not os.path.isdir(destinationFolder): information(None, "Making a new folder to put the file into...", "Information Transparency report") # TODO: What if this results in an exception? Catch and do something? # TODO: Keep track of made directories so we may delete them later os.makedirs(os.path.abspath(destinationFolder)) # The save as dialog box. # TODO: change wildcard to current extension wildcard dialog = FileDialog(action="save as", title = "Select directory into which the data file will be copied",\ wildcard = "*.*", default_directory = destinationFolder, default_filename = destinationFile) #*.h5||| elif dlg.return_code == NO and verbose: information(None, "No file was copied.\n\nIf you change your mind, you will have to transfer the data file manually."\ , "Information Transparency report") return dialog.open() # User clicked Save and successful input received. if dialog.return_code == OK: # The actual copying of the file. TODO: See if the copy2 function throws an exception copy2(sourceFile, dialog.path) # The user clicked Cancel. elif dialog.return_code == CANCEL: information(None, "No file was copied.\n\nIf you change your mind, you will have to transfer the data file manually."\ , "Information Transparency report") #TODO: update the Voyeur config file after asking user return dialog.path
def _settings_import_from_file_button_fired(self): """Imports settings from INI file and sends settings write to device for each entry. Prompts user for input file. Should handle all expected error cases. """ # Prompt user for file file = FileDialog(action='open', default_directory=swift_path, default_filename='config.ini', wildcard='*.ini') is_ok = file.open() if is_ok == OK: # file chosen successfully print('Importing settings from local path {} to device.'.format( file.path)) parser = configparser.ConfigParser() # the optionxform is needed to handle case sensitive settings parser.optionxform = str try: with open(file.path, 'r') as f: parser.read_file(f) except configparser.ParsingError as e: # file formatted incorrectly print( 'Unable to parse ini file due to ParsingError: {}.'.format( e)) print('Unable to import settings to device.') return except IOError as e: # IOError (likely a file permission issue) print('Unable to read ini file due to IOError: {}'.format(e)) print('Unable to import settings to device.') return # Iterate over each setting and set in the GUI. # Use the same mechanism as GUI to do settings write to device for section, settings in parser.items(): this_section = self.settings.get(section, None) for setting, value in settings.items(): if this_section: this_setting = this_section.get(setting, None) if this_setting: this_setting.value = value else: print(( "Unable to import settings from file. Setting \"{0}\" in section \"{1}\"" " has not been sent from device.").format( setting, section)) return else: print(( "Unable to import settings from file." " Setting section \"{0}\" has not been sent from device." ).format(section)) return # Double check that no settings had a write failure. All settings should exist if we get to this point. a = TimedDelayStoppableThread( SETTINGS_REVERT_TIMEOUT + 0.1, target=self._wait_for_any_write_failures, args=(dict(parser))) a.start() else: pass # No error message here because user likely pressed cancel when choosing file
def do_load_data(self, info): the_pybert = info.object dlg = FileDialog(action='open', wildcard='*.pybert_data', default_path=the_pybert.data_file) if dlg.open() == OK: try: with open(dlg.path, 'rt') as the_file: the_plotdata = pickle.load(the_file) if(type(the_plotdata) is not PyBertData): raise Exception("The data structure read in is NOT of type: ArrayPlotData!") for prop, value in the_plotdata.the_data.arrays.iteritems(): the_pybert.plotdata.set_data(prop + '_ref', value) the_pybert.data_file = dlg.path # Add reference plots, if necessary. # - time domain for (container, suffix, has_both) in [ (the_pybert.plots_h.component_grid.flat, 'h', False), (the_pybert.plots_s.component_grid.flat, 's', True), (the_pybert.plots_p.component_grid.flat, 'p', False), ]: if(not 'Reference' in container[0].plots): (ix, prefix) = (0, 'chnl') item_name = prefix + "_" + suffix + "_ref" container[ix].plot(("t_ns_chnl", item_name), type="line", color="darkcyan", name="Inc_ref") for (ix, prefix) in [ (1, 'tx'), (2, 'ctle'), (3, 'dfe'), ]: item_name = prefix + "_out_" + suffix + "_ref" container[ix].plot(("t_ns_chnl", item_name), type="line", color="darkmagenta", name="Cum_ref") if(has_both): for (ix, prefix) in [ (1, 'tx'), (2, 'ctle'), (3, 'dfe'), ]: item_name = prefix + "_" + suffix + "_ref" container[ix].plot(("t_ns_chnl", item_name), type="line", color="darkcyan", name="Inc_ref") # - frequency domain for (container, suffix, has_both) in [ (the_pybert.plots_H.component_grid.flat, 'H', True) ]: if(not 'Reference' in container[0].plots): (ix, prefix) = (0, 'chnl') item_name = prefix + "_" + suffix + "_ref" container[ix].plot(("f_GHz", item_name), type="line", color="darkcyan", name="Inc_ref", index_scale='log') for (ix, prefix) in [ (1, 'tx'), (2, 'ctle'), (3, 'dfe'), ]: item_name = prefix + "_out_" + suffix + "_ref" container[ix].plot(("f_GHz", item_name), type="line", color="darkmagenta", name="Cum_ref", index_scale='log') if(has_both): for (ix, prefix) in [ (1, 'tx'), (2, 'ctle'), (3, 'dfe'), ]: item_name = prefix + "_" + suffix + "_ref" container[ix].plot(("f_GHz", item_name), type="line", color="darkcyan", name="Inc_ref", index_scale='log') except Exception as err: print item_name err.message = "The following error occured:\n\t{}\nThe waveform data was NOT loaded.".format(err.message) the_pybert.handle_error(err)
def _save_fig_btn_fired(self): dlg = FileDialog(action='save as') if dlg.open() == OK: self.savefig(dlg.path + ".png", dpi=300) self.savefig(dlg.path + ".eps") self.savefig(dlg.path + ".pdf")
def do_load_data(self, info): """Read in the pickled data.'""" the_pybert = info.object dlg = FileDialog(action="open", wildcard="*.pybert_data", default_path=the_pybert.data_file) if dlg.open() == OK: try: with open(dlg.path, "rb") as the_file: the_plotdata = pickle.load(the_file) if not isinstance(the_plotdata, PyBertData): raise Exception( "The data structure read in is NOT of type: ArrayPlotData!" ) for prop, value in the_plotdata.the_data.arrays.items(): the_pybert.plotdata.set_data(prop + "_ref", value) the_pybert.data_file = dlg.path # Add reference plots, if necessary. # - time domain for (container, suffix, has_both) in [ (the_pybert.plots_h.component_grid.flat, "h", False), (the_pybert.plots_s.component_grid.flat, "s", True), (the_pybert.plots_p.component_grid.flat, "p", False), ]: if "Reference" not in container[0].plots: (ix, prefix) = (0, "chnl") item_name = prefix + "_" + suffix + "_ref" container[ix].plot(("t_ns_chnl", item_name), type="line", color="darkcyan", name="Inc_ref") for (ix, prefix) in [(1, "tx"), (2, "ctle"), (3, "dfe")]: item_name = prefix + "_out_" + suffix + "_ref" container[ix].plot(("t_ns_chnl", item_name), type="line", color="darkmagenta", name="Cum_ref") if has_both: for (ix, prefix) in [(1, "tx"), (2, "ctle"), (3, "dfe")]: item_name = prefix + "_" + suffix + "_ref" container[ix].plot(("t_ns_chnl", item_name), type="line", color="darkcyan", name="Inc_ref") # - frequency domain for (container, suffix, has_both) in [ (the_pybert.plots_H.component_grid.flat, "H", True) ]: if "Reference" not in container[0].plots: (ix, prefix) = (0, "chnl") item_name = prefix + "_" + suffix + "_ref" container[ix].plot(("f_GHz", item_name), type="line", color="darkcyan", name="Inc_ref", index_scale="log") for (ix, prefix) in [(1, "tx"), (2, "ctle"), (3, "dfe")]: item_name = prefix + "_out_" + suffix + "_ref" container[ix].plot( ("f_GHz", item_name), type="line", color="darkmagenta", name="Cum_ref", index_scale="log", ) if has_both: for (ix, prefix) in [(1, "tx"), (2, "ctle"), (3, "dfe")]: item_name = prefix + "_" + suffix + "_ref" container[ix].plot( ("f_GHz", item_name), type="line", color="darkcyan", name="Inc_ref", index_scale="log", ) except Exception as err: error_message = f"The following error occured while processing item: {item_name}:\n \ \t{err}\nThe configuration was NOT saved." the_pybert.log( "Exception raised by pybert.pybert_view.MyHandler.do_load_data().", exception=RuntimeError(error_message))
def _path_factory(self): dlg = FileDialog(action='save as') if dlg.open() == OK: return dlg.path
def perform(self, event=None): logger.info('OpenFileAction.perform()') dialog = FileDialog(parent=self.window.control, title='Open File') if dialog.open() == OK: self.window.workbench.edit(File(dialog.path), kind=TextEditor)
def get_file_from_dialog(): dlg = FileDialog(title='Choose file', action='open', wildcard=xye_wildcard) if dlg.open() == OK: return dlg.paths[0] return None