def save_data(self, filename=None): """Save data""" if filename is None: filename = self.filename if filename is None: filename = getcwd_or_home() filename, _selfilter = getsavefilename(self, _("Save data"), filename, iofunctions.save_filters) if filename: self.filename = filename else: return False QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() error_message = self.shellwidget.save_namespace(self.filename) self.shellwidget._kernel_reply = None QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: if 'Some objects could not be saved:' in error_message: save_data_message = ( _('<b>Some objects could not be saved:</b>') + '<br><br><code>{obj_list}</code>'.format( obj_list=error_message.split(': ')[1])) else: save_data_message = _( '<b>Unable to save current workspace</b>' '<br><br>Error message:<br>') + error_message QMessageBox.critical(self, _("Save data"), save_data_message) self.save_button.setEnabled(self.filename is not None)
def get_root_path(self, language): """ Get root path to pass to the LSP servers. This can be the current project path or the output of getcwd_or_home (except for Python, see below). """ path = None # Get path of the current project if self.main and self.main.projects: path = self.main.projects.get_active_project_path() # If there's no project, use the output of getcwd_or_home. if not path: # We can't use getcwd_or_home for Python because if it # returns home and you have a lot of Python files on it # then computing Rope completions takes a long time # and blocks the PyLS server. # Instead we use an empty directory inside our config one, # just like we did for Rope in Spyder 3. if language == 'python': path = get_conf_path('lsp_root_path') if not osp.exists(path): os.mkdir(path) else: path = getcwd_or_home() return path
def save_data(self, filename=None): """Save data""" if filename is None: filename = self.filename if filename is None: filename = getcwd_or_home() filename, _selfilter = getsavefilename(self, _("Save data"), filename, iofunctions.save_filters) if filename: self.filename = filename else: return False QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() error_message = self.shellwidget.save_namespace(self.filename) self.shellwidget._kernel_reply = None QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: QMessageBox.critical(self, _("Save data"), _("<b>Unable to save current workspace</b>" "<br><br>Error message:<br>%s") % error_message) self.save_button.setEnabled(self.filename is not None)
def open_project(self, path=None, restart_consoles=True, save_previous_files=True): """Open the project located in `path`""" if path is None: basedir = get_home_dir() path = getexistingdirectory(parent=self, caption=_("Open project"), basedir=basedir) if not self.is_valid_project(path): if path: QMessageBox.critical(self, _('Error'), _("<b>%s</b> is not a Spyder project!") % path) return else: self.add_to_recent(path) # A project was not open before if self.current_active_project is None: if save_previous_files: self.editor.save_open_files() self.editor.set_option('last_working_dir', getcwd_or_home()) self.show_explorer() else: # we are switching projects self.set_project_filenames(self.editor.get_open_filenames()) self.current_active_project = EmptyProject(path) self.latest_project = EmptyProject(path) self.set_option('current_project_path', self.get_active_project_path()) self.setup_menu_actions() self.sig_project_loaded.emit(path) self.pythonpath_changed.emit() if restart_consoles: self.restart_consoles()
def run_script(self, filename=None, silent=False, set_focus=False, args=None): """Run a Python script""" if filename is None: self.shell.interpreter.restore_stds() filename, _selfilter = getopenfilename( self, _("Run Python script"), getcwd_or_home(), _("Python scripts")+" (*.py ; *.pyw ; *.ipy)") self.shell.interpreter.redirect_stds() if filename: os.chdir( osp.dirname(filename) ) filename = osp.basename(filename) else: return logger.debug("Running script with %s", args) filename = osp.abspath(filename) rbs = remove_backslashes command = "runfile('%s', args='%s')" % (rbs(filename), rbs(args)) if set_focus: self.shell.setFocus() if self.dockwidget and not self.ismaximized: self.dockwidget.setVisible(True) self.dockwidget.raise_() self.shell.write(command+'\n') self.shell.run_command(command)
def compare(self): filename, _selfilter = getopenfilename( self, _("Select script to compare"), getcwd_or_home(), _("Profiler result")+" (*.Result)") if filename: self.datatree.compare(filename) self.show_data() self.clear_button.setEnabled(True)
def save_data(self): """Save data""" title = _( "Save profiler result") filename, _selfilter = getsavefilename( self, title, getcwd_or_home(), _("Profiler result")+" (*.Result)") if filename: self.datatree.save_data(filename)
def select_directory(self): """Select directory""" self.redirect_stdio.emit(False) directory = getexistingdirectory(self.main, _("Select directory"), getcwd_or_home()) if directory: self.chdir(directory) self.redirect_stdio.emit(True)
def save_all_figures_as(self): """Save all the figures to a file.""" self.redirect_stdio.emit(False) dirname = getexistingdirectory(self, caption='Save all figures', basedir=getcwd_or_home()) self.redirect_stdio.emit(True) if dirname: return self.save_all_figures_todir(dirname)
def select_file(self): self.redirect_stdio.emit(False) filename, _selfilter = getopenfilename( self, _("Select Python file"), getcwd_or_home(), _("Python files")+" (*.py ; *.pyw)") self.redirect_stdio.emit(True) if filename: self.analyze(filename)
def refresh_plugin(self): """Refresh widget""" curdir = getcwd_or_home() self.pathedit.add_text(curdir) self.save_wdhistory() self.set_previous_enabled.emit( self.histindex is not None and self.histindex > 0) self.set_next_enabled.emit(self.histindex is not None and \ self.histindex < len(self.history)-1)
def select_directory(self): """Select directory""" basedir = to_text_string(self.wd_edit.text()) if not osp.isdir(basedir): basedir = getcwd_or_home() directory = getexistingdirectory(self, _("Select directory"), basedir) if directory: self.wd_edit.setText(directory) self.dir = directory
def select_directory(self, edit): """Select directory""" basedir = to_text_string(edit.text()) if not osp.isdir(basedir): basedir = getcwd_or_home() title = _("Select directory") directory = getexistingdirectory(self, title, basedir) if directory: edit.setText(directory)
def select_file(self, edit, filters=None): """Select File""" basedir = osp.dirname(to_text_string(edit.text())) if not osp.isdir(basedir): basedir = getcwd_or_home() if filters is None: filters = _("All files (*)") title = _("Select file") filename, _selfilter = getopenfilename(self, title, basedir, filters) if filename: edit.setText(filename)
def setup_page(self): about_label = QLabel(_("The <b>current working directory</b> is " "the working directory for IPython consoles " "and the current directory for the File Explorer.")) about_label.setWordWrap(True) console_group = QGroupBox(_("Console directory")) console_label = QLabel(_("The working directory for new consoles is:")) console_label.setWordWrap(True) console_bg = QButtonGroup(console_group) console_project_radio = self.create_radiobutton( _("The current project directory " "or user home directory " "(if no project is active)"), 'console/use_project_or_home_directory', True, button_group=console_bg) console_cwd_radio = self.create_radiobutton( _("The current working directory"), 'console/use_cwd', False, button_group=console_bg) console_dir_radio = self.create_radiobutton( _("the following directory:"), 'console/use_fixed_directory', False, _("The directory when a new console " "is open will be the specified path"), button_group=console_bg) console_dir_bd = self.create_browsedir("", 'console/fixed_directory', getcwd_or_home()) console_dir_radio.toggled.connect(console_dir_bd.setEnabled) console_project_radio.toggled.connect(console_dir_bd.setDisabled) console_cwd_radio.toggled.connect(console_dir_bd.setDisabled) console_dir_layout = QHBoxLayout() console_dir_layout.addWidget(console_dir_radio) console_dir_layout.addWidget(console_dir_bd) console_layout = QVBoxLayout() console_layout.addWidget(console_label) console_layout.addWidget(console_project_radio) console_layout.addWidget(console_cwd_radio) console_layout.addLayout(console_dir_layout) console_group.setLayout(console_layout) vlayout = QVBoxLayout() vlayout.addWidget(about_label) vlayout.addSpacing(10) vlayout.addWidget(console_group) vlayout.addStretch(1) self.setLayout(vlayout)
def __init__(self, parent=None, pathlist=None, ro_pathlist=None, not_active_pathlist=None, sync=True): 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) assert isinstance(pathlist, list) self.pathlist = pathlist if not_active_pathlist is None: not_active_pathlist = [] self.not_active_pathlist = not_active_pathlist if ro_pathlist is None: ro_pathlist = [] self.ro_pathlist = ro_pathlist self.last_path = getcwd_or_home() self.setWindowTitle(_("PYTHONPATH manager")) self.setWindowIcon(ima.icon('pythonpath')) self.resize(500, 300) self.selection_widgets = [] layout = QVBoxLayout() self.setLayout(layout) top_layout = QHBoxLayout() layout.addLayout(top_layout) self.toolbar_widgets1 = self.setup_top_toolbar(top_layout) self.listwidget = QListWidget(self) self.listwidget.currentRowChanged.connect(self.refresh) self.listwidget.itemChanged.connect(self.update_not_active_pathlist) layout.addWidget(self.listwidget) bottom_layout = QHBoxLayout() layout.addLayout(bottom_layout) self.sync_button = None self.toolbar_widgets2 = self.setup_bottom_toolbar(bottom_layout, sync) # Buttons configuration bbox = QDialogButtonBox(QDialogButtonBox.Close) bbox.rejected.connect(self.reject) bottom_layout.addWidget(bbox) self.update_list() self.refresh()
def save_dictionary(data, filename): """Save dictionary in a single file .spydata file""" filename = osp.abspath(filename) old_cwd = getcwd_or_home() os.chdir(osp.dirname(filename)) error_message = None try: saved_arrays = {} if load_array is not None: # Saving numpy arrays with np.save arr_fname = osp.splitext(filename)[0] for name in list(data.keys()): if isinstance(data[name], np.ndarray) and data[name].size > 0: # Saving arrays at data root fname = __save_array(data[name], arr_fname, len(saved_arrays)) saved_arrays[(name, None)] = osp.basename(fname) data.pop(name) elif isinstance(data[name], (list, dict)): # Saving arrays nested in lists or dictionaries if isinstance(data[name], list): iterator = enumerate(data[name]) else: iterator = iter(list(data[name].items())) to_remove = [] for index, value in iterator: if isinstance(value, np.ndarray) and value.size > 0: fname = __save_array(value, arr_fname, len(saved_arrays)) saved_arrays[(name, index)] = osp.basename(fname) to_remove.append(index) for index in sorted(to_remove, reverse=True): data[name].pop(index) if saved_arrays: data['__saved_arrays__'] = saved_arrays pickle_filename = osp.splitext(filename)[0]+'.pickle' with open(pickle_filename, 'wb') as fdesc: pickle.dump(data, fdesc, 2) tar = tarfile.open(filename, "w") for fname in [pickle_filename]+[fn for fn in list(saved_arrays.values())]: tar.add(osp.basename(fname)) os.remove(fname) tar.close() if saved_arrays: data.pop('__saved_arrays__') except (RuntimeError, pickle.PicklingError, TypeError) as error: error_message = to_text_string(error) os.chdir(old_cwd) return error_message
def guess_filename(filename): """Guess filename""" if osp.isfile(filename): return filename if not filename.endswith('.py'): filename += '.py' for path in [getcwd_or_home()] + sys.path: fname = osp.join(path, filename) if osp.isfile(fname): return fname elif osp.isfile(fname+'.py'): return fname+'.py' elif osp.isfile(fname+'.pyw'): return fname+'.pyw' return filename
def save_figure_as(self, fig, fmt): """Save the figure to a file.""" fext, ffilt = { 'image/png': ('.png', 'PNG (*.png)'), 'image/jpeg': ('.jpg', 'JPEG (*.jpg;*.jpeg;*.jpe;*.jfif)'), 'image/svg+xml': ('.svg', 'SVG (*.svg);;PNG (*.png)')}[fmt] figname = get_unique_figname(getcwd_or_home(), 'Figure', fext) self.redirect_stdio.emit(False) fname, fext = getsavefilename( parent=self.parent(), caption='Save Figure', basedir=figname, filters=ffilt, selectedfilter='', options=None) self.redirect_stdio.emit(True) if fname: save_figure_tofile(fig, fmt, fname)
def load_dictionary(filename): """Load dictionary from .spydata file""" filename = osp.abspath(filename) old_cwd = getcwd_or_home() tmp_folder = tempfile.mkdtemp() os.chdir(tmp_folder) data = None error_message = None try: tar = tarfile.open(filename, "r") tar.extractall() data_file = osp.basename(filename) pickle_filename = osp.splitext(data_file)[0]+'.pickle' try: # Old format (Spyder 2.0-2.1 for Python 2) with open(pickle_filename, 'U') as fdesc: data = pickle.loads(fdesc.read()) except (pickle.PickleError, TypeError, UnicodeDecodeError): # New format (Spyder >=2.2 for Python 2 and Python 3) with open(pickle_filename, 'rb') as fdesc: data = pickle.loads(fdesc.read()) saved_arrays = {} if load_array is not None: # Loading numpy arrays saved with np.save try: saved_arrays = data.pop('__saved_arrays__') for (name, index), fname in list(saved_arrays.items()): arr = np.load( osp.join(tmp_folder, fname) ) if index is None: data[name] = arr elif isinstance(data[name], dict): data[name][index] = arr else: data[name].insert(index, arr) except KeyError: pass except (EOFError, ValueError) as error: error_message = to_text_string(error) os.chdir(old_cwd) try: shutil.rmtree(tmp_folder) except OSError as error: error_message = to_text_string(error) return data, error_message
def __init__(self, parent, server_settings={}, folder=getcwd_or_home(), language='python'): QObject.__init__(self) # LSPMethodProviderMixIn.__init__(self) self.manager = parent self.zmq_in_socket = None self.zmq_out_socket = None self.zmq_in_port = None self.zmq_out_port = None self.transport_client = None self.language = language self.initialized = False self.ready_to_close = False self.request_seq = 1 self.req_status = {} self.watched_files = {} self.req_reply = {} self.transport_args = [sys.executable, '-u', osp.join(LOCATION, 'transport', 'main.py')] self.external_server = server_settings.get('external', False) self.folder = folder self.plugin_configurations = server_settings.get('configurations', {}) self.client_capabilites = CLIENT_CAPABILITES self.server_capabilites = SERVER_CAPABILITES self.context = zmq.Context() server_args_fmt = server_settings.get('args', '') server_args = server_args_fmt.format(**server_settings) # transport_args = self.local_server_fmt % (server_settings) # if self.external_server: transport_args = self.external_server_fmt % (server_settings) self.server_args = [sys.executable, '-m', server_settings['cmd']] self.server_args += server_args.split(' ') self.transport_args += transport_args.split(' ') self.transport_args += ['--folder', folder] self.transport_args += ['--transport-debug', str(get_debug_level())]
def __init__(self, figure_viewer, parent=None, background_color=None): super().__init__(parent) self._thumbnails = [] self.background_color = background_color self.save_dir = getcwd_or_home() self.current_thumbnail = None self.set_figureviewer(figure_viewer) self.setup_gui() # Because the range of Qt scrollareas is not updated immediately # after a new item is added to it, setting the scrollbar's value # to its maximum value after adding a new item will scroll down to # the penultimate item instead of the last. # So to scroll programmatically to the latest item after it # is added to the scrollarea, we need to do it instead in a slot # connected to the scrollbar's rangeChanged signal. # See spyder-ide/spyder#10914 for more details. self._new_thumbnail_added = False self.scrollarea.verticalScrollBar().rangeChanged.connect( self._scroll_to_newest_item)
def save_figure_as(self, fig, fmt): """Save the figure to a file.""" fext, ffilt = { 'image/png': ('.png', 'PNG (*.png)'), 'image/jpeg': ('.jpg', 'JPEG (*.jpg;*.jpeg;*.jpe;*.jfif)'), 'image/svg+xml': ('.svg', 'SVG (*.svg);;PNG (*.png)') }[fmt] figname = get_unique_figname(getcwd_or_home(), 'Figure', fext) self.redirect_stdio.emit(False) fname, fext = getsavefilename(parent=self.parent(), caption='Save Figure', basedir=figname, filters=ffilt, selectedfilter='', options=None) self.redirect_stdio.emit(True) if fname: save_figure_tofile(fig, fmt, fname)
def select_file(self, filename=None): """ Select filename to profile. Parameters ---------- filename: str, optional Path to filename to profile. default is None. Notes ----- If no `filename` is provided an open filename dialog will be used. """ if filename is None: self.sig_redirect_stdio_requested.emit(False) filename, _selfilter = getopenfilename( self, _("Select Python script"), getcwd_or_home(), _("Python scripts") + " (*.py ; *.pyw)") self.sig_redirect_stdio_requested.emit(True) if filename: self.analyze(filename)
def start(self): """Start the code analysis.""" filename = str(self.filecombo.currentText()) self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setWorkingDirectory(getcwd_or_home()) self.process.readyReadStandardOutput.connect(self.read_output) self.process.readyReadStandardError.connect( lambda: self.read_output(error=True)) self.process.finished.connect( lambda ec, es=QProcess.ExitStatus: self.finished(ec, es)) self.stop_button.clicked.connect(self.process.kill) self.output = '' self.error_output = '' if PYLINT_VER is not None: pylint_args = [ '-m', 'pylint', '--output-format=text', '--msg-template=' "'{msg_id}:{symbol}:{line:3d},{column}: {msg}'" ] pylintrc_path = self.get_pylintrc_path(filename=filename) if pylintrc_path is not None: pylint_args += ['--rcfile={}'.format(pylintrc_path)] pylint_args.append(filename) processEnvironment = QProcessEnvironment() processEnvironment.insert("PYTHONIOENCODING", "utf8") self.process.setProcessEnvironment(processEnvironment) self.process.start(sys.executable, pylint_args) running = self.process.waitForStarted() self.set_running_state(running) if not running: QMessageBox.critical(self, _("Error"), _("Process failed to start"))
def save_data(self): """Save data""" filename = self.filename if filename is None: filename = getcwd_or_home() extension = osp.splitext(filename)[1].lower() if not extension: # Needed to prevent trying to save a data file without extension # See spyder-ide/spyder#7196 filename = filename + '.spydata' filename, _selfilter = getsavefilename(self, _("Save data"), filename, iofunctions.save_filters) if filename: self.filename = filename else: return False QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() error_message = self.shellwidget.save_namespace(self.filename) QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: if 'Some objects could not be saved:' in error_message: save_data_message = ( _("<b>Some objects could not be saved:</b>") + "<br><br><code>{obj_list}</code>".format( obj_list=error_message.split(': ')[1])) else: save_data_message = _( "<b>Unable to save current workspace</b>" "<br><br>" "The error message was:<br>") + error_message QMessageBox.critical(self, _("Save data"), save_data_message)
def open_project(self, path=None, restart_consoles=True, save_previous_files=True): """Open the project located in `path`""" if path is None: basedir = get_home_dir() path = getexistingdirectory(parent=self, caption=_("Open project"), basedir=basedir) if not self.is_valid_project(path): if path: QMessageBox.critical( self, _('Error'), _("<b>%s</b> is not a Spyder project!") % path) return else: self.add_to_recent(path) # A project was not open before if self.current_active_project is None: if save_previous_files: self.editor.save_open_files() self.editor.set_option('last_working_dir', getcwd_or_home()) self.show_explorer() else: # we are switching projects self.set_project_filenames(self.editor.get_open_filenames()) self.current_active_project = EmptyProject(path) self.latest_project = EmptyProject(path) self.set_option('current_project_path', self.get_active_project_path()) self.setup_menu_actions() self.sig_project_loaded.emit(path) self.pythonpath_changed.emit() if restart_consoles: self.restart_consoles()
def select_directory(self, directory=None): """ Select working directory. Parameters ---------- directory: str, optional The directory to change to. Notes ----- If directory is None, a get directorty dialog will be used. """ if directory is None: self.sig_redirect_stdio_requested.emit(False) directory = getexistingdirectory( self, _("Select directory"), getcwd_or_home(), ) self.sig_redirect_stdio_requested.emit(True) if directory: self.chdir(directory)
def run_script(self, filename=None, silent=False, set_focus=False, args=None): """Run a Python script""" if filename is None: self.shell.interpreter.restore_stds() filename, _selfilter = getopenfilename( self, _("Run Python script"), getcwd_or_home(), _("Python scripts")+" (*.py ; *.pyw ; *.ipy)") self.shell.interpreter.redirect_stds() if filename: os.chdir( osp.dirname(filename) ) filename = osp.basename(filename) else: return logger.debug("Running script with %s", args) filename = osp.abspath(filename) rbs = remove_backslashes command = "runfile('%s', args='%s')" % (rbs(filename), rbs(args)) if set_focus: self.shell.setFocus() if self.dockwidget: self.switch_to_plugin() self.shell.write(command+'\n') self.shell.run_command(command)
def __init__(self, parent, search_text, search_text_regexp, search_path, exclude, exclude_idx, exclude_regexp, supported_encodings, in_python_path, more_options, case_sensitive, external_path_history): QWidget.__init__(self, parent) if search_path is None: search_path = getcwd_or_home() if not isinstance(search_text, (list, tuple)): search_text = [search_text] if not isinstance(search_path, (list, tuple)): search_path = [search_path] if not isinstance(exclude, (list, tuple)): exclude = [exclude] if not isinstance(external_path_history, (list, tuple)): external_path_history = [external_path_history] self.supported_encodings = supported_encodings # Layout 1 hlayout1 = QHBoxLayout() self.search_text = PatternComboBox(self, search_text, _("Search pattern")) self.edit_regexp = create_toolbutton(self, icon=ima.icon('advanced'), tip=_('Regular expression')) self.case_button = create_toolbutton(self, icon=get_icon("upper_lower.png"), tip=_("Case Sensitive")) self.case_button.setCheckable(True) self.case_button.setChecked(case_sensitive) self.edit_regexp.setCheckable(True) self.edit_regexp.setChecked(search_text_regexp) self.more_widgets = () self.more_options = create_toolbutton(self, toggled=self.toggle_more_options) self.more_options.setCheckable(True) self.more_options.setChecked(more_options) self.ok_button = create_toolbutton(self, text=_("Search"), icon=ima.icon('find'), triggered=lambda: self.find.emit(), tip=_("Start search"), text_beside_icon=True) self.ok_button.clicked.connect(self.update_combos) self.stop_button = create_toolbutton( self, text=_("Stop"), icon=ima.icon('editclear'), triggered=lambda: self.stop.emit(), tip=_("Stop search"), text_beside_icon=True) self.stop_button.setEnabled(False) for widget in [ self.search_text, self.edit_regexp, self.case_button, self.ok_button, self.stop_button, self.more_options ]: hlayout1.addWidget(widget) # Layout 2 hlayout2 = QHBoxLayout() self.exclude_pattern = PatternComboBox(self, exclude, _("Excluded filenames pattern")) if exclude_idx is not None and exclude_idx >= 0 \ and exclude_idx < self.exclude_pattern.count(): self.exclude_pattern.setCurrentIndex(exclude_idx) self.exclude_regexp = create_toolbutton(self, icon=ima.icon('advanced'), tip=_('Regular expression')) self.exclude_regexp.setCheckable(True) self.exclude_regexp.setChecked(exclude_regexp) exclude_label = QLabel(_("Exclude:")) exclude_label.setBuddy(self.exclude_pattern) for widget in [ exclude_label, self.exclude_pattern, self.exclude_regexp ]: hlayout2.addWidget(widget) # Layout 3 hlayout3 = QHBoxLayout() search_on_label = QLabel(_("Search in:")) self.path_selection_combo = SearchInComboBox(external_path_history, parent) hlayout3.addWidget(search_on_label) hlayout3.addWidget(self.path_selection_combo) self.search_text.valid.connect(lambda valid: self.find.emit()) self.exclude_pattern.valid.connect(lambda valid: self.find.emit()) vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.addLayout(hlayout1) vlayout.addLayout(hlayout2) vlayout.addLayout(hlayout3) self.more_widgets = (hlayout2, ) self.toggle_more_options(more_options) self.setLayout(vlayout) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
def refreshdir(self): """Refresh search directory""" self.findinfiles.find_options.set_directory( getcwd_or_home())
def import_data(self, filenames=None): """Import data from text file.""" title = _("Import data") if filenames is None: if self.filename is None: basedir = getcwd_or_home() else: basedir = osp.dirname(self.filename) filenames, _selfilter = getopenfilenames(self, title, basedir, iofunctions.load_filters) if not filenames: return elif 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.editor.new_value(var_name, clip_data) except Exception as error: error_message = str(error) else: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() error_message = self.shellwidget.load_data(self.filename, ext) self.shellwidget._kernel_reply = None 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 setup_page(self): about_label = QLabel( _("The <b>current working directory</b> is " "the working directory for IPython consoles " "and the current directory for the File Explorer.")) about_label.setWordWrap(True) startup_group = QGroupBox(_("Startup")) startup_bg = QButtonGroup(startup_group) startup_label = QLabel( _("At startup, the current working " "directory is:")) startup_label.setWordWrap(True) lastdir_radio = self.create_radiobutton( _("The current project directory " "or user home directory " "(if no project is active)"), 'startup/use_project_or_home_directory', True, _("At startup,"), # TODO button_group=startup_bg) thisdir_radio = self.create_radiobutton( _("the following directory:"), 'startup/use_fixed_directory', False, _("At startup, the current working " "directory will be the specified path"), button_group=startup_bg) thisdir_bd = self.create_browsedir("", 'startup/fixed_directory', getcwd_or_home()) thisdir_radio.toggled.connect(thisdir_bd.setEnabled) lastdir_radio.toggled.connect(thisdir_bd.setDisabled) thisdir_layout = QHBoxLayout() thisdir_layout.addWidget(thisdir_radio) thisdir_layout.addWidget(thisdir_bd) startup_layout = QVBoxLayout() startup_layout.addWidget(startup_label) startup_layout.addWidget(lastdir_radio) startup_layout.addLayout(thisdir_layout) startup_group.setLayout(startup_layout) # Console Directory console_group = QGroupBox(_("Console directory")) console_label = QLabel(_("The working directory for new consoles is:")) console_label.setWordWrap(True) console_bg = QButtonGroup(console_group) console_project_radio = self.create_radiobutton( _("The current project directory " "or user home directory " "(if no project is active)"), 'console/use_project_or_home_directory', True, button_group=console_bg) console_cwd_radio = self.create_radiobutton( _("The current working directory"), 'console/use_cwd', False, button_group=console_bg) console_dir_radio = self.create_radiobutton( _("the following directory:"), 'console/use_fixed_directory', False, _("The directory when a new console " "is open will be the specified path"), button_group=console_bg) console_dir_bd = self.create_browsedir("", 'console/fixed_directory', getcwd_or_home()) console_dir_radio.toggled.connect(console_dir_bd.setEnabled) console_project_radio.toggled.connect(console_dir_bd.setDisabled) console_cwd_radio.toggled.connect(console_dir_bd.setDisabled) console_dir_layout = QHBoxLayout() console_dir_layout.addWidget(console_dir_radio) console_dir_layout.addWidget(console_dir_bd) console_layout = QVBoxLayout() console_layout.addWidget(console_label) console_layout.addWidget(console_project_radio) console_layout.addWidget(console_cwd_radio) console_layout.addLayout(console_dir_layout) console_group.setLayout(console_layout) vlayout = QVBoxLayout() vlayout.addWidget(about_label) vlayout.addSpacing(10) vlayout.addWidget(startup_group) vlayout.addWidget(console_group) vlayout.addStretch(1) self.setLayout(vlayout)
def parent_directory(self): """Change working directory to parent directory""" self.chdir(os.path.join(getcwd_or_home(), os.path.pardir))
def get_last_working_dir(self): """Get the path of the last working directory""" return self.get_conf( 'last_working_dir', section='editor', default=getcwd_or_home())
def __init__(self, parent, server_settings={}, folder=getcwd_or_home(), language='python'): QObject.__init__(self) # LSPMethodProviderMixIn.__init__(self) self.manager = parent self.zmq_in_socket = None self.zmq_out_socket = None self.zmq_in_port = None self.zmq_out_port = None self.transport_client = None self.language = language self.initialized = False self.ready_to_close = False self.request_seq = 1 self.req_status = {} self.watched_files = {} self.watched_folders = {} self.req_reply = {} self.transport_args = [ sys.executable, '-u', osp.join(LOCATION, 'transport', 'main.py') ] self.external_server = server_settings.get('external', False) self.stdio = server_settings.get('stdio', False) # Setting stdio on implies that external_server is off if self.stdio and self.external_server: error = ('If server is set to use stdio communication, ' 'then it cannot be an external server') logger.error(error) raise AssertionError(error) self.folder = folder self.plugin_configurations = server_settings.get('configurations', {}) self.client_capabilites = CLIENT_CAPABILITES self.server_capabilites = SERVER_CAPABILITES self.context = zmq.Context() server_args_fmt = server_settings.get('args', '') server_args = server_args_fmt.format(**server_settings) transport_args = self.external_server_fmt % (server_settings) self.server_args = [] if language == 'python': self.server_args += [sys.executable, '-m'] self.server_args += [server_settings['cmd']] if len(server_args) > 0: self.server_args += server_args.split(' ') self.transport_args += transport_args.split(' ') self.transport_args += ['--folder', folder] self.transport_args += ['--transport-debug', str(get_debug_level())] if not self.stdio: self.transport_args += ['--external-server'] else: self.transport_args += ['--stdio-server'] self.external_server = True
def refreshdir(self): """Refresh search directory""" self.findinfiles.find_options.set_directory(getcwd_or_home())
def setup_page(self): about_label = QLabel( _("This is the directory that will be set as the default for " "the IPython console and Files panes.")) about_label.setWordWrap(True) # Startup directory startup_group = QGroupBox(_("Startup")) startup_bg = QButtonGroup(startup_group) startup_label = QLabel(_("At startup, the working directory is:")) startup_label.setWordWrap(True) lastdir_radio = self.create_radiobutton( _("The project (if open) or user home directory"), 'startup/use_project_or_home_directory', tip=_("The startup working dir will be root of the " "current project if one is open, otherwise the " "user home directory"), button_group=startup_bg) thisdir_radio = self.create_radiobutton( _("The following directory:"), 'startup/use_fixed_directory', _("At startup, the current working directory will be the " "specified path"), button_group=startup_bg) thisdir_bd = self.create_browsedir("", 'startup/fixed_directory', getcwd_or_home()) thisdir_radio.toggled.connect(thisdir_bd.setEnabled) lastdir_radio.toggled.connect(thisdir_bd.setDisabled) thisdir_layout = QHBoxLayout() thisdir_layout.addWidget(thisdir_radio) thisdir_layout.addWidget(thisdir_bd) startup_layout = QVBoxLayout() startup_layout.addWidget(startup_label) startup_layout.addWidget(lastdir_radio) startup_layout.addLayout(thisdir_layout) startup_group.setLayout(startup_layout) # Console Directory console_group = QGroupBox(_("New consoles")) console_label = QLabel( _("The working directory for new IPython consoles is:")) console_label.setWordWrap(True) console_bg = QButtonGroup(console_group) console_project_radio = self.create_radiobutton( _("The project (if open) or user home directory"), 'console/use_project_or_home_directory', tip=_("The working dir for new consoles will be root of the " "project if one is open, otherwise the user home directory"), button_group=console_bg) console_cwd_radio = self.create_radiobutton( _("The working directory of the current console"), 'console/use_cwd', button_group=console_bg) console_dir_radio = self.create_radiobutton( _("The following directory:"), 'console/use_fixed_directory', _("The directory when a new console is open will be the " "specified path"), button_group=console_bg) console_dir_bd = self.create_browsedir("", 'console/fixed_directory', getcwd_or_home()) console_dir_radio.toggled.connect(console_dir_bd.setEnabled) console_project_radio.toggled.connect(console_dir_bd.setDisabled) console_cwd_radio.toggled.connect(console_dir_bd.setDisabled) console_dir_layout = QHBoxLayout() console_dir_layout.addWidget(console_dir_radio) console_dir_layout.addWidget(console_dir_bd) console_layout = QVBoxLayout() console_layout.addWidget(console_label) console_layout.addWidget(console_project_radio) console_layout.addWidget(console_cwd_radio) console_layout.addLayout(console_dir_layout) console_group.setLayout(console_layout) vlayout = QVBoxLayout() vlayout.addWidget(about_label) vlayout.addSpacing(10) vlayout.addWidget(startup_group) vlayout.addWidget(console_group) vlayout.addStretch(1) self.setLayout(vlayout)
def __init__(self, parent, server_settings={}, folder=getcwd_or_home(), language='python'): QObject.__init__(self) self.manager = parent self.zmq_in_socket = None self.zmq_out_socket = None self.zmq_in_port = None self.zmq_out_port = None self.transport = None self.server = None self.stdio_pid = None self.notifier = None self.language = language self.initialized = False self.ready_to_close = False self.request_seq = 1 self.req_status = {} self.watched_files = {} self.watched_folders = {} self.req_reply = {} self.server_unresponsive = False self.transport_unresponsive = False # Select a free port to start the server. # NOTE: Don't use the new value to set server_setttings['port']!! # That's not required because this doesn't really correspond to a # change in the config settings of the server. Else a server # restart would be generated when doing a # workspace/didChangeConfiguration request. if not server_settings['external']: self.server_port = select_port( default_port=server_settings['port']) else: self.server_port = server_settings['port'] self.server_host = server_settings['host'] self.external_server = server_settings.get('external', False) self.stdio = server_settings.get('stdio', False) # Setting stdio on implies that external_server is off if self.stdio and self.external_server: error = ('If server is set to use stdio communication, ' 'then it cannot be an external server') logger.error(error) raise AssertionError(error) self.folder = folder self.configurations = server_settings.get('configurations', {}) self.client_capabilites = CLIENT_CAPABILITES self.server_capabilites = SERVER_CAPABILITES self.context = zmq.Context() # To set server args self._server_args = server_settings.get('args', '') self._server_cmd = server_settings['cmd'] # Save requests name and id. This is only necessary for testing. self._requests = []
def __init__(self, parent, path=None, read_only_path=None, not_active_path=None, sync=True): """Path manager dialog.""" super(PathManager, self).__init__(parent) assert isinstance(path, (tuple, None)) self.path = path or () self.read_only_path = read_only_path or () self.not_active_path = not_active_path or () self.last_path = getcwd_or_home() self.original_path_dict = None # Widgets self.add_button = None self.remove_button = None self.movetop_button = None self.moveup_button = None self.movedown_button = None self.movebottom_button = None self.sync_button = None self.selection_widgets = [] self.top_toolbar_widgets = self._setup_top_toolbar() self.bottom_toolbar_widgets = self._setup_bottom_toolbar() self.listwidget = QListWidget(self) self.bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_ok = self.bbox.button(QDialogButtonBox.Ok) # Widget setup # 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.setWindowTitle(_("PYTHONPATH manager")) self.setWindowIcon(ima.icon('pythonpath')) self.resize(500, 300) self.sync_button.setVisible(os.name == 'nt' and sync) # Layouts top_layout = QHBoxLayout() self._add_widgets_to_layout(self.top_toolbar_widgets, top_layout) bottom_layout = QHBoxLayout() self._add_widgets_to_layout(self.bottom_toolbar_widgets, bottom_layout) bottom_layout.addWidget(self.bbox) layout = QVBoxLayout() layout.addLayout(top_layout) layout.addWidget(self.listwidget) layout.addLayout(bottom_layout) self.setLayout(layout) # Signals self.listwidget.currentRowChanged.connect(lambda x: self.refresh()) self.listwidget.itemChanged.connect(lambda x: self.refresh()) self.bbox.accepted.connect(self.accept) self.bbox.rejected.connect(self.reject) # Setup self.setup()
def get_cdlistdir(self): """Return shell current directory list dir""" return os.listdir(getcwd_or_home())
def setup_page(self): about_label = QLabel(_("The following are the default options for " "running files.These options may be overriden " "using the <b>Configuration per file</b> entry " "of the <b>Run</b> menu.")) about_label.setWordWrap(True) interpreter_group = QGroupBox(_("Console")) interpreter_bg = QButtonGroup(interpreter_group) self.current_radio = self.create_radiobutton(CURRENT_INTERPRETER, CURRENT_INTERPRETER_OPTION, True, button_group=interpreter_bg) self.dedicated_radio = self.create_radiobutton(DEDICATED_INTERPRETER, DEDICATED_INTERPRETER_OPTION, False, button_group=interpreter_bg) self.systerm_radio = self.create_radiobutton(SYSTERM_INTERPRETER, SYSTERM_INTERPRETER_OPTION, False, button_group=interpreter_bg) interpreter_layout = QVBoxLayout() interpreter_group.setLayout(interpreter_layout) interpreter_layout.addWidget(self.current_radio) interpreter_layout.addWidget(self.dedicated_radio) interpreter_layout.addWidget(self.systerm_radio) general_group = QGroupBox(_("General settings")) post_mortem = self.create_checkbox(POST_MORTEM, 'post_mortem', False) clear_variables = self.create_checkbox(CLEAR_ALL_VARIABLES, 'clear_namespace', False) general_layout = QVBoxLayout() general_layout.addWidget(clear_variables) general_layout.addWidget(post_mortem) general_group.setLayout(general_layout) wdir_group = QGroupBox(_("Working Directory settings")) wdir_bg = QButtonGroup(wdir_group) wdir_label = QLabel(_("Default working directory is:")) wdir_label.setWordWrap(True) dirname_radio = self.create_radiobutton( FILE_DIR, WDIR_USE_SCRIPT_DIR_OPTION, True, button_group=wdir_bg) cwd_radio = self.create_radiobutton( CW_DIR, WDIR_USE_CWD_DIR_OPTION, False, button_group=wdir_bg) thisdir_radio = self.create_radiobutton( FIXED_DIR, WDIR_USE_FIXED_DIR_OPTION, False, button_group=wdir_bg) thisdir_bd = self.create_browsedir("", WDIR_FIXED_DIR_OPTION, getcwd_or_home()) thisdir_radio.toggled.connect(thisdir_bd.setEnabled) dirname_radio.toggled.connect(thisdir_bd.setDisabled) cwd_radio.toggled.connect(thisdir_bd.setDisabled) thisdir_layout = QHBoxLayout() thisdir_layout.addWidget(thisdir_radio) thisdir_layout.addWidget(thisdir_bd) wdir_layout = QVBoxLayout() wdir_layout.addWidget(wdir_label) wdir_layout.addWidget(dirname_radio) wdir_layout.addWidget(cwd_radio) wdir_layout.addLayout(thisdir_layout) wdir_group.setLayout(wdir_layout) external_group = QGroupBox(_("External system terminal")) interact_after = self.create_checkbox(INTERACT, 'interact', False) external_layout = QVBoxLayout() external_layout.addWidget(interact_after) external_group.setLayout(external_layout) firstrun_cb = self.create_checkbox( ALWAYS_OPEN_FIRST_RUN % _("Run Settings dialog"), ALWAYS_OPEN_FIRST_RUN_OPTION, False) vlayout = QVBoxLayout() vlayout.addWidget(about_label) vlayout.addSpacing(10) vlayout.addWidget(interpreter_group) vlayout.addWidget(general_group) vlayout.addWidget(wdir_group) vlayout.addWidget(external_group) vlayout.addWidget(firstrun_cb) vlayout.addStretch(1) self.setLayout(vlayout)
def __init__(self, parent, search_text, search_text_regexp, search_path, exclude, exclude_idx, exclude_regexp, supported_encodings, in_python_path, more_options, case_sensitive, external_path_history): QWidget.__init__(self, parent) if search_path is None: search_path = getcwd_or_home() self.path = '' self.project_path = None self.file_path = None self.external_path = None self.external_path_history = external_path_history if not isinstance(search_text, (list, tuple)): search_text = [search_text] if not isinstance(search_path, (list, tuple)): search_path = [search_path] if not isinstance(exclude, (list, tuple)): exclude = [exclude] if not isinstance(external_path_history, (list, tuple)): external_path_history = [external_path_history] self.supported_encodings = supported_encodings # Layout 1 hlayout1 = QHBoxLayout() self.search_text = PatternComboBox(self, search_text, _("Search pattern")) self.edit_regexp = create_toolbutton(self, icon=ima.icon('advanced'), tip=_('Regular expression')) self.case_button = create_toolbutton(self, icon=get_icon("upper_lower.png"), tip=_("Case Sensitive")) self.case_button.setCheckable(True) self.case_button.setChecked(case_sensitive) self.edit_regexp.setCheckable(True) self.edit_regexp.setChecked(search_text_regexp) self.more_widgets = () self.more_options = create_toolbutton(self, toggled=self.toggle_more_options) self.more_options.setCheckable(True) self.more_options.setChecked(more_options) self.ok_button = create_toolbutton(self, text=_("Search"), icon=ima.icon('find'), triggered=lambda: self.find.emit(), tip=_("Start search"), text_beside_icon=True) self.ok_button.clicked.connect(self.update_combos) self.stop_button = create_toolbutton( self, text=_("Stop"), icon=ima.icon('editclear'), triggered=lambda: self.stop.emit(), tip=_("Stop search"), text_beside_icon=True) self.stop_button.setEnabled(False) for widget in [ self.search_text, self.edit_regexp, self.case_button, self.ok_button, self.stop_button, self.more_options ]: hlayout1.addWidget(widget) # Layout 2 hlayout2 = QHBoxLayout() self.exclude_pattern = PatternComboBox(self, exclude, _("Excluded filenames pattern")) if exclude_idx is not None and exclude_idx >= 0 \ and exclude_idx < self.exclude_pattern.count(): self.exclude_pattern.setCurrentIndex(exclude_idx) self.exclude_regexp = create_toolbutton(self, icon=ima.icon('advanced'), tip=_('Regular expression')) self.exclude_regexp.setCheckable(True) self.exclude_regexp.setChecked(exclude_regexp) exclude_label = QLabel(_("Exclude:")) exclude_label.setBuddy(self.exclude_pattern) for widget in [ exclude_label, self.exclude_pattern, self.exclude_regexp ]: hlayout2.addWidget(widget) # Layout 3 hlayout3 = QHBoxLayout() search_on_label = QLabel(_("Search in:")) self.path_selection_combo = PatternComboBox(self, exclude, _('Search directory')) self.path_selection_combo.setEditable(False) self.path_selection_contents = QListWidget(self.path_selection_combo) self.path_selection_contents.hide() self.path_selection_combo.setModel( self.path_selection_contents.model()) self.path_selection_contents.addItem(_("Current working directory")) item = self.path_selection_contents.item(0) item.setToolTip( _("Search in all files and " "directories present on the" "current Spyder path")) self.path_selection_contents.addItem(_("Project")) item = self.path_selection_contents.item(1) item.setToolTip( _("Search in all files and " "directories present on the" "current project path " "(If opened)")) item.setFlags(item.flags() & ~Qt.ItemIsEnabled) self.path_selection_contents.addItem(_("File").replace('&', '')) item = self.path_selection_contents.item(2) item.setToolTip(_("Search in current opened file")) self.path_selection_contents.addItem(_("Select other directory")) item = self.path_selection_contents.item(3) item.setToolTip(_("Search in other folder present on the file system")) self.path_selection_combo.insertSeparator(3) self.path_selection_combo.insertSeparator(5) for path in external_path_history: item = ExternalPathItem(None, path) self.path_selection_contents.addItem(item) self.path_selection_combo.currentIndexChanged.connect( self.path_selection_changed) hlayout3.addWidget(search_on_label) hlayout3.addWidget(self.path_selection_combo) self.search_text.valid.connect(lambda valid: self.find.emit()) self.exclude_pattern.valid.connect(lambda valid: self.find.emit()) vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.addLayout(hlayout1) vlayout.addLayout(hlayout2) vlayout.addLayout(hlayout3) self.more_widgets = (hlayout2, ) self.toggle_more_options(more_options) self.setLayout(vlayout) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
def open_project(self, path=None, project=None, restart_consoles=True, save_previous_files=True, workdir=None): """Open the project located in `path`.""" self.unmaximize() if path is None: basedir = get_home_dir() path = getexistingdirectory(parent=self, caption=_("Open project"), basedir=basedir) path = encoding.to_unicode_from_fs(path) if not self.is_valid_project(path): if path: QMessageBox.critical( self, _('Error'), _("<b>%s</b> is not a Spyder project!") % path, ) return else: path = encoding.to_unicode_from_fs(path) if project is None: project_type_class = self._load_project_type_class(path) project = project_type_class( root_path=path, parent_plugin=project_type_class._PARENT_PLUGIN, ) # A project was not open before if self.current_active_project is None: if save_previous_files and self.main.editor is not None: self.main.editor.save_open_files() if self.main.editor is not None: self.main.editor.set_option('last_working_dir', getcwd_or_home()) if self.get_option('visible_if_project_open'): self.show_explorer() else: # We are switching projects if self.main.editor is not None: self.set_project_filenames( self.main.editor.get_open_filenames()) # TODO: Don't emit sig_project_closed when we support # multiple workspaces. self.sig_project_closed.emit(self.current_active_project.root_path) self.current_active_project = project self.latest_project = project self.add_to_recent(path) self.set_option('current_project_path', self.get_active_project_path()) self.setup_menu_actions() if workdir and osp.isdir(workdir): self.sig_project_loaded.emit(workdir) else: self.sig_project_loaded.emit(path) self.sig_pythonpath_changed.emit() self.watcher.start(path) if restart_consoles: self.restart_consoles() open_successfully, message = project.open_project() if not open_successfully: QMessageBox.warning(self, "Project open", message)
def __init__(self, parent, server_settings={}, folder=getcwd_or_home(), language='python'): QObject.__init__(self) self.manager = parent self.zmq_in_socket = None self.zmq_out_socket = None self.zmq_in_port = None self.zmq_out_port = None self.transport_client = None self.lsp_server = None self.notifier = None self.language = language self.initialized = False self.ready_to_close = False self.request_seq = 1 self.req_status = {} self.watched_files = {} self.watched_folders = {} self.req_reply = {} # Select a free port to start the server. # NOTE: Don't use the new value to set server_setttings['port']!! # That's not required because this doesn't really correspond to a # change in the config settings of the server. Else a server # restart would be generated when doing a # workspace/didChangeConfiguration request. if not server_settings['external']: self.server_port = select_port( default_port=server_settings['port']) else: self.server_port = server_settings['port'] self.server_host = server_settings['host'] self.transport_args = [ sys.executable, '-u', osp.join(LOCATION, 'transport', 'main.py') ] self.external_server = server_settings.get('external', False) self.stdio = server_settings.get('stdio', False) # Setting stdio on implies that external_server is off if self.stdio and self.external_server: error = ('If server is set to use stdio communication, ' 'then it cannot be an external server') logger.error(error) raise AssertionError(error) self.folder = folder self.plugin_configurations = server_settings.get('configurations', {}) self.client_capabilites = CLIENT_CAPABILITES self.server_capabilites = SERVER_CAPABILITES self.context = zmq.Context() server_args_fmt = server_settings.get('args', '') server_args = server_args_fmt.format(host=self.server_host, port=self.server_port) transport_args_fmt = '--server-host {host} --server-port {port} ' transport_args = transport_args_fmt.format(host=self.server_host, port=self.server_port) self.server_args = [] if self.language == 'python': self.server_args += [sys.executable, '-m'] self.server_args += [server_settings['cmd']] if len(server_args) > 0: self.server_args += server_args.split(' ') self.server_unresponsive = False self.transport_args += transport_args.split(' ') self.transport_args += ['--folder', folder] self.transport_args += ['--transport-debug', str(get_debug_level())] if not self.stdio: self.transport_args += ['--external-server'] else: self.transport_args += ['--stdio-server'] self.external_server = True self.transport_unresponsive = False
def get_last_working_dir(self): """Get the path of the last working directory""" return self.editor.get_option('last_working_dir', default=getcwd_or_home())
def import_data(self, filenames=None): """Import data from text file.""" title = _("Import data") if filenames is None: if self.filename is None: basedir = getcwd_or_home() else: basedir = osp.dirname(self.filename) filenames, _selfilter = getopenfilenames(self, title, basedir, iofunctions.load_filters) if not filenames: return elif is_text_string(filenames): filenames = [filenames] for filename in filenames: self.filename = to_text_string(filename) if os.name == "nt": self.filename = remove_backslashes(self.filename) ext = osp.splitext(self.filename)[1].lower() if ext not in iofunctions.load_funcs: buttons = QMessageBox.Yes | QMessageBox.Cancel answer = QMessageBox.question( self, title, _("<b>Unsupported file extension '%s'</b><br><br>" "Would you like to import it anyway " "(by selecting a known file format)?") % ext, buttons) if answer == QMessageBox.Cancel: return formats = list(iofunctions.load_extensions.keys()) item, ok = QInputDialog.getItem(self, title, _('Open file as:'), formats, 0, False) if ok: ext = iofunctions.load_extensions[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.editor.new_value(var_name, clip_data) except Exception as error: error_message = str(error) else: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() error_message = self.shellwidget.load_data(self.filename, ext) QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: QMessageBox.critical( self, title, _("<b>Unable to load '%s'</b>" "<br><br>" "The error message was:<br>%s") % (self.filename, error_message)) self.refresh_table()
def parent_directory(self): """Change working directory to parent one.""" self.chdir(osp.join(getcwd_or_home(), osp.pardir))
def __init__(self, parent, search_text, search_text_regexp, search_path, exclude, exclude_idx, exclude_regexp, supported_encodings, in_python_path, more_options, case_sensitive, external_path_history, options_button=None): QWidget.__init__(self, parent) if search_path is None: search_path = getcwd_or_home() if not isinstance(search_text, (list, tuple)): search_text = [search_text] if not isinstance(search_path, (list, tuple)): search_path = [search_path] if not isinstance(exclude, (list, tuple)): exclude = [exclude] if not isinstance(external_path_history, (list, tuple)): external_path_history = [external_path_history] self.supported_encodings = supported_encodings # Layout 1 hlayout1 = QHBoxLayout() self.search_text = PatternComboBox(self, search_text, _("Search pattern")) self.edit_regexp = create_toolbutton(self, icon=ima.icon('advanced'), tip=_('Regular expression')) self.case_button = create_toolbutton(self, icon=get_icon("upper_lower.png"), tip=_("Case Sensitive")) self.case_button.setCheckable(True) self.case_button.setChecked(case_sensitive) self.edit_regexp.setCheckable(True) self.edit_regexp.setChecked(search_text_regexp) self.more_widgets = () self.more_options = create_toolbutton(self, toggled=self.toggle_more_options) self.more_options.setCheckable(True) self.more_options.setChecked(more_options) self.ok_button = create_toolbutton(self, text=_("Search"), icon=ima.icon('find'), triggered=lambda: self.find.emit(), tip=_("Start search"), text_beside_icon=True) self.ok_button.clicked.connect(self.update_combos) self.stop_button = create_toolbutton(self, text=_("Stop"), icon=ima.icon('editclear'), triggered=lambda: self.stop.emit(), tip=_("Stop search"), text_beside_icon=True) self.stop_button.setEnabled(False) for widget in [self.search_text, self.edit_regexp, self.case_button, self.ok_button, self.stop_button, self.more_options]: hlayout1.addWidget(widget) if options_button: hlayout1.addWidget(options_button) # Layout 2 hlayout2 = QHBoxLayout() self.exclude_pattern = PatternComboBox(self, exclude, _("Excluded filenames pattern")) if exclude_idx is not None and exclude_idx >= 0 \ and exclude_idx < self.exclude_pattern.count(): self.exclude_pattern.setCurrentIndex(exclude_idx) self.exclude_regexp = create_toolbutton(self, icon=ima.icon('advanced'), tip=_('Regular expression')) self.exclude_regexp.setCheckable(True) self.exclude_regexp.setChecked(exclude_regexp) exclude_label = QLabel(_("Exclude:")) exclude_label.setBuddy(self.exclude_pattern) for widget in [exclude_label, self.exclude_pattern, self.exclude_regexp]: hlayout2.addWidget(widget) # Layout 3 hlayout3 = QHBoxLayout() search_on_label = QLabel(_("Search in:")) self.path_selection_combo = SearchInComboBox( external_path_history, parent) hlayout3.addWidget(search_on_label) hlayout3.addWidget(self.path_selection_combo) self.search_text.valid.connect(lambda valid: self.find.emit()) self.exclude_pattern.valid.connect(lambda valid: self.find.emit()) vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.addLayout(hlayout1) vlayout.addLayout(hlayout2) vlayout.addLayout(hlayout3) self.more_widgets = (hlayout2,) self.toggle_more_options(more_options) self.setLayout(vlayout) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
def setup_page(self): about_label = QLabel(_("The following are the default options for " "running files.These options may be overriden " "using the <b>Configuration per file</b> entry " "of the <b>Run</b> menu.")) about_label.setWordWrap(True) interpreter_group = QGroupBox(_("Console")) interpreter_bg = QButtonGroup(interpreter_group) self.current_radio = self.create_radiobutton(CURRENT_INTERPRETER, CURRENT_INTERPRETER_OPTION, True, button_group=interpreter_bg) self.dedicated_radio = self.create_radiobutton(DEDICATED_INTERPRETER, DEDICATED_INTERPRETER_OPTION, False, button_group=interpreter_bg) self.systerm_radio = self.create_radiobutton(SYSTERM_INTERPRETER, SYSTERM_INTERPRETER_OPTION, False, button_group=interpreter_bg) interpreter_layout = QVBoxLayout() interpreter_group.setLayout(interpreter_layout) interpreter_layout.addWidget(self.current_radio) interpreter_layout.addWidget(self.dedicated_radio) interpreter_layout.addWidget(self.systerm_radio) general_group = QGroupBox(_("General settings")) post_mortem = self.create_checkbox(POST_MORTEM, 'post_mortem', False) clear_variables = self.create_checkbox(CLEAR_ALL_VARIABLES, 'clear_namespace', False) console_namespace = self.create_checkbox(CONSOLE_NAMESPACE, 'console_namespace', False) general_layout = QVBoxLayout() general_layout.addWidget(clear_variables) general_layout.addWidget(console_namespace) general_layout.addWidget(post_mortem) general_group.setLayout(general_layout) wdir_group = QGroupBox(_("Working directory settings")) wdir_bg = QButtonGroup(wdir_group) wdir_label = QLabel(_("Default working directory is:")) wdir_label.setWordWrap(True) dirname_radio = self.create_radiobutton( FILE_DIR, WDIR_USE_SCRIPT_DIR_OPTION, True, button_group=wdir_bg) cwd_radio = self.create_radiobutton( CW_DIR, WDIR_USE_CWD_DIR_OPTION, False, button_group=wdir_bg) thisdir_radio = self.create_radiobutton( FIXED_DIR, WDIR_USE_FIXED_DIR_OPTION, False, button_group=wdir_bg) thisdir_bd = self.create_browsedir("", WDIR_FIXED_DIR_OPTION, getcwd_or_home()) thisdir_radio.toggled.connect(thisdir_bd.setEnabled) dirname_radio.toggled.connect(thisdir_bd.setDisabled) cwd_radio.toggled.connect(thisdir_bd.setDisabled) thisdir_layout = QHBoxLayout() thisdir_layout.addWidget(thisdir_radio) thisdir_layout.addWidget(thisdir_bd) wdir_layout = QVBoxLayout() wdir_layout.addWidget(wdir_label) wdir_layout.addWidget(dirname_radio) wdir_layout.addWidget(cwd_radio) wdir_layout.addLayout(thisdir_layout) wdir_group.setLayout(wdir_layout) external_group = QGroupBox(_("External system terminal")) interact_after = self.create_checkbox(INTERACT, 'interact', False) external_layout = QVBoxLayout() external_layout.addWidget(interact_after) external_group.setLayout(external_layout) firstrun_cb = self.create_checkbox( ALWAYS_OPEN_FIRST_RUN % _("Run Settings dialog"), ALWAYS_OPEN_FIRST_RUN_OPTION, False) vlayout = QVBoxLayout() vlayout.addWidget(about_label) vlayout.addSpacing(10) vlayout.addWidget(interpreter_group) vlayout.addWidget(general_group) vlayout.addWidget(wdir_group) vlayout.addWidget(external_group) vlayout.addWidget(firstrun_cb) vlayout.addStretch(1) self.setLayout(vlayout)
def get_last_working_dir(self): """Get the path of the last working directory""" return self.main.editor.get_option('last_working_dir', default=getcwd_or_home())
class PlotsWidget(PluginMainWidget): DEFAULT_OPTIONS = { 'auto_fit_plotting': True, 'mute_inline_plotting': True, 'show_plot_outline': True, 'save_dir': getcwd_or_home() } # Signals sig_option_changed = Signal(str, object) sig_figure_loaded = Signal() """This signal is emitted when a figure is loaded succesfully""" sig_redirect_stdio_requested = Signal(bool) """ This signal is emitted to request the main application to redirect standard output/error when using Open/Save/Browse dialogs within widgets. Parameters ---------- redirect: bool Start redirect (True) or stop redirect (False). """ def __init__(self, name=None, plugin=None, parent=None, options=DEFAULT_OPTIONS): super().__init__(name, plugin, parent, options) # Widgets self._stack = PlotsStackedWidget(parent=self) self._shellwidgets = {} self.zoom_disp = QSpinBox(self) self._right_clicked_thumbnail = None # Widget setup self.zoom_disp.setAlignment(Qt.AlignCenter) self.zoom_disp.setButtonSymbols(QSpinBox.NoButtons) self.zoom_disp.setReadOnly(True) self.zoom_disp.setSuffix(' %') self.zoom_disp.setRange(0, 9999) self.zoom_disp.setValue(100) # Layout layout = QHBoxLayout() layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self._stack) self.setLayout(layout) # Signals self._stack.sig_figure_loaded.connect(self.sig_figure_loaded) self._stack.sig_figure_menu_requested.connect(self.show_figure_menu) self._stack.sig_thumbnail_menu_requested.connect( self.show_thumbnail_menu) self._stack.sig_zoom_changed.connect(self.zoom_disp.setValue) self._stack.sig_figure_loaded.connect(self.update_actions) self._stack.sig_save_dir_changed.connect( lambda val: self.set_option('save_dir', val)) # --- PluginMainWidget API # ------------------------------------------------------------------------ def get_title(self): return _('Plots') def get_focus_widget(self): widget = self.current_widget() if widget and widget.thumbnails_sb.current_thumbnail is not None: if widget.figviewer.figcanvas.fig: widget = widget.thumbnails_sb.scrollarea return widget def setup(self, options): # Menu actions self.mute_action = self.create_action( name=PlotsWidgetActions.ToggleMuteInlinePlotting, text=_("Mute inline plotting"), tip=_("Mute inline plotting in the ipython console."), toggled=lambda val: self.set_option('mute_inline_plotting', val), initial=options['mute_inline_plotting'], ) self.outline_action = self.create_action( name=PlotsWidgetActions.ToggleShowPlotOutline, text=_("Show plot outline"), tip=_("Show the plot outline."), toggled=lambda val: self.set_option('show_plot_outline', val), initial=options['show_plot_outline'], ) self.fit_action = self.create_action( name=PlotsWidgetActions.ToggleAutoFitPlotting, text=_("Fit plots to window"), tip=_("Automatically fit plots to Plot pane size."), toggled=lambda val: self.set_option('auto_fit_plotting', val), initial=options['auto_fit_plotting'], ) # Toolbar actions save_action = self.create_action( name=PlotsWidgetActions.Save, text=_("Save plot as..."), icon=self.create_icon('filesave'), triggered=self.save_plot, register_shortcut=True, ) save_all_action = self.create_action( name=PlotsWidgetActions.SaveAll, text=_("Save all plots..."), icon=self.create_icon('save_all'), triggered=self.save_all_plots, register_shortcut=True, ) copy_action = self.create_action( name=PlotsWidgetActions.Copy, text=_("Copy Image"), icon=self.create_icon('editcopy'), triggered=self.copy_image, register_shortcut=True, ) remove_action = self.create_action( name=PlotsWidgetActions.Close, text=_("Remove plot"), icon=self.create_icon('editclear'), triggered=self.remove_plot, ) remove_all_action = self.create_action( name=PlotsWidgetActions.CloseAll, text=_("Remove all plots"), tip=_("Remove all plots"), icon=self.create_icon('filecloseall'), triggered=self.remove_all_plots, register_shortcut=True, ) previous_action = self.create_action( name=PlotsWidgetActions.MoveToPreviousFigure, text=_("Previous plot"), tip=_("Previous plot"), icon=self.create_icon('ArrowBack'), triggered=self.previous_plot, register_shortcut=True, ) next_action = self.create_action( name=PlotsWidgetActions.MoveToNextFigure, text=_("Next plot"), tip=_("Next plot"), icon=self.create_icon('ArrowForward'), triggered=self.next_plot, register_shortcut=True, ) zoom_in_action = self.create_action( name=PlotsWidgetActions.ZoomIn, text=_("Zoom in"), tip=_("Zoom in"), icon=self.create_icon('zoom_in'), triggered=self.zoom_in, register_shortcut=True, ) zoom_out_action = self.create_action( name=PlotsWidgetActions.ZoomOut, text=_("Zoom out"), tip=_("Zoom out"), icon=self.create_icon('zoom_out'), triggered=self.zoom_out, register_shortcut=True, ) # Options menu options_menu = self.get_options_menu() self.add_item_to_menu(self.mute_action, menu=options_menu) self.add_item_to_menu(self.outline_action, menu=options_menu) self.add_item_to_menu(self.fit_action, menu=options_menu) # Main toolbar main_toolbar = self.get_main_toolbar() for item in [ save_action, save_all_action, copy_action, remove_action, remove_all_action, previous_action, next_action, zoom_in_action, zoom_out_action, self.zoom_disp ]: self.add_item_to_toolbar( item, toolbar=main_toolbar, section=PlotsWidgetMainToolBarSections.Edit, ) # Context menu context_menu = self.create_menu(PluginMainWidgetMenus.Context) for item in [save_action, copy_action, remove_action]: self.add_item_to_menu(item, menu=context_menu) def update_actions(self): value = False widget = self.current_widget() figviewer = None if widget: figviewer = widget.figviewer thumbnails_sb = widget.thumbnails_sb value = figviewer.figcanvas.fig is not None for __, action in self.get_actions().items(): if action and action not in [ self.mute_action, self.outline_action, self.fit_action ]: action.setEnabled(value) # IMPORTANT: Since we are defining the main actions in here # and the context is WidgetWithChildrenShortcut we need to # assign the same actions to the children widgets in order # for shortcuts to work if figviewer: figviewer_actions = figviewer.actions() thumbnails_sb_actions = thumbnails_sb.actions() if action not in figviewer_actions: figviewer.addAction(action) if action not in thumbnails_sb_actions: thumbnails_sb.addAction(action) self.zoom_disp.setEnabled(value) # Disable zoom buttons if autofit if value: value = not self.get_option('auto_fit_plotting') self.get_action(PlotsWidgetActions.ZoomIn).setEnabled(value) self.get_action(PlotsWidgetActions.ZoomOut).setEnabled(value) self.zoom_disp.setEnabled(value) def on_option_update(self, option, value): for index in range(self.count()): widget = self._stack.widget(index) if widget: widget.setup({option: value}) self.update_actions() # --- Public API: # ------------------------------------------------------------------------ def set_current_widget(self, fig_browser): """ Set the current figure browser widget in the stack. Parameters ---------- fig_browser: spyder.plugins.plots.widgets.figurebrowser.FigureBrowser The widget to set. """ self._stack.setCurrentWidget(fig_browser) def current_widget(self): """ Return the current figure browser widget in the stack. Returns ------- spyder.plugins.plots.widgets.figurebrowser.FigureBrowser The current widget. """ return self._stack.currentWidget() def count(self): """ Return the number of widgets in the stack. Returns ------- int The number of widgets in the stack. """ return self._stack.count() def remove_widget(self, fig_browser): """ Remove widget from stack. Parameters ---------- fig_browser: spyder.plugins.plots.widgets.figurebrowser.FigureBrowser The figure browser widget to remove. """ self._stack.removeWidget(fig_browser) def add_widget(self, fig_browser): """ Add widget to stack. Parameters ---------- fig_browser: spyder.plugins.plots.widgets.figurebrowser.FigureBrowser The figure browser widget to add. """ self._stack.addWidget(fig_browser) def add_shellwidget(self, shellwidget): """ Add a new shellwidget registered with the plots plugin. This function registers a new FigureBrowser for browsing the figures in the shell. Parameters ---------- shelwidget: spyder.plugins.ipyconsole.widgets.shell.ShellWidget The shell widget. """ shellwidget_id = id(shellwidget) if shellwidget_id not in self._shellwidgets: fig_browser = FigureBrowser(parent=self._stack, background_color=MAIN_BG_COLOR) fig_browser.set_shellwidget(shellwidget) fig_browser.sig_redirect_stdio_requested.connect( self.sig_redirect_stdio_requested) self.add_widget(fig_browser) self._shellwidgets[shellwidget_id] = fig_browser self.set_shellwidget(shellwidget) return fig_browser def remove_shellwidget(self, shellwidget): """ Remove the shellwidget registered with the plots plugin. Parameters ---------- shelwidget: spyder.plugins.ipyconsole.widgets.shell.ShellWidget The shell widget. """ shellwidget_id = id(shellwidget) if shellwidget_id in self._shellwidgets: fig_browser = self._shellwidgets.pop(shellwidget_id) self.remove_widget(fig_browser) fig_browser.close() def set_shellwidget(self, shellwidget): """ Update the current shellwidget displayed with the plots plugin. Parameters ---------- shelwidget: spyder.plugins.ipyconsole.widgets.shell.ShellWidget The shell widget. """ shellwidget_id = id(shellwidget) if shellwidget_id in self._shellwidgets: fig_browser = self._shellwidgets[shellwidget_id] fig_browser.setup(self._options) self.set_current_widget(fig_browser) def show_figure_menu(self, qpoint): """ Show main figure menu and display on given `qpoint`. Parameters ---------- qpoint: QPoint The point to display the menu in global coordinated. """ self._right_clicked_thumbnail = None widget = self.current_widget() if widget: self.get_menu(PluginMainWidgetMenus.Context).popup(qpoint) def show_thumbnail_menu(self, qpoint, thumbnail): """ Show menu on a given `thumbnail` and display on given `qpoint`. Parameters ---------- qpoint: QPoint The point to display the menu in global coordinated. """ self._right_clicked_thumbnail = thumbnail widget = self.current_widget() if widget: self.get_menu(PluginMainWidgetMenus.Context).popup(qpoint) def save_plot(self): """ Save currently active plot or plot selected to be saved with context menu in the thumbnails scrollbar. """ widget = self.current_widget() if widget: if self._right_clicked_thumbnail is None: widget.thumbnails_sb.save_current_figure_as() else: widget.thumbnails_sb.save_thumbnail_figure_as( self._right_clicked_thumbnail) # Reset the toolbar buttons to use the figviewer and not the thumbnail # selection self._right_clicked_thumbnail = None def save_all_plots(self): """Save all available plots.""" widget = self.current_widget() if widget: widget.thumbnails_sb.save_all_figures_as() def copy_image(self): """ Copy currently active plot or plot selected to be copied with context menu in the thumbnails scrollbar into the clipboard. """ widget = self.current_widget() if widget and widget.figviewer and widget.figviewer.figcanvas.fig: if self._right_clicked_thumbnail is None: widget.figviewer.figcanvas.copy_figure() else: self._right_clicked_thumbnail.canvas.copy_figure() # Reset the toolbar buttons to use the figviewer and not the thumbnail # selection self._right_clicked_thumbnail = None def remove_plot(self): """ Remove currently active plot or plot selected to be removed with context menu in the thumbnails scrollbar. """ widget = self.current_widget() if widget: if self._right_clicked_thumbnail is None: widget.thumbnails_sb.remove_current_thumbnail() else: widget.thumbnails_sb.remove_thumbnail( self._right_clicked_thumbnail) # Reset the toolbar buttons to use the figviewer and not the thumbnail # selection self._right_clicked_thumbnail = None self.update_actions() def remove_all_plots(self): """Remove all available plots..""" widget = self.current_widget() if widget: widget.thumbnails_sb.remove_all_thumbnails() self.update_actions() def previous_plot(self): """Select the previous plot in the thumbnails scrollbar.""" widget = self.current_widget() if widget: widget.thumbnails_sb.go_previous_thumbnail() def next_plot(self): """Select the next plot in the thumbnails scrollbar.""" widget = self.current_widget() if widget: widget.thumbnails_sb.go_next_thumbnail() def zoom_in(self): """Perform a zoom in on the main figure.""" widget = self.current_widget() if widget: widget.zoom_in() def zoom_out(self): """Perform a zoom out on the main figure.""" widget = self.current_widget() if widget: widget.zoom_out()
def refresh_search_directory(self): """ Refresh search directory. """ self.get_widget().set_directory(getcwd_or_home())
def __init__(self, parent, path=None, read_only_path=None, not_active_path=None, sync=True): """Path manager dialog.""" super(PathManager, self).__init__(parent) assert isinstance(path, (tuple, type(None))) self.path = path or () self.read_only_path = read_only_path or () self.not_active_path = not_active_path or () self.last_path = getcwd_or_home() self.original_path_dict = None # Widgets self.add_button = None self.remove_button = None self.movetop_button = None self.moveup_button = None self.movedown_button = None self.movebottom_button = None self.import_button = None self.export_button = None self.selection_widgets = [] self.top_toolbar_widgets = self._setup_top_toolbar() self.bottom_toolbar_widgets = self._setup_bottom_toolbar() self.listwidget = QListWidget(self) self.bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_ok = self.bbox.button(QDialogButtonBox.Ok) # Widget setup # 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.setWindowTitle(_("PYTHONPATH manager")) self.setWindowIcon(ima.icon('pythonpath')) self.resize(500, 400) self.import_button.setVisible(sync) self.export_button.setVisible(os.name == 'nt' and sync) # Layouts description = QLabel( _("The paths listed below will be passed to IPython consoles and " "the language server as additional locations to search for " "Python modules.<br><br>" "Any paths in your system <tt>PYTHONPATH</tt> environment " "variable can be imported here if you'd like to use them.")) description.setWordWrap(True) top_layout = QHBoxLayout() self._add_widgets_to_layout(self.top_toolbar_widgets, top_layout) bottom_layout = QHBoxLayout() self._add_widgets_to_layout(self.bottom_toolbar_widgets, bottom_layout) bottom_layout.addWidget(self.bbox) layout = QVBoxLayout() layout.addWidget(description) layout.addLayout(top_layout) layout.addWidget(self.listwidget) layout.addLayout(bottom_layout) self.setLayout(layout) # Signals self.listwidget.currentRowChanged.connect(lambda x: self.refresh()) self.listwidget.itemChanged.connect(lambda x: self.refresh()) self.bbox.accepted.connect(self.accept) self.bbox.rejected.connect(self.reject) # Setup self.setup()