def test_open_external_link_externally(self): model = HTMLModel(content=""" <html> <a href='test://testing' target='_blank' style='display:block; width: 100%; height: 100%'> External Link </a> </html> """) view = View( Item("content", editor=HTMLEditor(open_externally=True)) ) with self.tester.create_ui(model, dict(view=view)) as ui: html_view = self.tester.find_by_name(ui, "content") with mock.patch("webbrowser.open_new") as mocked_browser: html_view.perform(MouseClick()) self.assertIn( "External Link", html_view.inspect(HTMLContent()), ) is_webkit = _is_webkit_page(html_view._target.control.page()) if is_webkit: # This is the expected behavior. mocked_browser.assert_called_once_with("test://testing") else: # Expected failure: # See enthought/traitsui#1464 # This is the current unexpected behavior if QtWebEngine is used. mocked_browser.assert_not_called()
def get_view(base_url_name): return View( Item("content", editor=HTMLEditor( format_text=True, base_url_name=base_url_name, )))
def test_open_internal_link_externally(self): # this test requires Qt because it relies on the link filling up # the entire page through the use of CSS, which isn't supported # by Wx. model = HTMLModel(content=""" <html> <a href='test://testing' target='_self' style='display:block; width: 100%; height: 100%'> Internal Link </a> </html> """) view = View( Item("content", editor=HTMLEditor(open_externally=True)) ) with self.tester.create_ui(model, dict(view=view)) as ui: html_view = self.tester.find_by_name(ui, "content") with mock.patch("webbrowser.open_new") as mocked_browser: html_view.perform(MouseClick()) self.assertIn( "Internal Link", html_view.inspect(HTMLContent()), ) mocked_browser.assert_called_once_with("test://testing")
def test_open_external_link(self): # this test requires Qt because it relies on the link filling up # the entire page through the use of CSS, which isn't supported # by Wx. model = HTMLModel(content=""" <html> <a href='test://testing' target='_blank' style='display:block; width: 100%; height: 100%'> External Link </a> </html> """) view = View( Item("content", editor=HTMLEditor()) ) with self.tester.create_ui(model, dict(view=view)) as ui: html_view = self.tester.find_by_name(ui, "content") with mock.patch("webbrowser.open_new") as mocked_browser: html_view.perform(MouseClick()) self.assertIn( "External Link", html_view.inspect(HTMLContent()), ) # See enthought/traitsui#1464 # This is the expected behaviour: # mocked_browser.assert_called_once_with("test://testing") # However, this is the current unexpected behaviour mocked_browser.assert_not_called()
class TestHTML(HasPrivateTraits): # ------------------------------------------------------------------------- # Trait definitions: # ------------------------------------------------------------------------- # Text string to display as HTML: html = Code(sample) # ------------------------------------------------------------------------- # Traits view definitions: # ------------------------------------------------------------------------- view = View( Group( [Item('html#@', editor=HTMLEditor(format_text=True)), '|<>'], ['{Enter formatted text and/or HTML below:}@', 'html#@', '|<>'], '|<>', layout='split', ), title='HTML Editor Test', resizable=True, width=0.4, height=0.6, )
class InfoViewer(HasTraits): text = Str() view = View(Item('text', editor=HTMLEditor(format_text=True), style='readonly', show_label=False), resizable=True, width=0.3, height=0.3)
class HelpDockPane(TraitsDockPane): """ A DockPane to view help for the current module """ #### TaskPane interface ############################################### id = 'edu.mit.synbio.cytoflowgui.help_pane' name = 'Help' # the Task that serves as the controller task = Instance(Task) view_plugins = List(IViewPlugin) op_plugins = List(IOperationPlugin) help_id = Str html = HTML("<b>Welcome to Cytoflow!</b>") traits_view = View( Item('html', editor=HTMLEditor(base_url=pathlib.Path(__file__).parent.joinpath( 'help').as_posix()), show_label=False)) def create_contents(self, parent): self.ui = self.edit_traits(kind='subpanel', parent=parent) layout = QtGui.QHBoxLayout() control = HintedWidget() layout.addWidget(self.ui.control) control.setLayout(layout) control.setParent(parent) parent.setWidget(control) return control @on_trait_change('help_id', post_init=True) def _on_help_id_changed(self): for plugin in self.view_plugins: if self.help_id == plugin.view_id: try: self.html = plugin.get_help() except AttributeError: pass finally: return for plugin in self.op_plugins: if self.help_id == plugin.operation_id: try: self.html = plugin.get_help() except AttributeError: pass finally: return
def html_editor(): """ Factory function for an "editor" that displays a multi-line string as interpreted HTML. """ global HTMLTextEditor if HTMLTextEditor is None: from traitsui.api import HTMLEditor HTMLTextEditor = HTMLEditor() return HTMLTextEditor
class ShowUsage(HasTraits): usage_str = Str() traits_view = View( Item("usage_str", style='readonly', show_label=False, editor=HTMLEditor(), resizable=True), width=680, resizable=True, icon=icon, title='Swift Console Usage') def __init__(self, usage, error_str): if error_str != "": self.usage_str = "<pre>" + error_str + '<br><br><br>' + usage + "</pre>" else: self.usage_str = "<pre>" + usage + "</pre>"
class EK60Dialog(HasTraits): """ This class implements a dialog box that displays bandwidth averaged sphere TS estimates. """ html_text = Str() view = View(Item('html_text', editor=HTMLEditor(format_text=False), show_label=False), title='EK60', buttons=[OKButton], resizable=True)
class ModelHelpPane(TraitsDockPane): """ A dock pane for viewing any help associated with a model. """ #### 'ITaskPane' interface ################################################ id = "example.attractors.model_help_pane" name = "Model Information" #### 'ModelConfigPane' interface ########################################## model = Instance(HasTraits) html = Property(Str, observe="model") view = View( Item( "pane.html", editor=HTMLEditor(base_url=HELP_PATH, open_externally=True), show_label=False, ), width=300, resizable=True, ) ########################################################################### # Protected interface. ########################################################################### @cached_property def _get_html(self): """ Fetch the help HTML for the current model. """ if self.model is None: return "No model selected." # Determine the name of the model. model = self.model while hasattr(model, "adaptee"): model = model.adaptee name = model.__class__.__name__.lower() # Load HTML file, if possible. path = os.path.join(HELP_PATH, name + ".html") if os.path.isfile(path): with codecs.open(path, "r", "utf-8") as f: return f.read() else: return "No information available for model."
def traits_view(self): v = View( Item('message', style='custom', editor=HTMLEditor(), show_label=False), HGroup(spring, Item('dismiss_notification')), kind='modal', handler=VersionInfoHandler, buttons=['OK'], width=300, height=300, title='Version Info', ) return v
class HTMLEditorDemo(HasTraits): """ Defines the main HTMLEditor demo class. """ # Define a HTML trait to view my_html_trait = HTML(sample_text) # Demo view traits_view = View( UItem( 'my_html_trait', # we specify the editor explicitly in order to set format_text: editor=HTMLEditor(format_text=True)), title='HTMLEditor', buttons=['OK'], width=800, height=600, resizable=True)
class HTMLItem(ADescriptionItem): """ Defines a class used for displaying a single HTML page within the tutor using the default Traits HTML editor. """ url = Str view = View( Item('content', style='readonly', show_label=False, editor=HTMLEditor())) def _url_changed(self, url): """ Sets the item title when the 'url' is changed. """ match = url_pat1.match(url) if match is not None: title = match.group(2).strip() else: title = url.strip() col = title.rfind('/') if col >= 0: title = os.path.splitext(title[col + 1:])[0] self.title = title @cached_property def _get_content(self): """ Returns the item content. """ url = self.url if url != '': match = url_pat1.match(url) if match is not None: url = match.group(1) + match.group(3) return url return read_file(self.path) def _set_content(self, content): """ Sets the item content. """ self._content = content
class HelpDockPane(TraitsDockPane): """ A DockPane to view help for the current module """ #### TaskPane interface ############################################### id = 'edu.mit.synbio.help_pane' name = 'Help' # the Task that serves as the controller task = Instance(Task) view_plugins = List(IViewPlugin) op_plugins = List(IOperationPlugin) help_id = Str html = HTML("<b>Welcome to Cytoflow!</b>") traits_view = View( Item('html', editor=HTMLEditor(base_url=pathlib.Path(__file__).parent.joinpath( 'help').as_posix()), show_label=False)) @on_trait_change('help_id', post_init=True) def _on_help_id_changed(self): for plugin in self.view_plugins: if self.help_id == plugin.view_id: try: self.html = plugin.get_help() except AttributeError: pass finally: return for plugin in self.op_plugins: if self.help_id == plugin.operation_id: try: self.html = plugin.get_help() except AttributeError: pass finally: return
class AboutDialog(HasTraits): """ This class implements an About dialog box using the TraitsUI user interface framework. The text displayed in the dialog is read from a file containing html-formatted text. """ helpFile = 'about.html' about_text = Str() view = View(Item('about_text', editor=HTMLEditor(), show_label=False), resizable=True, title='About', buttons=[OKButton]) def load_help_text(self): """ Loads the help text from the file. """ f = open(self.helpFile, 'r') self.about_text = f.read()
def traits_view(self): """ Default view to show for this class. """ args = [] kw_args = { "title": "Preferences Page Help", "buttons": ["OK"], "width": 800, "height": 800, "resizable": True, "id": "apptools.preferences.ui.preferences_manager.help", } to_show = {} for name, trait_obj in self.traits().items(): if name != "trait_added" and name != "trait_modified": to_show[name] = trait_obj.help for name in to_show: args.append(Item(name, style="readonly", editor=HTMLEditor())) view = View(*args, **kw_args) return view
def traits_view(self): """ Default view to show for this class. """ args = [] kw_args = { 'title': 'Preferences Page Help', 'buttons': ['OK'], 'width': 800, 'height': 800, 'resizable': True, 'id': 'apptools.preferences.ui.preferences_manager.help' } to_show = {} for name, trait_obj in self.traits().items(): if name != 'trait_added' and name != 'trait_modified': to_show[name] = trait_obj.help for name in to_show: args.append(Item(name, style='readonly', editor=HTMLEditor())) view = View(*args, **kw_args) return view
def trait_view(self, name='default'): rest_editor = CodeEditor(lexer='rest', selected_line='selected_line', auto_scroll=True, squiggle_lines='warning_lines', selected_text='selected_text', selected_start_pos='selected_start_pos', selected_end_pos='selected_end_pos') warning_editor = TabularEditor(editable=False, adapter=DocUtilsWarningAdapter(), dclicked='dclicked_warning') html_editor = HTMLEditor(open_externally=True, base_url_name='base_url') return View(Group(Group(Item('object.model.rest', style='custom', editor=rest_editor), Item('html', editor=html_editor), id='rest_editor_view.PairView.HorzGroup', show_labels=False, orientation='horizontal', layout='split'), Item('object.model.warnings', height=0.2, editor=warning_editor), id='rest_editor_view.PairView.VertGroup', show_labels=False, orientation='vertical', layout='split'), id='rest_editor_view.PairView', handler=ReSTHTMLPairHandler(), width=800, height=600, resizable=True)
_, ext = splitext(filename) file_factory = self._file_factory[ext] demo_file = file_factory(parent=self, name=filename) return demo_file # ------------------------------------------------------------------------- # Defines the demo tree editor: # ------------------------------------------------------------------------- demo_path_view = View( UItem( "description", style="readonly", editor=HTMLEditor( format_text=True, base_url_name='base_url', ), ), id="demo_path_view", kind='subpanel', ) demo_file_view = View( HSplit( UItem( "description", style="readonly", editor=HTMLEditor( format_text=True, base_url_name='base_url', ),
class CiteOverlapGUI(HasTraits): """GUI for Citation Overlap.""" #: str: Default extractor option to prompt user to select an extractor. _DEFAULT_EXTRACTOR = "Select..." #: int: Default number of import views. _DEFAULT_NUM_IMPORTS = 3 #: OrderedDict[str, str]: Dictionary of separator descriptions to # separator characters. _EXPORT_SEPS = OrderedDict(( ('Tabs (.tsv)', '\t'), ('Comma (.csv)', ','), ('Bar (.csv)', '|'), ('Semi-colon (.csv)', ';'), )) # handler triggers selectSheetTab = Int(-1) # tab index to select renameSheetTab = Int(-1) # tab index to rename renameSheetName = Str # new tab name # CONTROL PANEL TRAITS # citation list import views importMedline = Instance(CiteImport) importEmbase = Instance(CiteImport) importScopus = Instance(CiteImport) importOther1 = Instance(CiteImport) importOther2 = Instance(CiteImport) importOther3 = Instance(CiteImport) importOther4 = Instance(CiteImport) _importAddBtn = Button('Add Sheet') # extractor drop-downs _extractorNames = Instance(TraitsList) _extractorAddBtn = Button('Add Extractor') # button to find overlaps and progress bar _overlapBtn = Button('Find Overlaps') _progBarPct = Int(0) _progBarMsg = Str('Awaiting overlaps') # table export _exportBtn = Button('Export Tables') _exportSep = Str _exportSepNames = Instance(TraitsList) _statusBarMsg = Str # HELP PANEL TRAITS pkgDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) docsDir = os.path.join(pkgDir, "docs") if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): # detect frozen env using the PyInstaller-specific attributes # (currently works even without this setting through symlinks) docsDir = os.path.realpath(os.path.join(sys._MEIPASS, "docs")) with open(os.path.join(docsDir, "sidebar.html"), mode="r") as help_file: helpMsg = "".join(help_file.readlines()) _helpHtml = HTML(helpMsg) # SHEETS TRAITS # counter for number of "other citation" sheets _numCitOther = Int(0) _tabularArgs = { 'editable': True, 'auto_resize_rows': True, 'stretch_last_section': False } # Import view groups, which need an adapter set here to avoid sharing # the adapter across view instances # MEDLINE table _medlineAdapter = TableArrayAdapter() _medlineTable = TabularEditor(adapter=_medlineAdapter, **_tabularArgs) _medline = CiteSheet(adapter=_medlineAdapter) # Embase table _embaseAdapter = TableArrayAdapter() _embaseTable = TabularEditor(adapter=_embaseAdapter, **_tabularArgs) _embase = CiteSheet(adapter=_embaseAdapter) # Scopus table _scopusAdapter = TableArrayAdapter() _scopusTable = TabularEditor(adapter=_scopusAdapter, **_tabularArgs) _scopus = CiteSheet(adapter=_scopusAdapter) # Other 1 table _citOther1Adapter = TableArrayAdapter() _citOther1Table = TabularEditor(adapter=_citOther1Adapter, **_tabularArgs) _citOther1 = CiteSheet(adapter=_citOther1Adapter) # Other 2 table _citOther2Adapter = TableArrayAdapter() _citOther2Table = TabularEditor(adapter=_citOther2Adapter, **_tabularArgs) _citOther2 = CiteSheet(adapter=_citOther2Adapter) # Other 3 table _citOther3Adapter = TableArrayAdapter() _citOther3Table = TabularEditor(adapter=_citOther3Adapter, **_tabularArgs) _citOther3 = CiteSheet(adapter=_citOther3Adapter) # Other 4 table _citOther4Adapter = TableArrayAdapter() _citOther4Table = TabularEditor(adapter=_citOther4Adapter, **_tabularArgs) _citOther4 = CiteSheet(adapter=_citOther4Adapter) # Overlaps output table _overlapsAdapter = TableArrayAdapter() _outputTable = TabularEditor(adapter=_overlapsAdapter, **_tabularArgs) _overlaps = CiteSheet(adapter=_overlapsAdapter) # TRAITUI WIDGETS # controls panel _controlsPanel = VGroup( VGroup( Item('importMedline', show_label=False, style='custom'), Item('importEmbase', show_label=False, style='custom'), Item('importScopus', show_label=False, style='custom'), Item('importOther1', show_label=False, style='custom', visible_when='_numCitOther >= 1'), Item('importOther2', show_label=False, style='custom', visible_when='_numCitOther >= 2'), Item('importOther3', show_label=False, style='custom', visible_when='_numCitOther >= 3'), Item('importOther4', show_label=False, style='custom', visible_when='_numCitOther >= 4'), HGroup( Item('_importAddBtn', show_label=False, springy=True, enabled_when='_numCitOther <= object._DEFAULT_NUM_IMPORTS' ), Item('_extractorAddBtn', show_label=False, springy=True), ), label='Load Citation Files', ), VGroup( HGroup(Item('_overlapBtn', show_label=False, springy=True), ), Item('_progBarPct', show_label=False, editor=ProgressEditor(min=0, max=100, message_name='_progBarMsg')), HGroup( Item('_exportBtn', show_label=False, springy=True), Item("_exportSep", label="Separator", editor=CheckListEditor( name="object._exportSepNames.selections")), ), label='Detect Overlapping Citations', ), label="Import", ) # help panel _helpPanel = VGroup( Item("_helpHtml", editor=HTMLEditor(format_text=True), show_label=False), label="Help", ) # tabbed panel for sidebar _sidebarTabs = Tabbed( _controlsPanel, _helpPanel, ) # Tabbed viewers of tables # WORKAROUND: Because of an apparent limitation in adding tabs dynamically # in TraitsUI (https://github.com/enthought/traitsui/pull/1456), separate # views are created and toggled depending on the number of "other" sheets, # toggled by the "visible_when" flag # default tabbed viewer _tableView1 = Tabbed( Item('object._medline.data', editor=_medlineTable, show_label=False, width=1000), Item('object._embase.data', editor=_embaseTable, show_label=False), Item('object._scopus.data', editor=_scopusTable, show_label=False), Item('object._overlaps.data', editor=_outputTable, show_label=False), visible_when='_numCitOther == 0', ) # tabbed viewer of tables with one "other" sheet _tableView2 = Tabbed( Item('object._medline.data', editor=_medlineTable, show_label=False, width=1000), Item('object._embase.data', editor=_embaseTable, show_label=False), Item('object._scopus.data', editor=_scopusTable, show_label=False), Item('object._citOther1.data', editor=_citOther1Table, show_label=False), Item('object._overlaps.data', editor=_outputTable, show_label=False), visible_when='_numCitOther == 1', ) # tabbed viewer of tables with two "other" sheets _tableView3 = Tabbed( Item('object._medline.data', editor=_medlineTable, show_label=False, width=1000), Item('object._embase.data', editor=_embaseTable, show_label=False), Item('object._scopus.data', editor=_scopusTable, show_label=False), Item('object._citOther1.data', editor=_citOther1Table, show_label=False), Item('object._citOther2.data', editor=_citOther2Table, show_label=False), Item('object._overlaps.data', editor=_outputTable, show_label=False), visible_when='_numCitOther == 2', ) # tabbed viewer of tables with three "other" sheets _tableView4 = Tabbed( Item('object._medline.data', editor=_medlineTable, show_label=False, width=1000), Item('object._embase.data', editor=_embaseTable, show_label=False), Item('object._scopus.data', editor=_scopusTable, show_label=False), Item('object._citOther1.data', editor=_citOther1Table, show_label=False), Item('object._citOther2.data', editor=_citOther2Table, show_label=False), Item('object._citOther3.data', editor=_citOther2Table, show_label=False), Item('object._overlaps.data', editor=_outputTable, show_label=False), visible_when='_numCitOther == 3', ) # tabbed viewer of tables with four "other" sheets _tableView5 = Tabbed( Item('object._medline.data', editor=_medlineTable, show_label=False, width=1000), Item('object._embase.data', editor=_embaseTable, show_label=False), Item('object._scopus.data', editor=_scopusTable, show_label=False), Item('object._citOther1.data', editor=_citOther1Table, show_label=False), Item('object._citOther2.data', editor=_citOther2Table, show_label=False), Item('object._citOther3.data', editor=_citOther2Table, show_label=False), Item('object._citOther4.data', editor=_citOther2Table, show_label=False), Item('object._overlaps.data', editor=_outputTable, show_label=False), visible_when='_numCitOther == 4', ) # main view view = View( HSplit( _sidebarTabs, # only one table view should be displayed at a time Group( _tableView1, _tableView2, _tableView3, _tableView4, _tableView5, ), ), width=1300, # also influenced by _tableView width height=800, title='Citation Overlap', resizable=True, handler=CiteOverlapHandler(), statusbar="_statusBarMsg") def __init__(self): """Initialize the GUI.""" super().__init__() # set up import views self.importMedline = CiteImport(sheet=self._medline) self.importEmbase = CiteImport(sheet=self._embase) self.importScopus = CiteImport(sheet=self._scopus) self.importOther1 = CiteImport(sheet=self._citOther1) self.importOther2 = CiteImport(sheet=self._citOther2) self.importOther3 = CiteImport(sheet=self._citOther3) self.importOther4 = CiteImport(sheet=self._citOther4) self.importViews = ( self.importMedline, self.importEmbase, self.importScopus, self.importOther1, self.importOther2, self.importOther3, self.importOther4, ) # populate drop-down of available extractors from directory of # extractors, displaying only basename but keeping dict with full path extractor_paths = [] for extractor_dir in config.extractor_dirs: extractor_paths.extend(glob.glob(str(extractor_dir / "*"))) self._extractor_paths = { os.path.basename(f): f for f in extractor_paths } self._updateExtractorNames(True) for importer in self.importViews: importer.observe(self.renameTabEvent, "extractor") importer.observe(self.importFile, "path") importer.observe(self.clearSheet, "clearBtn") # populate drop-down of separators/delimiters self._exportSepNames = TraitsList() self._exportSepNames.selections = list(self._EXPORT_SEPS.keys()) self._exportSep = self._exportSepNames.selections[0] # extractor and overlaps thread instances self.dbExtractor = extractor.DbExtractor() self._overlapsThread = None # last opened directory self._save_dir = None def _updateExtractorNames(self, reset=False): """Update the list of extractor names shown in the combo boxes. Args: reset (bool): True to reset to default selections; defaults to False. """ if reset: # pick default selections for each extractor selections = [e.value for e in extractor.DefaultExtractors] numExtra = len(self.importViews) - len(selections) if numExtra > 0: selections.extend([self._DEFAULT_EXTRACTOR] * numExtra) else: # keep current selections selections = [v.extractor for v in self.importViews] # update combo box from extractor path keys self._extractorNames = TraitsList() extractorNames = [self._DEFAULT_EXTRACTOR] extractorNames.extend(self._extractor_paths.keys()) self._extractorNames.selections = extractorNames # assign default extractor selections for view, selection in zip(self.importViews, selections): view.extractorNames = self._extractorNames view.extractor = selection def renameTabEvent(self, event): """Handler to rename a spreadsheet tab. Args: event (:class:`traits.observation.events.TraitChangeEvent`): Event. """ self.renameSheetTab = self.importViews.index(event.object) self.renameSheetName = _displayExtractor(event.object.extractor) def clearSheet(self, event): """Clear the sheet associated with an import view. Args: event (:class:`traits.observation.events.TraitChangeEvent`): Event. """ event.object.sheet.data = np.empty((0, 0)) del self.dbExtractor.dbsParsed[event.object.dbName] event.object.path = '' @staticmethod def _df_to_cols(df): """Convert a data frame to table columns with widths adjusted to fit the column width up to a given max amount. Args: df (:obj:`pd.DataFrame`): Data frame to enter into table. Returns: dict[int, int], list[(str, Any)], :obj:`np.ndarray`: Dictionary of column indices to width, list of column tuples given as ``(col_name, col_ID)``, and data frame as a Numpy arry. """ colWidths = [] colsIDs = [] for i, col in enumerate(df.columns.values.tolist()): # get widths of all rows in column as well as header colWidth = df[col].astype(str).str.len().tolist() colWidth.append(len(col)) colWidths.append(colWidth) # use index as ID except for group/sub-group, where using a string # allows the col along with row to be accessed for individual cells colID = col.lower() if col in ('Group', 'Subgrp') else i colsIDs.append((col, colID)) # get max width for each col, taking log to slow the width increase # for wider strings and capping at a max width widths = { i: min((math.log1p(max(c)) * 40, TableArrayAdapter.MAX_WIDTH)) for i, c in enumerate(colWidths) } return widths, colsIDs, df.to_numpy() @on_trait_change('_importAddBtn') def addImport(self): """Add import fields and a new sheet.""" if self._numCitOther < len( self.importViews) - self._DEFAULT_NUM_IMPORTS: # trigger additional import view and tab with new sheet self._numCitOther += 1 @on_trait_change('_extractorAddBtn') def addExtractor(self): """Add an extractor to the combo box.""" try: # get path to extractor from file dialog path = self._getFileDialogPath() except FileNotFoundError: return # update combo box pathName = os.path.basename(path) self._extractor_paths[pathName] = path self._updateExtractorNames() def importFile(self, event): """Import a database file. Args: event (:class:`traits.observation.events.TraitChangeEvent`): Event. Returns: :obj:`pd.DataFrame`: Data frame of extracted file. """ path = event.object.path if not os.path.exists(path): if path: # file inaccessible, or manually edited, non-accessible path self._statusBarMsg = f'{path} could not be found, skipping' return None self._save_dir = os.path.dirname(path) try: # extract file extractorPath = self._extractor_paths[event.object.extractor] df, dbName = self.dbExtractor.extractDb(path, extractorPath) event.object.dbName = dbName try: self.dbExtractor.checkExtraction(df) self._statusBarMsg = f'Imported file from {path}' except SyntaxWarning as e: msg = \ f'WARNING: {str(e)}. Please check the selected file ' \ f'source and reload the citation file.' self._statusBarMsg = msg _logger.warning(msg) sheet = event.object.sheet if df is not None and sheet is not None: # output data frame to associated table sheet.adapter._widths, sheet.adapter.columns, sheet.data = \ self._df_to_cols(df) self.selectSheetTab = self.importViews.index(event.object) return df except (FileNotFoundError, SyntaxError) as e: self._statusBarMsg = str(e) return None def _updateProgBar(self, pct: int, msg: str): """"Update progress bar. Args: pct: Percentage complete, from 0-100. msg: Message to display. """ self._progBarPct = pct self._progBarMsg = msg def _overlapsHandler(self, result: Union[pd.DataFrame, str]): """Handle result from finding overlaps. Args: result: Data frame of overlaps or message. """ if isinstance(result, pd.DataFrame): self._progBarPct = 100 if result is None: # clear any existing data in sheet if no citation lists self._overlaps.data = np.empty((0, 0)) self._statusBarMsg = 'No citation lists found' return # populate overlaps sheet self._overlaps.adapter._widths, self._overlaps.adapter.columns, \ self._overlaps.data = self._df_to_cols(result) self.selectSheetTab = self._DEFAULT_NUM_IMPORTS + self._numCitOther self._statusBarMsg = 'Found overlaps across databases' elif isinstance(result, str): # show message self._statusBarMsg = result @on_trait_change('_overlapBtn') def findOverlaps(self): """Find overlaps in a thread.""" self._progBarPct = 0 self._overlapsThread = overlaps_thread.OverlapsThread( self.dbExtractor, self._overlapsHandler, self._updateProgBar) self._overlapsThread.start() def _getFileDialogPath(self, default_path='', mode='open'): """Get a path from the user through a file dialog. Args: default_path (str): Initial path to display in the dialog; defaults to an emptry string. If :attr:`_save_dir` is set, ``default_path`` will be joined to the save directory. mode (str): "open" for an open dialog, or "save as" for a save dialog. Returns: str: Chosen path. Raises: FileNotFoundError: User canceled file selection. """ if self._save_dir: # use directory of last chosen import file default_path = os.path.join(self._save_dir, default_path) # open a PyFace file dialog in save mode save_dialog = FileDialog(action=mode, default_path=default_path) if save_dialog.open() == OK: # get user selected path return save_dialog.path else: # user canceled file selection raise FileNotFoundError("User canceled file selection") @on_trait_change('_exportBtn') def exportTables(self): """Export tables to a files.""" self.dbExtractor.saveSep = self._EXPORT_SEPS[self._exportSep] try: # prompt user to select an output file path for the combined list; # save along with filtered folders in a separate dir there save_path = self._getFileDialogPath( self.dbExtractor.DEFAULT_OVERLAPS_PATH, "save as") self.dbExtractor.exportDataFrames(save_path) self._statusBarMsg = ( f'Saved combined table to "{save_path}" and filtered tables ' f'alongside in "{self.dbExtractor.DEFAULT_CLEANED_DIR_PATH}"') except FileNotFoundError: print("Skipping file save")
return len(self.resources) > 0 def get_children(self): return self.resources # ------------------------------------------------------------------------- # Defines the demo tree editor: # ------------------------------------------------------------------------- demo_path_view = View( UItem( "description", style="readonly", editor=HTMLEditor( format_text=True, base_url_name='base_url', ), ), id="demo_path_view", kind='subpanel', ) demo_file_view = View( HSplit( UItem( "description", style="readonly", editor=HTMLEditor( format_text=True, base_url_name='base_url', open_externally=True,
class MainWindow(HasTraits): title = String() date = String() category = Enum(['nus', 'travel', 'pics', 'food']) dirpath = Directory() codedir = Directory() html_text = String('') status = String('no connection') ftp_url = String('files.000webhost.com') ftp_user = String('maxinsingapore') ftp_dir = String('public_html/pictures') ftp_pw = String() upload_btn = Button('Upload') html_preview = HTML() preview_btn = Button('HTML preview') uploadthread = Instance(UploadThread) notuploading = Bool(True) html_intro_1 = '''<!DOCTYPE html><html><head><link href="main.css" rel="stylesheet"/> <title>Max in Singapore</title> </head> <body> <?php require("ground.php"); ?> <div class = "title"> <a href="''' html_intro_2 = '''.php"><figure><p>back</p</figure></a> </div> <div class="center">''' html_end = ''' </div> </div> </div> </body> </html>''' traits_view = View( HGroup('ftp_url', 'ftp_user', 'ftp_pw', 'ftp_dir'), HGroup('title', 'date', 'category'), HGroup(Item('html_text', editor=CodeEditor()), Item('html_preview', editor=HTMLEditor())), 'preview_btn', Item('dirpath', label='Photo Directory'), Item('codedir', label='Code Directory'), Item('status', style='readonly'), Item('upload_btn', enabled_when='notuploading')) def _preview_btn_fired(self): html_intro = self.html_intro_1 + self.category + self.html_intro_2 self.html_preview = html_intro + self.html_text + self.html_end def _upload_btn_fired(self): if self.dirpath != '' and self.codedir != '': self.notuploading = False self.uploadthread = UploadThread() self.uploadthread.wants_abort = False self.uploadthread.master = self self.uploadthread.start() else: self.status = "choose directories"
if ext == '.py': return True return False #------------------------------------------------------------------------------- # Defines the demo tree editor: #------------------------------------------------------------------------------- path_view = View( Tabbed( Item( 'description', label = 'Description', show_label = False, style = 'readonly', editor=HTMLEditor(format_text=True) ), Item( 'source', label = 'Source', show_label = False, style = 'custom' ), export = 'DockWindowShell', id = 'tabbed' ), id = 'traitsui.demos.demo.path_view', #dock = 'horizontal' ) demo_view = View( #VSplit(
def html_editor(): """ Factory function for an "editor" that displays a multi-line string as interpreted HTML. """ from traitsui.api import HTMLEditor return HTMLEditor()