def register_plugin(self): self.main.add_dockwidget(self) print('** Looking for ExternalPythonShell') #from spyderlib.widgets.externalshell import pythonshell #print(len(self.main.extconsole.shellwidgets)) #for sw in self.main.extconsole.shellwidgets: #print('sw {}'.format(sw)) #if isinstance(sw, pythonshell.ExternalPythonShell): #print(' Found ExternalPythonShell: {}'.format(sw)) print(self.main.extconsole.start) self.main.extconsole.__class__ = SBNWExternalConsole if self.main.explorer is not None: self.connect(self.main.explorer, SIGNAL("open_interpreter(QString)"), self.sigslot) if self.main.projectexplorer is not None: self.connect(self.main.projectexplorer, SIGNAL("open_interpreter(QString)"), self.sigslot) if self.main.extconsole is not None: self.connect(self.main.extconsole, SIGNAL("open_interpreter(QString)"), self.sigslot) #print(dir(self.main.extconsole)) self.connect(self.main.console.shell, SIGNAL('refresh()'), self.sigslot) self.connect(self.main, SIGNAL('open_external_file(QString)'), self.sigslot)
def create_toolbutton(parent, text=None, shortcut=None, icon=None, tip=None, toggled=None, triggered=None, autoraise=True, text_beside_icon=False): """Create a QToolButton""" button = QToolButton(parent) if text is not None: button.setText(text) if icon is not None: if is_text_string(icon): icon = get_icon(icon) button.setIcon(icon) if text is not None or tip is not None: button.setToolTip(text if tip is None else tip) if text_beside_icon: button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) button.setAutoRaise(autoraise) if triggered is not None: QObject.connect(button, SIGNAL('clicked()'), triggered) if toggled is not None: QObject.connect(button, SIGNAL("toggled(bool)"), toggled) button.setCheckable(True) if shortcut is not None: button.setShortcut(shortcut) return button
def __init__(self, parent=None, name_filters=['*.py', '*.pyw'], valid_types=('.py', '.pyw'), show_all=False, show_cd_only=None, show_toolbar=True, show_icontext=True): QWidget.__init__(self, parent) self.treewidget = ExplorerTreeWidget(self, show_cd_only=show_cd_only) self.treewidget.setup(name_filters=name_filters, valid_types=valid_types, show_all=show_all) self.treewidget.chdir(getcwd()) toolbar_action = create_action(self, _("Show toolbar"), toggled=self.toggle_toolbar) icontext_action = create_action(self, _("Show icons and text"), toggled=self.toggle_icontext) self.treewidget.common_actions += [None, toolbar_action, icontext_action] # Setup toolbar self.toolbar = QToolBar(self) self.toolbar.setIconSize(QSize(16, 16)) self.previous_action = create_action(self, text=_("Previous"), icon=get_icon('previous.png'), triggered=self.treewidget.go_to_previous_directory) self.toolbar.addAction(self.previous_action) self.previous_action.setEnabled(False) self.connect(self.treewidget, SIGNAL("set_previous_enabled(bool)"), self.previous_action.setEnabled) self.next_action = create_action(self, text=_("Next"), icon=get_icon('next.png'), triggered=self.treewidget.go_to_next_directory) self.toolbar.addAction(self.next_action) self.next_action.setEnabled(False) self.connect(self.treewidget, SIGNAL("set_next_enabled(bool)"), self.next_action.setEnabled) parent_action = create_action(self, text=_("Parent"), icon=get_icon('up.png'), triggered=self.treewidget.go_to_parent_directory) self.toolbar.addAction(parent_action) options_action = create_action(self, text='', tip=_("Options"), icon=get_icon('tooloptions.png')) self.toolbar.addAction(options_action) widget = self.toolbar.widgetForAction(options_action) widget.setPopupMode(QToolButton.InstantPopup) menu = QMenu(self) add_actions(menu, self.treewidget.common_actions) options_action.setMenu(menu) toolbar_action.setChecked(show_toolbar) self.toggle_toolbar(show_toolbar) icontext_action.setChecked(show_icontext) self.toggle_icontext(show_icontext) vlayout = QVBoxLayout() vlayout.addWidget(self.toolbar) vlayout.addWidget(self.treewidget) self.setLayout(vlayout)
def create_dockwidget(self): """Add to parent QMainWindow as a dock widget""" # This is not clear yet why the following do not work... # (see Issue #880) ## # Using Qt.Window window flags solves Issue #880 (detached dockwidgets ## # are not painted after restarting Spyder and restoring their hexstate) ## # but it does not work with PyQt <=v4.7 (dockwidgets can't be docked) ## # or non-Windows platforms (lot of warnings are printed out) ## # (so in those cases, we use the default window flags: Qt.Widget): ## flags = Qt.Widget if is_old_pyqt or os.name != 'nt' else Qt.Window dock = SpyderDockWidget(self.get_plugin_title(), self.main) #, flags) dock.setObjectName(self.__class__.__name__ + "_dw") dock.setAllowedAreas(self.ALLOWED_AREAS) dock.setFeatures(self.FEATURES) dock.setWidget(self) self.update_margins() self.connect(dock, SIGNAL('visibilityChanged(bool)'), self.visibility_changed) self.connect(dock, SIGNAL('plugin_closed()'), self.plugin_closed) self.dockwidget = dock try: short = CONF.get('shortcuts', '_/switch to %s' % self.CONF_SECTION) except configparser.NoOptionError: short = None if short is not None: shortcut = QShortcut(QKeySequence(short), self.main, self.switch_to_plugin) self.register_shortcut(shortcut, "_", "Switch to %s" % self.CONF_SECTION) return (dock, self.LOCATION)
def start(self, wdir=None, args=None, pythonpath=None): filename = to_text_string(self.filecombo.currentText()) if wdir is None: wdir = self._last_wdir if wdir is None: wdir = osp.basename(filename) if args is None: args = self._last_args if args is None: args = [] if pythonpath is None: pythonpath = self._last_pythonpath self._last_wdir = wdir self._last_args = args self._last_pythonpath = pythonpath self.datelabel.setText(_('Profiling, please wait...')) self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setWorkingDirectory(wdir) self.connect(self.process, SIGNAL("readyReadStandardOutput()"), self.read_output) self.connect(self.process, SIGNAL("readyReadStandardError()"), lambda: self.read_output(error=True)) self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"), self.finished) self.connect(self.stop_button, SIGNAL("clicked()"), self.process.kill) if pythonpath is not None: env = [to_text_string(_pth) for _pth in self.process.systemEnvironment()] baseshell.add_pathlist_to_PYTHONPATH(env, pythonpath) self.process.setEnvironment(env) self.output = '' self.error_output = '' p_args = ['-m', 'cProfile', '-o', self.DATAPATH] if os.name == 'nt': # On Windows, one has to replace backslashes by slashes to avoid # confusion with escape characters (otherwise, for example, '\t' # will be interpreted as a tabulation): p_args.append(osp.normpath(filename).replace(os.sep, '/')) else: p_args.append(filename) if args: p_args.extend(shell_split(args)) executable = sys.executable if executable.endswith("spyder.exe"): # py2exe distribution executable = "python.exe" self.process.start(executable, p_args) running = self.process.waitForStarted() self.set_running_state(running) if not running: QMessageBox.critical(self, _("Error"), _("Process failed to start"))
def create_action(parent, text, shortcut=None, icon=None, tip=None, toggled=None, triggered=None, data=None, menurole=None, context=Qt.WindowShortcut): """Create a QAction""" action = QAction(text, parent) if triggered is not None: parent.connect(action, SIGNAL("triggered()"), triggered) if toggled is not None: parent.connect(action, SIGNAL("toggled(bool)"), toggled) action.setCheckable(True) if icon is not None: if is_text_string(icon): icon = get_icon(icon) action.setIcon(icon) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if data is not None: action.setData(to_qvariant(data)) if menurole is not None: action.setMenuRole(menurole) #TODO: Hard-code all shortcuts and choose context=Qt.WidgetShortcut # (this will avoid calling shortcuts from another dockwidget # since the context thing doesn't work quite well with these widgets) action.setShortcutContext(context) return action
def create_button(self, text, callback): btn = QPushButton(text) self.connect(btn, SIGNAL('clicked()'), callback) self.connect(btn, SIGNAL('clicked()'), lambda opt='': self.has_been_modified(opt)) return btn
def run(self): html_text = self.html_text_no_doc doc = self.doc if doc is not None: if type(doc) is dict and 'docstring' in doc.keys(): try: context = generate_context(name=doc['name'], argspec=doc['argspec'], note=doc['note'], math=self.math_option) html_text = sphinxify(doc['docstring'], context) if doc['docstring'] == '': html_text += '<div class="hr"></div>' html_text += self.html_text_no_doc except Exception as error: self.emit(SIGNAL('error_msg(QString)'), to_text_string(error)) return elif self.context is not None: try: html_text = sphinxify(doc, self.context) except Exception as error: self.emit(SIGNAL('error_msg(QString)'), to_text_string(error)) return self.emit(SIGNAL('html_ready(QString)'), html_text)
def register_plugin(self): """Register plugin in Spyder's main window""" self.connect(self, SIGNAL("edit_goto(QString,int,QString)"), self.main.editor.load) self.connect(self, SIGNAL('redirect_stdio(bool)'), self.main.redirect_internalshell_stdio) self.main.add_dockwidget(self) s2pwp_act = create_action(self, _("Import SED-ML as PhrasedML"), triggered=self.run_s2pwp) s2pwp_act.setEnabled(True) #self.register_shortcut(s2p_act, context="SED-ML to Python", # name="Import SED-ML file", default="Alt-I") for item in self.main.file_menu_actions: try: menu_title = item.title() except AttributeError: pass else: if not is_text_string(menu_title): # string is a QString menu_title = to_text_string(menu_title.toUtf8) if item.title() == str("Import"): item.addAction(s2pwp_act)
def load_and_translate(self, sbmlfile, pythonfile, editor, set_current=True): """ Read filename as combine archive, unzip, translate, reconstitute in Python, and create an editor instance and return it *Warning* This is loading file, creating editor but not executing the source code analysis -- the analysis must be done by the editor plugin (in case multiple editorstack instances are handled) """ sbmlfile = str(sbmlfile) self.emit(SIGNAL('starting_long_process(QString)'), _("Loading %s...") % sbmlfile) text, enc = encoding.read(sbmlfile) sbmlstr = te.readFromFile(sbmlfile) text = "import tellurium as te\n\nr = te.loada('''\n" + str(te.sbmlToAntimony(sbmlstr)) + "''')" widgeteditor = editor.editorstacks[0] finfo = widgeteditor.create_new_editor(pythonfile, enc, text, set_current, new=True) index = widgeteditor.data.index(finfo) widgeteditor._refresh_outlineexplorer(index, update=True) self.emit(SIGNAL('ending_long_process(QString)'), "") if widgeteditor.isVisible() and widgeteditor.checkeolchars_enabled \ and sourcecode.has_mixed_eol_chars(text): name = os.path.basename(pythonfile) QMessageBox.warning(self, widgeteditor.title, _("<b>%s</b> contains mixed end-of-line " "characters.<br>Spyder will fix this " "automatically.") % name, QMessageBox.Ok) widgeteditor.set_os_eol_chars(index) widgeteditor.is_analysis_done = False finfo.editor.set_cursor_position('eof') finfo.editor.insert_text(os.linesep) return finfo, sbmlfile
def delete_file(self, fname, multiple, yes_to_all): """Delete file""" if multiple: buttons = QMessageBox.Yes|QMessageBox.YesAll| \ QMessageBox.No|QMessageBox.Cancel else: buttons = QMessageBox.Yes|QMessageBox.No if yes_to_all is None: answer = QMessageBox.warning(self, _("Delete"), _("Do you really want " "to delete <b>%s</b>?" ) % osp.basename(fname), buttons) if answer == QMessageBox.No: return yes_to_all elif answer == QMessageBox.Cancel: return False elif answer == QMessageBox.YesAll: yes_to_all = True try: if osp.isfile(fname): misc.remove_file(fname) self.parent_widget.emit(SIGNAL("removed(QString)"), fname) else: self.remove_tree(fname) self.parent_widget.emit(SIGNAL("removed_tree(QString)"), fname) return yes_to_all except EnvironmentError as error: action_str = _('delete') QMessageBox.critical(self, _("Project Explorer"), _("<b>Unable to %s <i>%s</i></b>" "<br><br>Error message:<br>%s" ) % (action_str, fname, to_text_string(error))) return False
def __init__(self, parent=None): QTreeWidget.__init__(self, parent) self.header_list = [ _('Function/Module'), _('Total Time'), _('Local Time'), _('Calls'), _('File:line') ] self.icon_list = { 'module': 'python.png', 'function': 'function.png', 'builtin': 'python_t.png', 'constructor': 'class.png' } self.profdata = None # To be filled by self.load_data() self.stats = None # To be filled by self.load_data() self.item_depth = None self.item_list = None self.items_to_be_shown = None self.current_view_depth = None self.setColumnCount(len(self.header_list)) self.setHeaderLabels(self.header_list) self.initialize_view() self.connect(self, SIGNAL('itemActivated(QTreeWidgetItem*,int)'), self.item_activated) self.connect(self, SIGNAL('itemExpanded(QTreeWidgetItem*)'), self.item_expanded)
def select_file(self): self.emit(SIGNAL('redirect_stdio(bool)'), False) filename, _selfilter = getopenfilename(self, _("Select Python file"), getcwd(), _("Python files")+" (*.py ; *.pyw)") self.emit(SIGNAL('redirect_stdio(bool)'), False) if filename: self.analyze(filename)
def chdir(self, directory=None, browsing_history=False, refresh_explorer=True): """Set directory as working directory""" # Working directory history management if directory is not None: directory = osp.abspath(to_text_string(directory)) if browsing_history: directory = self.history[self.histindex] elif directory in self.history: self.histindex = self.history.index(directory) else: if self.histindex is None: self.history = [] else: self.history = self.history[:self.histindex + 1] self.history.append(directory) self.histindex = len(self.history) - 1 # Changing working directory os.chdir(to_text_string(directory)) self.refresh_plugin() if refresh_explorer: self.emit(SIGNAL("set_explorer_cwd(QString)"), directory) self.emit(SIGNAL("refresh_findinfiles()"))
def register_plugin(self): """Register plugin in Spyder's main window""" self.connect(self, SIGNAL("edit_goto(QString,int,QString)"), self.main.editor.load) self.connect(self, SIGNAL('redirect_stdio(bool)'), self.main.redirect_internalshell_stdio) self.main.add_dockwidget(self) c2p_act = create_action(self, _("Import COMBINE as Python"), triggered=self.run_c2p) c2p_act.setEnabled(True) #self.register_shortcut(c2p_act, context="Combine to Python", # name="Import combine archive", default="Alt-C") for item in self.main.file_menu_actions: try: menu_title = item.title() except AttributeError: pass else: if not is_text_string(menu_title): # string is a QString menu_title = to_text_string(menu_title.toUtf8) if item.title() == str("Import"): item.addAction(c2p_act) c2p_actions = (None, c2p_act) import_menu = QMenu(_("Import")) add_actions(import_menu, c2p_actions) self.main.file_menu_actions.insert(8, import_menu)
def register_plugin(self): """Register plugin in Spyder's main window""" self.connect(self, SIGNAL('redirect_stdio(bool)'), self.main.redirect_internalshell_stdio) self.connect(self.main.console.shell, SIGNAL("refresh()"), self.refresh_plugin) self.main.addToolBar(self)
def load_and_translate(self, combine, pythonfile, editor, set_current=True): """ Read filename as combine archive, unzip, translate, reconstitute in Python, and create an editor instance and return it *Warning* This is loading file, creating editor but not executing the source code analysis -- the analysis must be done by the editor plugin (in case multiple editorstack instances are handled) """ combine = str(combine) self.emit(SIGNAL('starting_long_process(QString)'), _("Loading %s...") % combine) text, enc = encoding.read(combine) text = Translatecombine(combine) zipextloctemp, sbmlloclisttemp, sedmlloclisttemp = manifestsearch(combine) for i in range(len(text)): widgeteditor = editor.editorstacks[0] sedmlfname = os.path.basename(sedmlloclisttemp[i]) finfo = widgeteditor.create_new_editor(os.path.splitext(sedmlfname)[0] + '.py', enc, text[i], set_current, new=True) index = widgeteditor.data.index(finfo) widgeteditor._refresh_outlineexplorer(index, update=True) self.emit(SIGNAL('ending_long_process(QString)'), "") if widgeteditor.isVisible() and widgeteditor.checkeolchars_enabled \ and sourcecode.has_mixed_eol_chars(text[i]): name = os.path.basename(os.path.splitext(sedmlfname)[0] + '.py') QMessageBox.warning(self, widgeteditor.title, _("<b>%s</b> contains mixed end-of-line " "characters.<br>Spyder will fix this " "automatically.") % name, QMessageBox.Ok) widgeteditor.set_os_eol_chars(index) widgeteditor.is_analysis_done = False finfo.editor.set_cursor_position('eof') finfo.editor.insert_text(os.linesep) return finfo, combine
def select_directory(self): """Select directory""" self.emit(SIGNAL('redirect_stdio(bool)'), False) directory = getexistingdirectory(self.main, _("Select directory"), getcwd()) if directory: self.chdir(directory) self.emit(SIGNAL('redirect_stdio(bool)'), True)
def register_plugin(self): """Register plugin in Spyder's main window""" self.connect(self, SIGNAL('focus_changed()'), self.main.plugin_focus_changed) self.main.add_dockwidget(self) # Connecting the following signal once the dockwidget has been created: self.connect(self.shell, SIGNAL('traceback_available()'), self.traceback_available)
def select_directory(self): """Select directory""" self.parent().emit(SIGNAL('redirect_stdio(bool)'), False) directory = getexistingdirectory(self, _("Select directory"), self.dir_combo.currentText()) if directory: self.set_directory(directory) self.parent().emit(SIGNAL('redirect_stdio(bool)'), True)
def set_current_working_directory(self): """Set current working directory""" cwd = self.shell.get_cwd() self.emit(SIGNAL('redirect_stdio(bool)'), False) directory = getexistingdirectory(self, _("Select directory"), cwd) if directory: self.shell.set_cwd(directory) self.emit(SIGNAL('redirect_stdio(bool)'), True)
def register_plugin(self): """Register plugin in Spyder's main window""" self.connect(self, SIGNAL('focus_changed()'), self.main.plugin_focus_changed) self.main.add_dockwidget(self) # self.main.console.set_historylog(self) self.connect(self.main.console.shell, SIGNAL("refresh()"), self.refresh_plugin)
def restore_expanded_state(self): """Restore all items expanded state""" if self.__expanded_state is not None: # In the old project explorer, the expanded state was a dictionnary: if isinstance(self.__expanded_state, list): self.connect(self.fsmodel, SIGNAL('directoryLoaded(QString)'), self.restore_directory_state) self.connect(self.fsmodel, SIGNAL('directoryLoaded(QString)'), self.follow_directories_loaded)
def create_dialog(self, dialog, refname, func): self.dialogs[id(dialog)] = dialog, refname, func self.connect(dialog, SIGNAL('accepted()'), lambda eid=id(dialog): self.editor_accepted(eid)) self.connect(dialog, SIGNAL('rejected()'), lambda eid=id(dialog): self.editor_rejected(eid)) dialog.show() dialog.activateWindow() dialog.raise_()
def refresh_plugin(self): """Refresh widget""" curdir = getcwd() self.pathedit.add_text(curdir) self.save_wdhistory() self.emit(SIGNAL("set_previous_enabled(bool)"), self.histindex is not None and self.histindex > 0) self.emit(SIGNAL("set_next_enabled(bool)"), self.histindex is not None and \ self.histindex < len(self.history)-1)
def add_button_box(self, stdbtns): """Create dialog button box and add it to the dialog layout""" bbox = QDialogButtonBox(stdbtns) run_btn = bbox.addButton(_("Run"), QDialogButtonBox.AcceptRole) self.connect(run_btn, SIGNAL('clicked()'), self.run_btn_clicked) self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()")) self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()")) btnlayout = QHBoxLayout() btnlayout.addStretch(1) btnlayout.addWidget(bbox) self.layout().addLayout(btnlayout)
def __init__(self, text, title='', font=None, parent=None, readonly=False, size=(400, 300)): QDialog.__init__(self, parent) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) self.text = None # Display text as unicode if it comes as bytes, so users see # its right representation if is_binary_string(text): self.is_binary = True text = to_text_string(text, 'utf8') else: self.is_binary = False self.layout = QVBoxLayout() self.setLayout(self.layout) # Text edit self.edit = QTextEdit(parent) self.connect(self.edit, SIGNAL('textChanged()'), self.text_changed) self.edit.setReadOnly(readonly) self.edit.setPlainText(text) if font is None: font = get_font('texteditor') self.edit.setFont(font) self.layout.addWidget(self.edit) # Buttons configuration buttons = QDialogButtonBox.Ok if not readonly: buttons = buttons | QDialogButtonBox.Cancel bbox = QDialogButtonBox(buttons) self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()")) self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()")) self.layout.addWidget(bbox) # Make the dialog act as a window self.setWindowFlags(Qt.Window) self.setWindowIcon(get_icon('edit.png')) self.setWindowTitle(_("Text editor") + \ "%s" % (" - "+str(title) if str(title) else "")) self.resize(size[0], size[1])
def initialize_plugin(self): """Initialize plugin: connect signals, setup actions, ...""" self.plugin_actions = self.get_plugin_actions() QObject.connect(self, SIGNAL('show_message(QString,int)'), self.show_message) QObject.connect(self, SIGNAL('update_plugin_title()'), self.__update_plugin_title) if self.sig_option_changed is not None: self.sig_option_changed.connect(self.set_option) self.setWindowTitle(self.get_plugin_title()) self.create_toggle_view_action()
def setup_page(self): self.table = ShortcutsTable(self) self.connect(self.table.model, SIGNAL("dataChanged(QModelIndex,QModelIndex)"), lambda i1, i2, opt='': self.has_been_modified(opt)) vlayout = QVBoxLayout() vlayout.addWidget(self.table) reset_btn = QPushButton(_("Reset to default values")) self.connect(reset_btn, SIGNAL('clicked()'), self.reset_to_default) vlayout.addWidget(reset_btn) self.setLayout(vlayout)
def __init__(self, color, parent=None): QHBoxLayout.__init__(self) assert isinstance(color, QColor) self.lineedit = QLineEdit(color.name(), parent) self.connect(self.lineedit, SIGNAL("textChanged(QString)"), self.update_color) self.addWidget(self.lineedit) self.colorbtn = ColorButton(parent) self.colorbtn.color = color self.connect(self.colorbtn, SIGNAL("colorChanged(QColor)"), self.update_text) self.addWidget(self.colorbtn)