Example #1
0
    def setup_page(self):
        newcb = self.create_checkbox

        # --- Workspace
        interface_group = QGroupBox(_("Interface"))
        restore_data_box = newcb(_("Restore data on startup"),
                                 'restore_data_on_startup')
        save_data_box = newcb(_("Save data on exit"),
                              'save_data_on_exit')
        save_history_box = newcb(_("Save history"),
                                 'save_history')
        save_non_project_box = newcb(_("Save non project files opened"),
                                     'save_non_project_files')

        interface_layout = QVBoxLayout()
        interface_layout.addWidget(restore_data_box)
        interface_layout.addWidget(save_data_box)
        interface_layout.addWidget(save_history_box)
        interface_layout.addWidget(save_non_project_box)
        interface_group.setLayout(interface_layout)

        vlayout = QVBoxLayout()
        vlayout.addWidget(interface_group)
        vlayout.addStretch(1)
        self.setLayout(vlayout)
Example #2
0
 def setup(self):
     iofuncs = self.get_internal_funcs()+self.get_3rd_party_funcs()
     load_extensions = {}
     save_extensions = {}
     load_funcs = {}
     save_funcs = {}
     load_filters = []
     save_filters = []
     load_ext = []
     for ext, name, loadfunc, savefunc in iofuncs:
         filter_str = to_text_string(name + " (*%s)" % ext)
         if loadfunc is not None:
             load_filters.append(filter_str)
             load_extensions[filter_str] = ext
             load_funcs[ext] = loadfunc
             load_ext.append(ext)
         if savefunc is not None:
             save_extensions[filter_str] = ext
             save_filters.append(filter_str)
             save_funcs[ext] = savefunc
     load_filters.insert(0, to_text_string(_("Supported files")+" (*"+\
                                           " *".join(load_ext)+")"))
     load_filters.append(to_text_string(_("All files (*.*)")))
     self.load_filters = "\n".join(load_filters)
     self.save_filters = "\n".join(save_filters)
     self.load_funcs = load_funcs
     self.save_funcs = save_funcs
     self.load_extensions = load_extensions
     self.save_extensions = save_extensions
Example #3
0
    def append_result(self, results, num_matches):
        """Real-time update of search results"""
        filename, lineno, colno, match_end, line = results

        if filename not in self.files:
            file_item = FileMatchItem(self, filename, self.sorting)
            file_item.setExpanded(True)
            self.files[filename] = file_item
            self.num_files += 1

        search_text = self.search_text
        title = "'%s' - " % search_text
        nb_files = self.num_files
        if nb_files == 0:
            text = _('String not found')
        else:
            text_matches = _('matches in')
            text_files = _('file')
            if nb_files > 1:
                text_files += 's'
            text = "%d %s %d %s" % (num_matches, text_matches,
                                    nb_files, text_files)
        self.set_title(title + text)

        file_item = self.files[filename]
        line = self.truncate_result(line, colno, match_end)
        item = LineMatchItem(file_item, lineno, colno, line)
        self.data[id(item)] = (filename, lineno, colno)
Example #4
0
    def get_options_menu(self):
        """Return options menu"""
        env_action = create_action(
                        self,
                        _("Show environment variables"),
                        icon=ima.icon('environ'),
                        triggered=self.shellwidget.get_env
                     )

        syspath_action = create_action(
                            self,
                            _("Show sys.path contents"),
                            icon=ima.icon('syspath'),
                            triggered=self.shellwidget.get_syspath
                         )

        self.show_time_action.setChecked(self.show_elapsed_time)
        additional_actions = [MENU_SEPARATOR,
                              env_action,
                              syspath_action,
                              self.show_time_action]

        if self.menu_actions is not None:
            console_menu = self.menu_actions + additional_actions
            return console_menu

        else:
            return additional_actions
Example #5
0
 def set_label_path(self, path, folder=False):
     text = truncate_path(path)
     if not folder:
         status_str = _(u' Scanning: {0}').format(text)
     else:
         status_str = _(u' Searching for files in folder: {0}').format(text)
     self.status_text.setText(status_str)
Example #6
0
 def add_actions_to_context_menu(self, menu):
     """Add actions to IPython widget context menu"""
     inspect_action = create_action(self, _("Inspect current object"),
                                 QKeySequence(get_shortcut('console',
                                                 'inspect current object')),
                                 icon=ima.icon('MessageBoxInformation'),
                                 triggered=self.inspect_object)
     clear_line_action = create_action(self, _("Clear line or block"),
                                       QKeySequence("Shift+Escape"),
                                       icon=ima.icon('editdelete'),
                                       triggered=self.clear_line)
     reset_namespace_action = create_action(self, _("Reset namespace"),
                                       QKeySequence("Ctrl+Alt+R"),
                                       triggered=self.reset_namespace)
     clear_console_action = create_action(self, _("Clear console"),
                                          QKeySequence(get_shortcut('console',
                                                            'clear shell')),
                                          icon=ima.icon('editclear'),
                                          triggered=self.clear_console)
     quit_action = create_action(self, _("&Quit"), icon=ima.icon('exit'),
                                 triggered=self.exit_callback)
     add_actions(menu, (None, inspect_action, clear_line_action,
                        clear_console_action, reset_namespace_action,
                        None, quit_action))
     return menu
Example #7
0
    def restart_kernel(self):
        """
        Restart the associanted kernel

        Took this code from the qtconsole project
        Licensed under the BSD license
        """
        message = _('Are you sure you want to restart the kernel?')
        buttons = QMessageBox.Yes | QMessageBox.No
        result = QMessageBox.question(self, _('Restart kernel?'),
                                      message, buttons)
        if result == QMessageBox.Yes:
            sw = self.shellwidget
            if sw.kernel_manager:
                try:
                    sw.kernel_manager.restart_kernel()
                except RuntimeError as e:
                    sw._append_plain_text(
                        _('Error restarting kernel: %s\n') % e,
                        before_prompt=True
                    )
                else:
                    sw._append_html(_("<br>Restarting kernel...\n<hr><br>"),
                        before_prompt=True,
                    )
            else:
                sw._append_plain_text(
                    _('Cannot restart a kernel not started by Spyder\n'),
                    before_prompt=True
                )
Example #8
0
    def get_options_menu(self):
        """Return options menu"""
        reset_action = create_action(self, _("Remove all variables"),
                                     icon=ima.icon('editdelete'),
                                     triggered=self.reset_namespace)

        self.show_time_action = create_action(self, _("Show elapsed time"),
                                         toggled=self.set_elapsed_time_visible)

        env_action = create_action(
                        self,
                        _("Show environment variables"),
                        icon=ima.icon('environ'),
                        triggered=self.shellwidget.get_env
                     )

        syspath_action = create_action(
                            self,
                            _("Show sys.path contents"),
                            icon=ima.icon('syspath'),
                            triggered=self.shellwidget.get_syspath
                         )

        self.show_time_action.setChecked(self.show_elapsed_time)
        additional_actions = [reset_action,
                              MENU_SEPARATOR,
                              env_action,
                              syspath_action,
                              self.show_time_action]

        if self.menu_actions is not None:
            return self.menu_actions + additional_actions
        else:
            return additional_actions
Example #9
0
    def get_toolbar_buttons(self):
        """Return toolbar buttons list"""
        buttons = []
        # Code to add the stop button
        if self.stop_button is None:
            self.stop_button = create_toolbutton(self, text=_("Stop"),
                                             icon=self.stop_icon,
                                             tip=_("Stop the current command"))
            self.disable_stop_button()
            # set click event handler
            self.stop_button.clicked.connect(self.stop_button_click_handler)
        if self.stop_button is not None:
            buttons.append(self.stop_button)

        if self.options_button is None:
            options = self.get_options_menu()
            if options:
                self.options_button = create_toolbutton(self,
                        text=_('Options'), icon=ima.icon('tooloptions'))
                self.options_button.setPopupMode(QToolButton.InstantPopup)
                menu = QMenu(self)
                add_actions(menu, options)
                self.options_button.setMenu(menu)
        if self.options_button is not None:
            buttons.append(self.options_button)

        return buttons
Example #10
0
 def synchronize(self):
     """
     Synchronize Spyder's path list with PYTHONPATH environment variable
     Only apply to: current user, on Windows platforms
     """
     answer = QMessageBox.question(self, _("Synchronize"),
         _("This will synchronize Spyder's path list with "
                 "<b>PYTHONPATH</b> environment variable for current user, "
                 "allowing you to run your Python modules outside Spyder "
                 "without having to configure sys.path. "
                 "<br>Do you want to clear contents of PYTHONPATH before "
                 "adding Spyder's path list?"),
         QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
     if answer == QMessageBox.Cancel:
         return
     elif answer == QMessageBox.Yes:
         remove = True
     else:
         remove = False
     from spyder.utils.environ import (get_user_env, set_user_env,
                                       listdict2envdict)
     env = get_user_env()
     if remove:
         ppath = self.active_pathlist+self.ro_pathlist
     else:
         ppath = env.get('PYTHONPATH', [])
         if not isinstance(ppath, list):
             ppath = [ppath]
         ppath = [path for path in ppath
                  if path not in (self.active_pathlist+self.ro_pathlist)]
         ppath.extend(self.active_pathlist+self.ro_pathlist)
     env['PYTHONPATH'] = ppath
     set_user_env(listdict2envdict(env), parent=self)
Example #11
0
 def setup_top_toolbar(self, layout):
     toolbar = []
     movetop_button = create_toolbutton(self,
                                 text=_("Move to top"),
                                 icon=ima.icon('2uparrow'),
                                 triggered=lambda: self.move_to(absolute=0),
                                 text_beside_icon=True)
     toolbar.append(movetop_button)
     moveup_button = create_toolbutton(self,
                                 text=_("Move up"),
                                 icon=ima.icon('1uparrow'),
                                 triggered=lambda: self.move_to(relative=-1),
                                 text_beside_icon=True)
     toolbar.append(moveup_button)
     movedown_button = create_toolbutton(self,
                                 text=_("Move down"),
                                 icon=ima.icon('1downarrow'),
                                 triggered=lambda: self.move_to(relative=1),
                                 text_beside_icon=True)
     toolbar.append(movedown_button)
     movebottom_button = create_toolbutton(self,
                                 text=_("Move to bottom"),
                                 icon=ima.icon('2downarrow'),
                                 triggered=lambda: self.move_to(absolute=1),
                                 text_beside_icon=True)
     toolbar.append(movebottom_button)
     self.selection_widgets.extend(toolbar)
     self._add_widgets_to_layout(layout, toolbar)
     return toolbar
Example #12
0
 def change_history_depth(self):
     "Change history max entries" ""
     depth, valid = QInputDialog.getInt(
         self, _("History"), _("Maximum entries"), self.get_option("max_entries"), 10, 10000
     )
     if valid:
         self.set_option("max_entries", depth)
Example #13
0
 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)
Example #14
0
    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)
Example #15
0
 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,
                                            img_path=self.img_path,
                                            css_path=self.css_path)
                 html_text = sphinxify(doc['docstring'], context)
                 if doc['docstring'] == '':
                     if any([doc['name'], doc['argspec'], doc['note']]):
                         msg = _("No further documentation available")
                         html_text += '<div class="hr"></div>'
                     else:
                         msg = _("No documentation available")
                     html_text += '<div id="doc-warning">%s</div>' % msg
             except Exception as error:
                 self.error_msg.emit(to_text_string(error))
                 return
         elif self.context is not None:
             try:
                 html_text = sphinxify(doc, self.context)
             except Exception as error:
                 self.error_msg.emit(to_text_string(error))
                 return
     self.html_ready.emit(html_text)
Example #16
0
 def __init__(self, value, parent=None):
     QGridLayout.__init__(self)
     font = tuple_to_qfont(value)
     assert font is not None
     
     # Font family
     self.family = QFontComboBox(parent)
     self.family.setCurrentFont(font)
     self.addWidget(self.family, 0, 0, 1, -1)
     
     # Font size
     self.size = QComboBox(parent)
     self.size.setEditable(True)
     sizelist = list(range(6, 12)) + list(range(12, 30, 2)) + [36, 48, 72]
     size = font.pointSize()
     if size not in sizelist:
         sizelist.append(size)
         sizelist.sort()
     self.size.addItems([str(s) for s in sizelist])
     self.size.setCurrentIndex(sizelist.index(size))
     self.addWidget(self.size, 1, 0)
     
     # Italic or not
     self.italic = QCheckBox(_("Italic"), parent)
     self.italic.setChecked(font.italic())
     self.addWidget(self.italic, 1, 1)
     
     # Bold or not
     self.bold = QCheckBox(_("Bold"), parent)
     self.bold.setChecked(font.bold())
     self.addWidget(self.bold, 1, 2)
Example #17
0
    def setup(self, fname):
        """Setup Run Configuration dialog with filename *fname*"""
        combo_label = QLabel(_("Select a run configuration:"))
        self.combo = QComboBox()
        self.combo.setMaxVisibleItems(20)
        self.combo.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength)
        self.combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        
        self.stack = QStackedWidget()

        configurations = _get_run_configurations()
        for index, (filename, options) in enumerate(configurations):
            if fname == filename:
                break
        else:
            # There is no run configuration for script *fname*:
            # creating a temporary configuration that will be kept only if
            # dialog changes are accepted by the user
            configurations.insert(0, (fname, RunConfiguration(fname).get()))
            index = 0
        for filename, options in configurations:
            widget = RunConfigOptions(self)
            widget.set(options)
            self.combo.addItem(filename)
            self.stack.addWidget(widget)
        self.combo.currentIndexChanged.connect(self.stack.setCurrentIndex)
        self.combo.setCurrentIndex(index)

        self.add_widgets(combo_label, self.combo, 10, self.stack)
        self.add_button_box(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)

        self.setWindowTitle(_("Run configuration per file"))
Example #18
0
 def create_new_folder(self, current_path, title, subtitle, is_package):
     """Create new folder"""
     if current_path is None:
         current_path = ''
     if osp.isfile(current_path):
         current_path = osp.dirname(current_path)
     name, valid = QInputDialog.getText(self, title, subtitle,
                                        QLineEdit.Normal, "")
     if valid:
         dirname = osp.join(current_path, to_text_string(name))
         try:
             os.mkdir(dirname)
         except EnvironmentError as error:
             QMessageBox.critical(self, title,
                                  _("<b>Unable "
                                    "to create folder <i>%s</i></b>"
                                    "<br><br>Error message:<br>%s"
                                    ) % (dirname, to_text_string(error)))
         finally:
             if is_package:
                 fname = osp.join(dirname, '__init__.py')
                 try:
                     with open(fname, 'wb') as f:
                         f.write(to_binary_string('#'))
                     return dirname
                 except EnvironmentError as error:
                     QMessageBox.critical(self, title,
                                          _("<b>Unable "
                                            "to create file <i>%s</i></b>"
                                            "<br><br>Error message:<br>%s"
                                            ) % (fname,
                                                 to_text_string(error)))
Example #19
0
    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)
Example #20
0
 def create_context_menu_actions(self):
     """Create context menu actions"""
     actions = []
     fnames = self.get_selected_filenames()
     new_actions = self.create_file_new_actions(fnames)
     if len(new_actions) > 1:
         # Creating a submenu only if there is more than one entry
         new_act_menu = QMenu(_('New'), self)
         add_actions(new_act_menu, new_actions)
         actions.append(new_act_menu)
     else:
         actions += new_actions
     import_actions = self.create_file_import_actions(fnames)
     if len(import_actions) > 1:
         # Creating a submenu only if there is more than one entry
         import_act_menu = QMenu(_('Import'), self)
         add_actions(import_act_menu, import_actions)
         actions.append(import_act_menu)
     else:
         actions += import_actions
     if actions:
         actions.append(None)
     if fnames:
         actions += self.create_file_manage_actions(fnames)
     if actions:
         actions.append(None)
     if fnames and all([osp.isdir(_fn) for _fn in fnames]):
         actions += self.create_folder_manage_actions(fnames)
     if actions:
         actions.append(None)
     actions += self.common_actions
     return actions
Example #21
0
 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.removed.emit(fname)
         else:
             self.remove_tree(fname)
             self.parent_widget.removed_tree.emit(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
Example #22
0
    def __init__(self, parent):
        QWidget.__init__(self, parent)

        vert_layout = QVBoxLayout()

        # Type frame
        type_layout = QHBoxLayout()
        type_label = QLabel(_("Import as"))
        type_layout.addWidget(type_label)

        self.array_btn = array_btn = QRadioButton(_("array"))
        array_btn.setEnabled(ndarray is not FakeObject)
        array_btn.setChecked(ndarray is not FakeObject)
        type_layout.addWidget(array_btn)

        list_btn = QRadioButton(_("list"))
        list_btn.setChecked(not array_btn.isChecked())
        type_layout.addWidget(list_btn)

        if pd:
            self.df_btn = df_btn = QRadioButton(_("DataFrame"))
            df_btn.setChecked(False)
            type_layout.addWidget(df_btn)

        h_spacer = QSpacerItem(40, 20,
                               QSizePolicy.Expanding, QSizePolicy.Minimum)
        type_layout.addItem(h_spacer)
        type_frame = QFrame()
        type_frame.setLayout(type_layout)

        self._table_view = PreviewTable(self)
        vert_layout.addWidget(type_frame)
        vert_layout.addWidget(self._table_view)
        self.setLayout(vert_layout)
Example #23
0
    def create_file_combobox(self, text, choices, option, default=NoDefault,
                             tip=None, restart=False, filters=None,
                             adjust_to_contents=False,
                             default_line_edit=False):
        """choices: couples (name, key)"""
        combobox = FileComboBox(self, adjust_to_contents=adjust_to_contents,
                                default_line_edit=default_line_edit)
        combobox.restart_required = restart
        combobox.label_text = text
        edit = combobox.lineEdit()
        edit.label_text = text
        edit.restart_required = restart
        self.lineedits[edit] = (option, default)

        if tip is not None:
            combobox.setToolTip(tip)
        combobox.addItems(choices)

        msg = _('Invalid file path')
        self.validate_data[edit] = (osp.isfile, msg)
        browse_btn = QPushButton(ima.icon('FileIcon'), '', self)
        browse_btn.setToolTip(_("Select file"))
        browse_btn.clicked.connect(lambda: self.select_file(edit, filters))

        layout = QGridLayout()
        layout.addWidget(combobox, 0, 0, 0, 9)
        layout.addWidget(browse_btn, 0, 10)
        layout.setContentsMargins(0, 0, 0, 0)
        widget = QWidget(self)
        widget.combobox = combobox
        widget.browse_btn = browse_btn
        widget.setLayout(layout)

        return widget
Example #24
0
 def get_toolbar_buttons(self):
     if self.run_button is None:
         self.run_button = create_toolbutton(self, text=_("Run"),
                                          icon=ima.icon('run'),
                                          tip=_("Run again this program"),
                                          triggered=self.start_shell)
     if self.kill_button is None:
         self.kill_button = create_toolbutton(self, text=_("Kill"),
                                  icon=ima.icon('kill'),
                                  tip=_("Kills the current process, "
                                        "causing it to exit immediately"))
     buttons = [self.run_button]
     if self.options_button is None:
         options = self.get_options_menu()
         if options:
             self.options_button = create_toolbutton(self, text=_('Options'),
                                         icon=ima.icon('tooloptions'))
             self.options_button.setPopupMode(QToolButton.InstantPopup)
             menu = QMenu(self)
             add_actions(menu, options)
             self.options_button.setMenu(menu)
     if self.options_button is not None:
         buttons.append(self.options_button)
     buttons.append(self.kill_button)
     return buttons
Example #25
0
 def create_scedit(self, text, option, default=NoDefault, tip=None,
                   without_layout=False):
     label = QLabel(text)
     clayout = ColorLayout(QColor(Qt.black), self)
     clayout.lineedit.setMaximumWidth(80)
     if tip is not None:
         clayout.setToolTip(tip)
     cb_bold = QCheckBox()
     cb_bold.setIcon(ima.icon('bold'))
     cb_bold.setToolTip(_("Bold"))
     cb_italic = QCheckBox()
     cb_italic.setIcon(ima.icon('italic'))
     cb_italic.setToolTip(_("Italic"))
     self.scedits[(clayout, cb_bold, cb_italic)] = (option, default)
     if without_layout:
         return label, clayout, cb_bold, cb_italic
     layout = QHBoxLayout()
     layout.addWidget(label)
     layout.addLayout(clayout)
     layout.addSpacing(10)
     layout.addWidget(cb_bold)
     layout.addWidget(cb_italic)
     layout.addStretch(1)
     layout.setContentsMargins(0, 0, 0, 0)
     widget = QWidget(self)
     widget.setLayout(layout)
     return widget
Example #26
0
 def _sel_to_text(self, cell_range):
     """Copy an array portion to a unicode string"""
     if not cell_range:
         return
     row_min, row_max, col_min, col_max = get_idx_rect(cell_range)
     if col_min == 0 and col_max == (self.model().cols_loaded-1):
         # we've selected a whole column. It isn't possible to
         # select only the first part of a column without loading more, 
         # so we can treat it as intentional and copy the whole thing
         col_max = self.model().total_cols-1
     if row_min == 0 and row_max == (self.model().rows_loaded-1):
         row_max = self.model().total_rows-1
     
     _data = self.model().get_data()
     if PY3:
         output = io.BytesIO()
     else:
         output = io.StringIO()
     try:
         np.savetxt(output, _data[row_min:row_max+1, col_min:col_max+1],
                    delimiter='\t', fmt=self.model().get_format())
     except:
         QMessageBox.warning(self, _("Warning"),
                             _("It was not possible to copy values for "
                               "this array"))
         return
     contents = output.getvalue().decode('utf-8')
     output.close()
     return contents
Example #27
0
 def set_user_env(reg, parent=None):
     """Set HKCU (current user) environment variables"""
     reg = listdict2envdict(reg)
     types = dict()
     key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Environment")
     for name in reg:
         try:
             _x, types[name] = winreg.QueryValueEx(key, name)
         except WindowsError:
             types[name] = winreg.REG_EXPAND_SZ
     key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Environment", 0,
                          winreg.KEY_SET_VALUE)
     for name in reg:
         winreg.SetValueEx(key, name, 0, types[name], reg[name])
     try:
         from win32gui import SendMessageTimeout
         from win32con import (HWND_BROADCAST, WM_SETTINGCHANGE,
                               SMTO_ABORTIFHUNG)
         SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
                            "Environment", SMTO_ABORTIFHUNG, 5000)
     except ImportError:
         QMessageBox.warning(parent, _("Warning"),
                     _("Module <b>pywin32 was not found</b>.<br>"
                       "Please restart this Windows <i>session</i> "
                       "(not the computer) for changes to take effect."))
Example #28
0
    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()
Example #29
0
    def setup_page(self):
        # Widgets
        self.table = ShortcutsTable(self)
        self.finder = ShortcutFinder(self.table, self.table.set_regex)
        self.table.finder = self.finder
        self.label_finder = QLabel(_('Search: '))
        self.reset_btn = QPushButton(_("Reset to default values"))

        # Layout
        hlayout = QHBoxLayout()
        vlayout = QVBoxLayout()
        hlayout.addWidget(self.label_finder)
        hlayout.addWidget(self.finder)
        vlayout.addWidget(self.table)
        vlayout.addLayout(hlayout)
        vlayout.addWidget(self.reset_btn)
        self.setLayout(vlayout)

        self.setTabOrder(self.table, self.finder)
        self.setTabOrder(self.finder, self.reset_btn)

        # Signals and slots
        if PYQT5:
            # Qt5 'dataChanged' has 3 parameters
            self.table.proxy_model.dataChanged.connect(
                lambda i1, i2, roles, opt='': self.has_been_modified(opt))
        else:
            self.table.proxy_model.dataChanged.connect(
                lambda i1, i2, opt='': self.has_been_modified(opt))
        self.reset_btn.clicked.connect(self.reset_to_default)
Example #30
0
 def _set_step(self, step):
     """Proceed to a given step"""
     new_tab = self.tab_widget.currentIndex() + step
     assert new_tab < self.tab_widget.count() and new_tab >= 0
     if new_tab == self.tab_widget.count()-1:
         try:
             self.table_widget.open_data(self._get_plain_text(),
                                     self.text_widget.get_col_sep(),
                                     self.text_widget.get_row_sep(),
                                     self.text_widget.trnsp_box.isChecked(),
                                     self.text_widget.get_skiprows(),
                                     self.text_widget.get_comments())
             self.done_btn.setEnabled(True)
             self.done_btn.setDefault(True)
             self.fwd_btn.setEnabled(False)
             self.back_btn.setEnabled(True)
         except (SyntaxError, AssertionError) as error:
             QMessageBox.critical(self, _("Import wizard"),
                         _("<b>Unable to proceed to next step</b>"
                           "<br><br>Please check your entries."
                           "<br><br>Error message:<br>%s") % str(error))
             return
     elif new_tab == 0:
         self.done_btn.setEnabled(False)
         self.fwd_btn.setEnabled(True)
         self.back_btn.setEnabled(False)
     self._focus_tab(new_tab)
Example #31
0
 def get_plugin_title(self):
     """Return widget title"""
     return _('Current working directory')
Example #32
0
# Local imports
from spyder.config.base import get_supported_types
from spyder.py3compat import (NUMERIC_TYPES, TEXT_TYPES, to_text_string,
                              is_text_string, is_binary_string, reprlib,
                              PY2, to_binary_string)
from spyder.utils import programs
from spyder import dependencies
from spyder.config.base import _


#==============================================================================
# Dependencies
#==============================================================================
PANDAS_REQVER = '>=0.13.1'
dependencies.add('pandas',  _("View and edit DataFrames and Series in the "
                              "Variable Explorer"),
                 required_version=PANDAS_REQVER, optional=True)

NUMPY_REQVER = '>=1.7'
dependencies.add("numpy", _("View and edit two and three dimensional arrays "
                            "in the Variable Explorer"),
                 required_version=NUMPY_REQVER, optional=True)

#==============================================================================
# FakeObject
#==============================================================================
class FakeObject(object):
    """Fake class used in replacement of missing modules"""
    pass

Example #33
0
    def __init__(self, parent, enable_replace=False):
        QWidget.__init__(self, parent)
        self.enable_replace = enable_replace
        self.editor = None
        self.is_code_editor = None

        glayout = QGridLayout()
        glayout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(glayout)

        self.close_button = create_toolbutton(
            self, triggered=self.hide, icon=ima.icon('DialogCloseButton'))
        glayout.addWidget(self.close_button, 0, 0)

        # Find layout
        self.search_text = PatternComboBox(self,
                                           tip=_("Search string"),
                                           adjust_to_minimum=False)
        self.search_text.valid.connect(lambda state: self.find(
            changed=False, forward=True, rehighlight=False))
        self.search_text.lineEdit().textEdited.connect(
            self.text_has_been_edited)

        self.previous_button = create_toolbutton(self,
                                                 triggered=self.find_previous,
                                                 icon=ima.icon('ArrowUp'))
        self.next_button = create_toolbutton(self,
                                             triggered=self.find_next,
                                             icon=ima.icon('ArrowDown'))
        self.next_button.clicked.connect(self.update_search_combo)
        self.previous_button.clicked.connect(self.update_search_combo)

        self.re_button = create_toolbutton(self,
                                           icon=ima.icon('advanced'),
                                           tip=_("Regular expression"))
        self.re_button.setCheckable(True)
        self.re_button.toggled.connect(lambda state: self.find())

        self.case_button = create_toolbutton(self,
                                             icon=get_icon("upper_lower.png"),
                                             tip=_("Case Sensitive"))
        self.case_button.setCheckable(True)
        self.case_button.toggled.connect(lambda state: self.find())

        self.words_button = create_toolbutton(self,
                                              icon=get_icon("whole_words.png"),
                                              tip=_("Whole words"))
        self.words_button.setCheckable(True)
        self.words_button.toggled.connect(lambda state: self.find())

        self.highlight_button = create_toolbutton(
            self, icon=get_icon("highlight.png"), tip=_("Highlight matches"))
        self.highlight_button.setCheckable(True)
        self.highlight_button.toggled.connect(self.toggle_highlighting)

        hlayout = QHBoxLayout()
        self.widgets = [
            self.close_button, self.search_text, self.previous_button,
            self.next_button, self.re_button, self.case_button,
            self.words_button, self.highlight_button
        ]
        for widget in self.widgets[1:]:
            hlayout.addWidget(widget)
        glayout.addLayout(hlayout, 0, 1)

        # Replace layout
        replace_with = QLabel(_("Replace with:"))
        self.replace_text = PatternComboBox(self,
                                            adjust_to_minimum=False,
                                            tip=_('Replace string'))

        self.replace_button = create_toolbutton(
            self,
            text=_('Replace/find'),
            icon=ima.icon('DialogApplyButton'),
            triggered=self.replace_find,
            text_beside_icon=True)
        self.replace_button.clicked.connect(self.update_replace_combo)
        self.replace_button.clicked.connect(self.update_search_combo)

        self.all_check = QCheckBox(_("Replace all"))

        self.replace_layout = QHBoxLayout()
        widgets = [
            replace_with, self.replace_text, self.replace_button,
            self.all_check
        ]
        for widget in widgets:
            self.replace_layout.addWidget(widget)
        glayout.addLayout(self.replace_layout, 1, 1)
        self.widgets.extend(widgets)
        self.replace_widgets = widgets
        self.hide_replace()

        self.search_text.setTabOrder(self.search_text, self.replace_text)

        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        self.shortcuts = self.create_shortcuts(parent)

        self.highlight_timer = QTimer(self)
        self.highlight_timer.setSingleShot(True)
        self.highlight_timer.setInterval(1000)
        self.highlight_timer.timeout.connect(self.highlight_matches)
Example #34
0
    def setup(self):
        """Performs the setup of plugin's menu and actions."""
        # Toolbar buttons
        toolbar = self.get_main_toolbar()
        fromcursor_btn = self.create_toolbutton(
            OutlineExplorerToolbuttons.GoToCursor,
            icon=self.create_icon('fromcursor'),
            tip=_('Go to cursor position'),
            triggered=self.treewidget.go_to_cursor_position)

        for item in [fromcursor_btn,
                     self.treewidget.collapse_all_action,
                     self.treewidget.expand_all_action,
                     self.treewidget.restore_action,
                     self.treewidget.collapse_selection_action,
                     self.treewidget.expand_selection_action]:
            self.add_item_to_toolbar(item, toolbar=toolbar,
                                     section=OutlineExplorerSections.Main)

        # Actions
        fromcursor_act = self.create_action(
            OutlineExplorerActions.GoToCursor,
            text=_('Go to cursor position'),
            icon=self.create_icon('fromcursor'),
            triggered=self.treewidget.go_to_cursor_position)

        fullpath_act = self.create_action(
            OutlineExplorerActions.ShowFullPath,
            text=_('Show absolute path'),
            toggled=True,
            option='show_fullpath')

        allfiles_act = self.create_action(
            OutlineExplorerActions.ShowAllFiles,
            text=_('Show all files'),
            toggled=True,
            option='show_all_files')

        comment_act = self.create_action(
            OutlineExplorerActions.ShowSpecialComments,
            text=_('Show special comments'),
            toggled=True,
            option='show_comments')

        group_cells_act = self.create_action(
            OutlineExplorerActions.GroupCodeCells,
            text=_('Group code cells'),
            toggled=True,
            option='group_cells')

        display_variables_act = self.create_action(
            OutlineExplorerActions.DisplayVariables,
            text=_('Display variables and attributes'),
            toggled=True,
            option='display_variables'
        )

        follow_cursor_act = self.create_action(
            OutlineExplorerActions.FollowCursor,
            text=_('Follow cursor position'),
            toggled=True,
            option='follow_cursor'
        )

        sort_files_alphabetically_act = self.create_action(
            OutlineExplorerActions.SortFiles,
            text=_('Sort files alphabetically'),
            toggled=True,
            option='sort_files_alphabetically'
        )

        actions = [fullpath_act, allfiles_act, group_cells_act,
                   display_variables_act, follow_cursor_act, comment_act,
                   sort_files_alphabetically_act, fromcursor_act]

        option_menu = self.get_options_menu()
        for action in actions:
            self.add_item_to_menu(
                action,
                option_menu,
                section=OutlineExplorerSections.DisplayOptions,
            )
Example #35
0
 def get_title(self):
     """Return the title of the plugin tab."""
     return _("Outline")
Example #36
0
 def setup(self):
     self.setToolTip(0, _("Line %s") % str(self.line))
Example #37
0
from qtpy.QtWidgets import (QHBoxLayout, QTreeWidgetItem,
                            QTreeWidgetItemIterator)

# Local imports
from spyder.api.config.decorators import on_conf_change
from spyder.api.widgets.main_widget import PluginMainWidget
from spyder.config.base import _
from spyder.py3compat import to_text_string
from spyder.utils.icon_manager import ima
from spyder.plugins.completion.api import SymbolKind, SYMBOL_KIND_ICON
from spyder.utils.qthelpers import set_item_user_text
from spyder.widgets.onecolumntree import OneColumnTree


SYMBOL_NAME_MAP = {
    SymbolKind.FILE: _('File'),
    SymbolKind.MODULE: _('Module'),
    SymbolKind.NAMESPACE: _('Namespace'),
    SymbolKind.PACKAGE: _('Package'),
    SymbolKind.CLASS: _('Class'),
    SymbolKind.METHOD: _('Method'),
    SymbolKind.PROPERTY: _('Property'),
    SymbolKind.FIELD: _('Attribute'),
    SymbolKind.CONSTRUCTOR: _('constructor'),
    SymbolKind.ENUM: _('Enum'),
    SymbolKind.INTERFACE: _('Interface'),
    SymbolKind.FUNCTION: _('Function'),
    SymbolKind.VARIABLE: _('Variable'),
    SymbolKind.CONSTANT: _('Constant'),
    SymbolKind.STRING: _('String'),
    SymbolKind.NUMBER: _('Number'),
Example #38
0
 def get_plugin_title(self):
     """Return widget title"""
     return _('Variable explorer')
Example #39
0
    def __init__(self, parent, search_text, search_text_regexp,
                 exclude, exclude_idx, exclude_regexp,
                 supported_encodings, more_options,
                 case_sensitive, external_path_history, search_in_index,
                 options_button=None):
        QWidget.__init__(self, parent)
        self._running = False
        if not isinstance(search_text, (list, tuple)):
            search_text = [search_text]
        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('regex'),
                                             tip=_('Regular expression'))
        self.case_button = create_toolbutton(self,
                                             icon=ima.icon(
                                                     "format_letter_case"),
                                             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('stop'),
                                             triggered=lambda:
                                             self.stop.emit(),
                                             tip=_("Stop search"),
                                             text_beside_icon=True)
        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,
                                               _("Exclude 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('regex'),
                                                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)
        self.path_selection_combo.set_current_searchpath_index(
            search_in_index)

        hlayout3.addWidget(search_on_label)
        hlayout3.addWidget(self.path_selection_combo)

        self.search_text.valid.connect(lambda valid: self._check_find())
        self.exclude_pattern.valid.connect(lambda valid: self._check_find())

        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)

        fm = self.ok_button.fontMetrics()
        width = fm.width('Search') * 1.8
        self.ok_button.setMinimumWidth(width)
        self.stop_button.setMinimumWidth(width)
        self.refresh_buttons(start=False)
Example #40
0
    def __init__(self, parent, workdir=None, **kwds):
        SpyderPluginWidget.__init__(self, parent)

        self.toolbar = QToolBar(self)

        # Initialize plugin
        self.initialize_plugin()

        self.toolbar.setWindowTitle(self.get_plugin_title())
        # Used to save Window state
        self.toolbar.setObjectName(self.get_plugin_title())

        # Previous dir action
        self.history = []
        self.histindex = None
        self.previous_action = create_action(self,
                                             "previous",
                                             None,
                                             ima.icon('previous'),
                                             _('Back'),
                                             triggered=self.previous_directory)
        self.toolbar.addAction(self.previous_action)

        # Next dir action
        self.history = []
        self.histindex = None
        self.next_action = create_action(self,
                                         "next",
                                         None,
                                         ima.icon('next'),
                                         _('Next'),
                                         triggered=self.next_directory)
        self.toolbar.addAction(self.next_action)

        # Enable/disable previous/next actions
        self.set_previous_enabled.connect(self.previous_action.setEnabled)
        self.set_next_enabled.connect(self.next_action.setEnabled)

        # Path combo box
        adjust = self.get_option('working_dir_adjusttocontents')
        self.pathedit = PathComboBox(self, adjust_to_contents=adjust)
        self.pathedit.setToolTip(
            _("This is the working directory for newly\n"
              "opened consoles (Python/IPython consoles and\n"
              "terminals), for the file explorer, for the\n"
              "find in files plugin and for new files\n"
              "created in the editor"))
        self.pathedit.open_dir.connect(self.chdir)
        self.pathedit.activated[str].connect(self.chdir)
        self.pathedit.setMaxCount(self.get_option('working_dir_history'))
        wdhistory = self.load_wdhistory(workdir)
        if workdir is None:
            if self.get_option('console/use_project_or_home_directory'):
                workdir = get_home_dir()
            else:
                workdir = self.get_option('console/fixed_directory',
                                          default='')
                if not osp.isdir(workdir):
                    workdir = get_home_dir()
        self.chdir(workdir)
        self.pathedit.addItems(wdhistory)
        self.pathedit.selected_text = self.pathedit.currentText()
        self.refresh_plugin()
        self.toolbar.addWidget(self.pathedit)

        # Browse action
        browse_action = create_action(self,
                                      "browse",
                                      None,
                                      ima.icon('DirOpenIcon'),
                                      _('Browse a working directory'),
                                      triggered=self.select_directory)
        self.toolbar.addAction(browse_action)

        # Parent dir action
        parent_action = create_action(self,
                                      "parent",
                                      None,
                                      ima.icon('up'),
                                      _('Change to parent directory'),
                                      triggered=self.parent_directory)
        self.toolbar.addAction(parent_action)
Example #41
0
    def find_string_in_file(self, fname):
        self.error_flag = False
        self.sig_current_file.emit(fname)
        try:
            for lineno, line in enumerate(open(fname, 'rb')):
                for text, enc in self.texts:
                    with QMutexLocker(self.mutex):
                        if self.stopped:
                            return False
                    line_search = line
                    if not self.case_sensitive:
                        line_search = line_search.lower()
                    if self.text_re:
                        found = re.search(text, line_search)
                        if found is not None:
                            break
                    else:
                        found = line_search.find(text)
                        if found > -1:
                            break
                try:
                    line_dec = line.decode(enc)
                except UnicodeDecodeError:
                    line_dec = line

                if not self.case_sensitive:
                    line = line.lower()

                if self.text_re:
                    for match in re.finditer(text, line):
                        with QMutexLocker(self.mutex):
                            if self.stopped:
                                return False
                        self.total_matches += 1
                        self.partial_results.append((osp.abspath(fname),
                                                     lineno + 1,
                                                     match.start(),
                                                     match.end(),
                                                     line_dec))
                        if len(self.partial_results) > (2**self.power):
                            self.process_results()
                            if self.power < self.max_power:
                                self.power += 1
                else:
                    found = line.find(text)
                    while found > -1:
                        with QMutexLocker(self.mutex):
                            if self.stopped:
                                return False
                        self.total_matches += 1
                        self.partial_results.append((osp.abspath(fname),
                                                     lineno + 1,
                                                     found,
                                                     found + len(text),
                                                     line_dec))
                        if len(self.partial_results) > (2**self.power):
                            self.process_results()
                            if self.power < self.max_power:
                                self.power += 1

                        for text, enc in self.texts:
                            found = line.find(text, found + 1)
                            if found > -1:
                                break

        except IOError as xxx_todo_changeme:
            (_errno, _strerror) = xxx_todo_changeme.args
            self.error_flag = _("permission denied errors were encountered")

        self.completed = True
Example #42
0
from qtpy.QtWidgets import QStackedWidget, QVBoxLayout
from spyder_kernels.utils.nsview import REMOTE_SETTINGS

# Local imports
from spyder import dependencies
from spyder.config.base import _
from spyder.api.plugins import SpyderPluginWidget
from spyder.utils import icon_manager as ima
from spyder.plugins.variableexplorer.widgets.namespacebrowser import (
    NamespaceBrowser)
from spyder.plugins.variableexplorer.confpage import VariableExplorerConfigPage

PANDAS_REQVER = '>=0.13.1'
dependencies.add('pandas',
                 'pandas',
                 _("View and edit DataFrames and Series in the "
                   "Variable Explorer"),
                 required_version=PANDAS_REQVER,
                 optional=True)

NUMPY_REQVER = '>=1.7'
dependencies.add("numpy",
                 "numpy",
                 _("View and edit two and three dimensional arrays "
                   "in the Variable Explorer"),
                 required_version=NUMPY_REQVER,
                 optional=True)

PYMPLER_REQVER = '>=0.7'
dependencies.add("pympler",
                 "pympler",
                 _("Development tool to measure, monitor and analyze the"
Example #43
0
 def reset(self):
     self.status_text.setText(_("  Searching for files..."))
Example #44
0
class FindOptions(QWidget):
    """Find widget with options"""
    REGEX_INVALID = "background-color:rgb(255, 80, 80);"
    REGEX_ERROR = _("Regular expression error")

    find = Signal()
    stop = Signal()
    redirect_stdio = Signal(bool)

    def __init__(self, parent, search_text, search_text_regexp,
                 exclude, exclude_idx, exclude_regexp,
                 supported_encodings, more_options,
                 case_sensitive, external_path_history, search_in_index,
                 options_button=None):
        QWidget.__init__(self, parent)
        self._running = False
        if not isinstance(search_text, (list, tuple)):
            search_text = [search_text]
        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('regex'),
                                             tip=_('Regular expression'))
        self.case_button = create_toolbutton(self,
                                             icon=ima.icon(
                                                     "format_letter_case"),
                                             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('stop'),
                                             triggered=lambda:
                                             self.stop.emit(),
                                             tip=_("Stop search"),
                                             text_beside_icon=True)
        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,
                                               _("Exclude 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('regex'),
                                                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)
        self.path_selection_combo.set_current_searchpath_index(
            search_in_index)

        hlayout3.addWidget(search_on_label)
        hlayout3.addWidget(self.path_selection_combo)

        self.search_text.valid.connect(lambda valid: self._check_find())
        self.exclude_pattern.valid.connect(lambda valid: self._check_find())

        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)

        fm = self.ok_button.fontMetrics()
        width = fm.width('Search') * 1.8
        self.ok_button.setMinimumWidth(width)
        self.stop_button.setMinimumWidth(width)
        self.refresh_buttons(start=False)

    def _check_find(self):
        """
        Check if find signal should be emitted.

        This allows the Enter to function as starting and stopping action
        depending on the state.
        """
        if self._running:
            self.stop.emit()
        else:
            self.find.emit()

    def refresh_buttons(self, start=False):
        """Refresh start/stop of buttons."""
        self._running = start
        self.setUpdatesEnabled(False)
        self.ok_button.setVisible(not start)
        self.stop_button.setVisible(start)
        self.setUpdatesEnabled(True)

    @Slot(bool)
    def toggle_more_options(self, state):
        for layout in self.more_widgets:
            for index in range(layout.count()):
                if state and self.isVisible() or not state:
                    layout.itemAt(index).widget().setVisible(state)
        if state:
            icon = ima.icon('options_less')
            tip = _('Hide advanced options')
        else:
            icon = ima.icon('options_more')
            tip = _('Show advanced options')
        self.more_options.setIcon(icon)
        self.more_options.setToolTip(tip)

    def update_combos(self):
        self.search_text.lineEdit().returnPressed.emit()
        self.exclude_pattern.lineEdit().returnPressed.emit()

    def set_search_text(self, text):
        if text:
            self.search_text.add_text(text)
            self.search_text.lineEdit().selectAll()
        self.search_text.setFocus()

    def get_options(self, to_save=False):
        """Get options"""
        text_re = self.edit_regexp.isChecked()
        exclude_re = self.exclude_regexp.isChecked()
        case_sensitive = self.case_button.isChecked()

        # Return current options for them to be saved when closing
        # Spyder.
        if to_save:
            search_text = [to_text_string(self.search_text.itemText(index))
                           for index in range(self.search_text.count())]
            exclude = [to_text_string(self.exclude_pattern.itemText(index))
                       for index in range(self.exclude_pattern.count())]
            exclude_idx = self.exclude_pattern.currentIndex()
            path_history = self.path_selection_combo.get_external_paths()
            more_options = self.more_options.isChecked()
            search_in_index = self.path_selection_combo.currentIndex()
            return (search_text, text_re,
                    exclude, exclude_idx,
                    exclude_re, more_options,
                    case_sensitive, path_history,
                    search_in_index)

        # Clear fields
        self.search_text.lineEdit().setStyleSheet("")
        self.exclude_pattern.lineEdit().setStyleSheet("")
        self.search_text.setToolTip("")
        self.exclude_pattern.setToolTip("")

        utext = to_text_string(self.search_text.currentText())
        if not utext:
            return

        try:
            texts = [(utext.encode('utf-8'), 'utf-8')]
        except UnicodeEncodeError:
            texts = []
            for enc in self.supported_encodings:
                try:
                    texts.append((utext.encode(enc), enc))
                except UnicodeDecodeError:
                    pass

        exclude = to_text_string(self.exclude_pattern.currentText())

        if not case_sensitive:
            texts = [(text[0].lower(), text[1]) for text in texts]

        file_search = self.path_selection_combo.is_file_search()
        path = self.path_selection_combo.get_current_searchpath()

        if not exclude_re:
            items = [fnmatch.translate(item.strip())
                     for item in exclude.split(",")
                     if item.strip() != '']
            exclude = '|'.join(items)

        # Validate exclude regular expression
        if exclude:
            error_msg = regexp_error_msg(exclude)
            if error_msg:
                exclude_edit = self.exclude_pattern.lineEdit()
                exclude_edit.setStyleSheet(self.REGEX_INVALID)
                tooltip = self.REGEX_ERROR + u': ' + to_text_string(error_msg)
                self.exclude_pattern.setToolTip(tooltip)
                return None
            else:
                exclude = re.compile(exclude)

        # Validate text regular expression
        if text_re:
            error_msg = regexp_error_msg(texts[0][0])
            if error_msg:
                self.search_text.lineEdit().setStyleSheet(self.REGEX_INVALID)
                tooltip = self.REGEX_ERROR + u': ' + to_text_string(error_msg)
                self.search_text.setToolTip(tooltip)
                return None
            else:
                texts = [(re.compile(x[0]), x[1]) for x in texts]

        return (path, file_search, exclude, texts, text_re, case_sensitive)

    @property
    def path(self):
        return self.path_selection_combo.path

    def set_directory(self, directory):
        self.path_selection_combo.path = osp.abspath(directory)

    @property
    def project_path(self):
        return self.path_selection_combo.project_path

    def set_project_path(self, path):
        self.path_selection_combo.set_project_path(path)

    def disable_project_search(self):
        self.path_selection_combo.set_project_path(None)

    @property
    def file_path(self):
        return self.path_selection_combo.file_path

    def set_file_path(self, path):
        self.path_selection_combo.file_path = path

    def keyPressEvent(self, event):
        """Reimplemented to handle key events"""
        ctrl = event.modifiers() & Qt.ControlModifier
        shift = event.modifiers() & Qt.ShiftModifier
        if event.key() in (Qt.Key_Enter, Qt.Key_Return):
            self.find.emit()
        elif event.key() == Qt.Key_F and ctrl and shift:
            # Toggle find widgets
            self.parent().toggle_visibility.emit(not self.isVisible())
        else:
            QWidget.keyPressEvent(self, event)
Example #45
0
 def _update_lock_icon(self):
     """Update locked state icon"""
     icon = ima.icon('lock') if self.locked else ima.icon('lock_open')
     self.locked_button.setIcon(icon)
     tip = _("Unlock") if self.locked else _("Lock")
     self.locked_button.setToolTip(tip)
Example #46
0
    def __init__(self,
                 parent,
                 search_text="",
                 search_text_regexp=False,
                 exclude=EXCLUDE_PATTERNS[0],
                 exclude_idx=None,
                 exclude_regexp=False,
                 supported_encodings=("utf-8", "iso-8859-1", "cp1252"),
                 more_options=False,
                 case_sensitive=False,
                 external_path_history=[],
                 search_in_index=0,
                 options_button=None,
                 text_color=None,
                 max_results=1000):
        QWidget.__init__(self, parent)

        self.search_thread = None
        self.text_color = text_color

        # Widgets
        self.status_bar = FileProgressBar(self)
        self.find_options = FindOptions(
            self,
            search_text,
            search_text_regexp,
            exclude,
            exclude_idx,
            exclude_regexp,
            supported_encodings,
            more_options,
            case_sensitive,
            external_path_history,
            search_in_index,
            options_button=options_button)

        self.result_browser = ResultsBrowser(self, text_color=text_color,
                                             max_results=max_results)
        # Widget setup
        self.setWindowTitle(_('Find in files'))
        self.status_bar.hide()

        # Layout
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.result_browser)

        layout = QVBoxLayout()
        left, _x, right, bottom = layout.getContentsMargins()
        layout.setContentsMargins(left, 0, right, bottom)
        layout.addWidget(self.find_options)
        layout.addLayout(hlayout)
        layout.addWidget(self.status_bar)
        self.setLayout(layout)

        # Signals
        self.find_options.find.connect(self.find)
        self.find_options.stop.connect(self.stop_and_reset_thread)
        self.result_browser.sig_max_results_reached.connect(
            self.stop_and_reset_thread)
        self.result_browser.sig_max_results_reached.connect(
            self.sig_max_results_reached)
Example #47
0
 def get_plugin_title(self):
     """Return widget title"""
     return _('Help')
Example #48
0
    def __init__(self, text, title='', font=None, parent=None, readonly=False):
        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
        self.btn_save_and_close = 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.edit.setReadOnly(readonly)
        self.edit.textChanged.connect(self.text_changed)
        self.edit.setPlainText(text)
        if font is None:
            font = get_font()
        self.edit.setFont(font)
        self.layout.addWidget(self.edit)

        # Buttons configuration
        btn_layout = QHBoxLayout()
        btn_layout.addStretch()
        if not readonly:
            self.btn_save_and_close = QPushButton(_('Save and Close'))
            self.btn_save_and_close.setDisabled(True)
            self.btn_save_and_close.clicked.connect(self.accept)
            btn_layout.addWidget(self.btn_save_and_close)

        self.btn_close = QPushButton(_('Close'))
        self.btn_close.setAutoDefault(True)
        self.btn_close.setDefault(True)
        self.btn_close.clicked.connect(self.reject)
        btn_layout.addWidget(self.btn_close)

        self.layout.addLayout(btn_layout)

        # Make the dialog act as a window
        if sys.platform == 'darwin':
            # See spyder-ide/spyder#12825
            self.setWindowFlags(Qt.Tool)
        else:
            # Make the dialog act as a window
            self.setWindowFlags(Qt.Window)

        self.setWindowIcon(ima.icon('edit'))
        if title:
            try:
                unicode_title = to_text_string(title)
            except UnicodeEncodeError:
                unicode_title = u''
        else:
            unicode_title = u''

        self.setWindowTitle(_("Text editor") + \
                            u"%s" % (u" - " + unicode_title
                                     if unicode_title else u""))
Example #49
0
    def __init__(self,
                 parent,
                 language=None,
                 cmd='',
                 host='127.0.0.1',
                 port=2084,
                 args='',
                 external=False,
                 configurations={},
                 **kwargs):
        super(LSPServerEditor, self).__init__(parent)
        self.parent = parent
        self.external = external
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_ok = bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = bbox.button(QDialogButtonBox.Cancel)
        self.button_ok.setEnabled(False)

        description = _('To create a new configuration, '
                        'you need to select a programming '
                        'language, along with a executable '
                        'name for the server to execute '
                        '(If the instance is local), '
                        'and the host and port. Finally, '
                        'you need to provide the '
                        'arguments that the server accepts. '
                        'The placeholders <tt>{host}</tt> and '
                        '<tt>{port}</tt> refer to the host '
                        'and the port, respectively.')
        server_settings_description = QLabel(description)
        server_settings_description.setWordWrap(True)

        lang_label = QLabel(_('Language:'))
        self.lang_cb = QComboBox(self)
        self.lang_cb.setToolTip(
            _('Programming language provided '
              'by the LSP server'))
        self.lang_cb.addItem(_('Select a language'))
        self.lang_cb.addItems(LSP_LANGUAGES)

        if language is not None:
            idx = LSP_LANGUAGES.index(language)
            self.lang_cb.setCurrentIndex(idx + 1)
            self.button_ok.setEnabled(True)

        host_label = QLabel(_('Host:'))
        self.host_input = QLineEdit(self)
        self.host_input.setToolTip(
            _('Name of the host that will provide '
              'access to the server'))
        self.host_input.setText(host)
        self.host_input.textChanged.connect(lambda x: self.validate())

        port_label = QLabel(_('Port:'))
        self.port_spinner = QSpinBox(self)
        self.port_spinner.setToolTip(_('TCP port number of the server'))
        self.port_spinner.setMinimum(1)
        self.port_spinner.setMaximum(60000)
        self.port_spinner.setValue(port)

        cmd_label = QLabel(_('Command to execute:'))
        self.cmd_input = QLineEdit(self)
        self.cmd_input.setToolTip(
            _('Command used to start the '
              'LSP server locally'))
        self.cmd_input.setText(cmd)

        if not external:
            self.cmd_input.textChanged.connect(lambda x: self.validate())

        args_label = QLabel(_('Server arguments:'))
        self.args_input = QLineEdit(self)
        self.args_input.setToolTip(
            _('Additional arguments required to '
              'start the server'))
        self.args_input.setText(args)

        conf_label = QLabel(_('LSP Server Configurations:'))
        self.conf_input = CodeEditor(None)
        self.conf_input.textChanged.connect(self.validate)
        color_scheme = CONF.get('appearance', 'selected')
        self.conf_input.setup_editor(language='JSON',
                                     color_scheme=color_scheme,
                                     wrap=False,
                                     edge_line=True,
                                     highlight_current_line=True,
                                     highlight_current_cell=True,
                                     occurrence_highlighting=True,
                                     auto_unindent=True,
                                     font=get_font(),
                                     filename='config.json')
        self.conf_input.setToolTip(
            _('Additional LSP server configurations '
              'set at runtime. JSON required'))
        conf_text = '{}'
        try:
            conf_text = json.dumps(configurations, indent=4, sort_keys=True)
        except Exception:
            pass
        self.conf_input.set_text(conf_text)
        self.json_label = QLabel(self.JSON_VALID, self)

        self.external_cb = QCheckBox(_('External server'), self)
        self.external_cb.setToolTip(
            _('Check if the server runs '
              'on a remote location'))
        self.external_cb.setChecked(external)
        self.external_cb.stateChanged.connect(self.set_local_options)

        hlayout = QHBoxLayout()
        general_vlayout = QVBoxLayout()
        general_vlayout.addWidget(server_settings_description)

        vlayout = QVBoxLayout()
        lang_layout = QVBoxLayout()
        lang_layout.addWidget(lang_label)
        lang_layout.addWidget(self.lang_cb)

        # layout2 = QHBoxLayout()
        # layout2.addLayout(lang_layout)
        lang_layout.addWidget(self.external_cb)
        vlayout.addLayout(lang_layout)

        host_layout = QVBoxLayout()
        host_layout.addWidget(host_label)
        host_layout.addWidget(self.host_input)

        port_layout = QVBoxLayout()
        port_layout.addWidget(port_label)
        port_layout.addWidget(self.port_spinner)

        conn_info_layout = QHBoxLayout()
        conn_info_layout.addLayout(host_layout)
        conn_info_layout.addLayout(port_layout)
        vlayout.addLayout(conn_info_layout)

        cmd_layout = QVBoxLayout()
        cmd_layout.addWidget(cmd_label)
        cmd_layout.addWidget(self.cmd_input)
        vlayout.addLayout(cmd_layout)

        args_layout = QVBoxLayout()
        args_layout.addWidget(args_label)
        args_layout.addWidget(self.args_input)
        vlayout.addLayout(args_layout)

        conf_layout = QVBoxLayout()
        conf_layout.addWidget(conf_label)
        conf_layout.addWidget(self.conf_input)
        conf_layout.addWidget(self.json_label)

        hlayout.addLayout(vlayout)
        hlayout.addLayout(conf_layout)
        general_vlayout.addLayout(hlayout)

        general_vlayout.addWidget(bbox)
        self.setLayout(general_vlayout)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        self.lang_cb.currentIndexChanged.connect(self.lang_selection_changed)
        self.form_status(False)
        if language is not None:
            self.form_status(True)
            self.validate()
Example #50
0
    def __init__(self, parent=None, css_path=CSS_PATH):
        SpyderPluginWidget.__init__(self, parent)

        self.internal_shell = None
        self.console = None
        self.css_path = css_path

        self.no_doc_string = _("No documentation available")

        self._last_console_cb = None
        self._last_editor_cb = None

        self.plain_text = PlainText(self)
        self.rich_text = RichText(self)

        color_scheme = self.get_color_scheme()
        self.set_plain_text_font(self.get_font(), color_scheme)
        self.plain_text.editor.toggle_wrap_mode(self.get_option('wrap'))

        # Add entries to read-only editor context-menu
        self.wrap_action = create_action(self,
                                         _("Wrap lines"),
                                         toggled=self.toggle_wrap_mode)
        self.wrap_action.setChecked(self.get_option('wrap'))
        self.plain_text.editor.readonly_menu.addSeparator()
        add_actions(self.plain_text.editor.readonly_menu, (self.wrap_action, ))

        self.set_rich_text_font(self.get_font(rich_text=True))

        self.shell = None

        # locked = disable link with Console
        self.locked = False
        self._last_texts = [None, None]
        self._last_editor_doc = None

        # Object name
        layout_edit = QHBoxLayout()
        layout_edit.setContentsMargins(0, 0, 0, 0)
        txt = _("Source")
        if sys.platform == 'darwin':
            source_label = QLabel("  " + txt)
        else:
            source_label = QLabel(txt)
        layout_edit.addWidget(source_label)
        self.source_combo = QComboBox(self)
        self.source_combo.addItems([_("Console"), _("Editor")])
        self.source_combo.currentIndexChanged.connect(self.source_changed)
        if (not programs.is_module_installed('rope')
                and not programs.is_module_installed('jedi', '>=0.11.0')):
            self.source_combo.hide()
            source_label.hide()
        layout_edit.addWidget(self.source_combo)
        layout_edit.addSpacing(10)
        layout_edit.addWidget(QLabel(_("Object")))
        self.combo = ObjectComboBox(self)
        layout_edit.addWidget(self.combo)
        self.object_edit = QLineEdit(self)
        self.object_edit.setReadOnly(True)
        layout_edit.addWidget(self.object_edit)
        self.combo.setMaxCount(self.get_option('max_history_entries'))
        self.combo.addItems(self.load_history())
        self.combo.setItemText(0, '')
        self.combo.valid.connect(self.force_refresh)

        # Plain text docstring option
        self.docstring = True
        self.rich_help = self.get_option('rich_mode', True)
        self.plain_text_action = create_action(self,
                                               _("Plain Text"),
                                               toggled=self.toggle_plain_text)

        # Source code option
        self.show_source_action = create_action(
            self, _("Show Source"), toggled=self.toggle_show_source)

        # Rich text option
        self.rich_text_action = create_action(self,
                                              _("Rich Text"),
                                              toggled=self.toggle_rich_text)

        # Add the help actions to an exclusive QActionGroup
        help_actions = QActionGroup(self)
        help_actions.setExclusive(True)
        help_actions.addAction(self.plain_text_action)
        help_actions.addAction(self.rich_text_action)

        # Automatic import option
        self.auto_import_action = create_action(
            self, _("Automatic import"), toggled=self.toggle_auto_import)
        auto_import_state = self.get_option('automatic_import')
        self.auto_import_action.setChecked(auto_import_state)

        # Lock checkbox
        self.locked_button = create_toolbutton(self,
                                               triggered=self.toggle_locked)
        layout_edit.addWidget(self.locked_button)
        self._update_lock_icon()

        # Option menu
        layout_edit.addWidget(self.options_button)

        if self.rich_help:
            self.switch_to_rich_text()
        else:
            self.switch_to_plain_text()
        self.plain_text_action.setChecked(not self.rich_help)
        self.rich_text_action.setChecked(self.rich_help)
        self.source_changed()

        # Main layout
        layout = create_plugin_layout(layout_edit)
        # we have two main widgets, but only one of them is shown at a time
        layout.addWidget(self.plain_text)
        layout.addWidget(self.rich_text)
        self.setLayout(layout)

        # Add worker thread for handling rich text rendering
        self._sphinx_thread = SphinxThread(html_text_no_doc=warning(
            self.no_doc_string, css_path=self.css_path),
                                           css_path=self.css_path)
        self._sphinx_thread.html_ready.connect(
            self._on_sphinx_thread_html_ready)
        self._sphinx_thread.error_msg.connect(self._on_sphinx_thread_error_msg)

        # Handle internal and external links
        view = self.rich_text.webview
        if not WEBENGINE:
            view.page().setLinkDelegationPolicy(
                QWebEnginePage.DelegateAllLinks)
        view.linkClicked.connect(self.handle_link_clicks)

        self._starting_up = True
Example #51
0
 def setup(self):
     self.set_icon(ima.icon('cell'))
     font = self.font(0)
     font.setItalic(True)
     self.setFont(0, font)
     self.setToolTip(0, _("Cell starts at line %s") % str(self.line))
Example #52
0
class LSPServerEditor(QDialog):
    DEFAULT_HOST = '127.0.0.1'
    DEFAULT_PORT = 2084
    DEFAULT_CMD = ''
    DEFAULT_ARGS = ''
    DEFAULT_CONFIGURATION = '{}'
    DEFAULT_EXTERNAL = False
    HOST_REGEX = re.compile(r'^\w+([.]\w+)*$')
    NON_EMPTY_REGEX = re.compile(r'^\S+$')
    JSON_VALID = _('JSON valid')
    JSON_INVALID = _('JSON invalid')

    def __init__(self,
                 parent,
                 language=None,
                 cmd='',
                 host='127.0.0.1',
                 port=2084,
                 args='',
                 external=False,
                 configurations={},
                 **kwargs):
        super(LSPServerEditor, self).__init__(parent)
        self.parent = parent
        self.external = external
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_ok = bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = bbox.button(QDialogButtonBox.Cancel)
        self.button_ok.setEnabled(False)

        description = _('To create a new configuration, '
                        'you need to select a programming '
                        'language, along with a executable '
                        'name for the server to execute '
                        '(If the instance is local), '
                        'and the host and port. Finally, '
                        'you need to provide the '
                        'arguments that the server accepts. '
                        'The placeholders <tt>{host}</tt> and '
                        '<tt>{port}</tt> refer to the host '
                        'and the port, respectively.')
        server_settings_description = QLabel(description)
        server_settings_description.setWordWrap(True)

        lang_label = QLabel(_('Language:'))
        self.lang_cb = QComboBox(self)
        self.lang_cb.setToolTip(
            _('Programming language provided '
              'by the LSP server'))
        self.lang_cb.addItem(_('Select a language'))
        self.lang_cb.addItems(LSP_LANGUAGES)

        if language is not None:
            idx = LSP_LANGUAGES.index(language)
            self.lang_cb.setCurrentIndex(idx + 1)
            self.button_ok.setEnabled(True)

        host_label = QLabel(_('Host:'))
        self.host_input = QLineEdit(self)
        self.host_input.setToolTip(
            _('Name of the host that will provide '
              'access to the server'))
        self.host_input.setText(host)
        self.host_input.textChanged.connect(lambda x: self.validate())

        port_label = QLabel(_('Port:'))
        self.port_spinner = QSpinBox(self)
        self.port_spinner.setToolTip(_('TCP port number of the server'))
        self.port_spinner.setMinimum(1)
        self.port_spinner.setMaximum(60000)
        self.port_spinner.setValue(port)

        cmd_label = QLabel(_('Command to execute:'))
        self.cmd_input = QLineEdit(self)
        self.cmd_input.setToolTip(
            _('Command used to start the '
              'LSP server locally'))
        self.cmd_input.setText(cmd)

        if not external:
            self.cmd_input.textChanged.connect(lambda x: self.validate())

        args_label = QLabel(_('Server arguments:'))
        self.args_input = QLineEdit(self)
        self.args_input.setToolTip(
            _('Additional arguments required to '
              'start the server'))
        self.args_input.setText(args)

        conf_label = QLabel(_('LSP Server Configurations:'))
        self.conf_input = CodeEditor(None)
        self.conf_input.textChanged.connect(self.validate)
        color_scheme = CONF.get('appearance', 'selected')
        self.conf_input.setup_editor(language='JSON',
                                     color_scheme=color_scheme,
                                     wrap=False,
                                     edge_line=True,
                                     highlight_current_line=True,
                                     highlight_current_cell=True,
                                     occurrence_highlighting=True,
                                     auto_unindent=True,
                                     font=get_font(),
                                     filename='config.json')
        self.conf_input.setToolTip(
            _('Additional LSP server configurations '
              'set at runtime. JSON required'))
        conf_text = '{}'
        try:
            conf_text = json.dumps(configurations, indent=4, sort_keys=True)
        except Exception:
            pass
        self.conf_input.set_text(conf_text)
        self.json_label = QLabel(self.JSON_VALID, self)

        self.external_cb = QCheckBox(_('External server'), self)
        self.external_cb.setToolTip(
            _('Check if the server runs '
              'on a remote location'))
        self.external_cb.setChecked(external)
        self.external_cb.stateChanged.connect(self.set_local_options)

        hlayout = QHBoxLayout()
        general_vlayout = QVBoxLayout()
        general_vlayout.addWidget(server_settings_description)

        vlayout = QVBoxLayout()
        lang_layout = QVBoxLayout()
        lang_layout.addWidget(lang_label)
        lang_layout.addWidget(self.lang_cb)

        # layout2 = QHBoxLayout()
        # layout2.addLayout(lang_layout)
        lang_layout.addWidget(self.external_cb)
        vlayout.addLayout(lang_layout)

        host_layout = QVBoxLayout()
        host_layout.addWidget(host_label)
        host_layout.addWidget(self.host_input)

        port_layout = QVBoxLayout()
        port_layout.addWidget(port_label)
        port_layout.addWidget(self.port_spinner)

        conn_info_layout = QHBoxLayout()
        conn_info_layout.addLayout(host_layout)
        conn_info_layout.addLayout(port_layout)
        vlayout.addLayout(conn_info_layout)

        cmd_layout = QVBoxLayout()
        cmd_layout.addWidget(cmd_label)
        cmd_layout.addWidget(self.cmd_input)
        vlayout.addLayout(cmd_layout)

        args_layout = QVBoxLayout()
        args_layout.addWidget(args_label)
        args_layout.addWidget(self.args_input)
        vlayout.addLayout(args_layout)

        conf_layout = QVBoxLayout()
        conf_layout.addWidget(conf_label)
        conf_layout.addWidget(self.conf_input)
        conf_layout.addWidget(self.json_label)

        hlayout.addLayout(vlayout)
        hlayout.addLayout(conf_layout)
        general_vlayout.addLayout(hlayout)

        general_vlayout.addWidget(bbox)
        self.setLayout(general_vlayout)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        self.lang_cb.currentIndexChanged.connect(self.lang_selection_changed)
        self.form_status(False)
        if language is not None:
            self.form_status(True)
            self.validate()

    @Slot()
    def validate(self):
        host_text = self.host_input.text()
        cmd_text = self.cmd_input.text()
        if not self.HOST_REGEX.match(host_text):
            self.button_ok.setEnabled(False)
            self.host_input.setStyleSheet("QLineEdit{border: 1px solid red;}")
            self.host_input.setToolTip('Hostname must be valid')
            return
        else:
            self.host_input.setStyleSheet(
                "QLineEdit{border: 1px solid green;}")
            self.host_input.setToolTip('Hostname is valid')
            self.button_ok.setEnabled(True)

        if not self.external:
            if not self.NON_EMPTY_REGEX.match(cmd_text):
                self.button_ok.setEnabled(False)
                self.cmd_input.setStyleSheet(
                    "QLineEdit{border: 1px solid red;}")
                self.cmd_input.setToolTip('Command must be non empty')
                return

            if find_program(cmd_text) is None:
                self.button_ok.setEnabled(False)
                self.cmd_input.setStyleSheet(
                    "QLineEdit{border: 1px solid red;}")
                self.cmd_input.setToolTip('Program was not found '
                                          'on your system')
                return
            else:
                self.cmd_input.setStyleSheet(
                    "QLineEdit{border: 1px solid green;}")
                self.cmd_input.setToolTip('Program was found on your system')
                self.button_ok.setEnabled(True)
        try:
            json.loads(self.conf_input.toPlainText())
            try:
                self.json_label.setText(self.JSON_VALID)
            except Exception:
                pass
        except (ValueError, json.decoder.JSONDecodeError):
            try:
                self.json_label.setText(self.JSON_INVALID)
                self.button_ok.setEnabled(False)
            except Exception:
                pass

    def form_status(self, status):
        self.host_input.setEnabled(status)
        self.port_spinner.setEnabled(status)
        self.external_cb.setEnabled(status)
        self.cmd_input.setEnabled(status)
        self.args_input.setEnabled(status)
        self.conf_input.setEnabled(status)
        self.json_label.setVisible(status)

    @Slot()
    def lang_selection_changed(self):
        idx = self.lang_cb.currentIndex()
        if idx == 0:
            self.set_defaults()
            self.form_status(False)
            self.button_ok.setEnabled(False)
        else:
            server = self.parent.get_server_by_lang(LSP_LANGUAGES[idx - 1])
            self.form_status(True)
            if server is not None:
                self.host_input.setText(server.host)
                self.port_spinner.setValue(server.port)
                self.external_cb.setChecked(server.external)
                self.cmd_input.setText(server.cmd)
                self.args_input.setText(server.args)
                self.conf_input.set_text(json.dumps(server.configurations))
                self.json_label.setText(self.JSON_VALID)
                self.button_ok.setEnabled(True)
            else:
                self.set_defaults()

    def set_defaults(self):
        self.cmd_input.setStyleSheet('')
        self.host_input.setStyleSheet('')
        self.host_input.setText(self.DEFAULT_HOST)
        self.port_spinner.setValue(self.DEFAULT_PORT)
        self.external_cb.setChecked(self.DEFAULT_EXTERNAL)
        self.cmd_input.setText(self.DEFAULT_CMD)
        self.args_input.setText(self.DEFAULT_ARGS)
        self.conf_input.set_text(self.DEFAULT_CONFIGURATION)
        self.json_label.setText(self.JSON_VALID)

    @Slot(bool)
    @Slot(int)
    def set_local_options(self, enabled):
        self.external = enabled
        self.cmd_input.setEnabled(True)
        self.args_input.setEnabled(True)
        if enabled:
            self.cmd_input.setEnabled(False)
            self.cmd_input.setStyleSheet('')
            self.args_input.setEnabled(False)
        try:
            self.validate()
        except Exception:
            pass

    def get_options(self):
        language_idx = self.lang_cb.currentIndex()
        language = LSP_LANGUAGES[language_idx - 1]
        host = self.host_input.text()
        port = int(self.port_spinner.value())
        external = self.external_cb.isChecked()
        args = self.args_input.text()
        cmd = self.cmd_input.text()
        configurations = json.loads(self.conf_input.toPlainText())
        server = LSPServer(language=language.lower(),
                           cmd=cmd,
                           args=args,
                           host=host,
                           port=port,
                           external=external,
                           configurations=configurations)
        return server
Example #53
0
 def setup(self):
     self.set_icon(ima.icon('class'))
     self.setToolTip(0, _("Class defined at line %s") % str(self.line))
Example #54
0
 def get_plugin_title(self):
     """Return widget title"""
     return _("Profiler")
Example #55
0
 def get_plugin_title(self):
     """Return widget title"""
     return _("File explorer")
Example #56
0
 def setup(self):
     self.set_icon(ima.icon('blockcomment'))
     font = self.font(0)
     font.setItalic(True)
     self.setFont(0, font)
     self.setToolTip(0, _("Line %s") % str(self.line))
Example #57
0
    def setup(self):
        """Setup the ShortcutEditor with the provided arguments."""
        # Widgets
        icon_info = HelperToolButton()
        icon_info.setIcon(get_std_icon('MessageBoxInformation'))
        layout_icon_info = QVBoxLayout()
        layout_icon_info.setContentsMargins(0, 0, 0, 0)
        layout_icon_info.setSpacing(0)
        layout_icon_info.addWidget(icon_info)
        layout_icon_info.addStretch(100)

        self.label_info = QLabel()
        self.label_info.setText(
            _("Press the new shortcut and select 'Ok' to confirm, "
              "click 'Cancel' to revert to the previous state, "
              "or use 'Clear' to unbind the command from a shortcut."))
        self.label_info.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        self.label_info.setWordWrap(True)
        layout_info = QHBoxLayout()
        layout_info.setContentsMargins(0, 0, 0, 0)
        layout_info.addLayout(layout_icon_info)
        layout_info.addWidget(self.label_info)
        layout_info.setStretch(1, 100)

        self.label_current_sequence = QLabel(_("Current shortcut:"))
        self.text_current_sequence = QLabel(self.current_sequence)

        self.label_new_sequence = QLabel(_("New shortcut:"))
        self.text_new_sequence = ShortcutLineEdit(self)
        self.text_new_sequence.setPlaceholderText(_("Press shortcut."))

        self.helper_button = HelperToolButton()
        self.helper_button.setIcon(QIcon())
        self.label_warning = QLabel()
        self.label_warning.setWordWrap(True)
        self.label_warning.setAlignment(Qt.AlignTop | Qt.AlignLeft)

        self.button_default = QPushButton(_('Default'))
        self.button_ok = QPushButton(_('Ok'))
        self.button_ok.setEnabled(False)
        self.button_clear = QPushButton(_('Clear'))
        self.button_cancel = QPushButton(_('Cancel'))
        button_box = QHBoxLayout()
        button_box.addWidget(self.button_default)
        button_box.addStretch(100)
        button_box.addWidget(self.button_ok)
        button_box.addWidget(self.button_clear)
        button_box.addWidget(self.button_cancel)

        # New Sequence button box
        self.btn_clear_sequence = create_toolbutton(
            self,
            icon=ima.icon('editclear'),
            tip=_("Clear all entered key sequences"),
            triggered=self.clear_new_sequence)
        self.button_back_sequence = create_toolbutton(
            self,
            icon=ima.icon('ArrowBack'),
            tip=_("Remove last key sequence entered"),
            triggered=self.back_new_sequence)

        newseq_btnbar = QHBoxLayout()
        newseq_btnbar.setSpacing(0)
        newseq_btnbar.setContentsMargins(0, 0, 0, 0)
        newseq_btnbar.addWidget(self.button_back_sequence)
        newseq_btnbar.addWidget(self.btn_clear_sequence)

        # Setup widgets
        self.setWindowTitle(_('Shortcut: {0}').format(self.name))
        self.helper_button.setToolTip('')
        style = """
            QToolButton {
              margin:1px;
              border: 0px solid grey;
              padding:0px;
              border-radius: 0px;
            }"""
        self.helper_button.setStyleSheet(style)
        icon_info.setToolTip('')
        icon_info.setStyleSheet(style)

        # Layout
        layout_sequence = QGridLayout()
        layout_sequence.setContentsMargins(0, 0, 0, 0)
        layout_sequence.addLayout(layout_info, 0, 0, 1, 4)
        layout_sequence.addItem(QSpacerItem(15, 15), 1, 0, 1, 4)
        layout_sequence.addWidget(self.label_current_sequence, 2, 0)
        layout_sequence.addWidget(self.text_current_sequence, 2, 2)
        layout_sequence.addWidget(self.label_new_sequence, 3, 0)
        layout_sequence.addWidget(self.helper_button, 3, 1)
        layout_sequence.addWidget(self.text_new_sequence, 3, 2)
        layout_sequence.addLayout(newseq_btnbar, 3, 3)
        layout_sequence.addWidget(self.label_warning, 4, 2, 1, 2)
        layout_sequence.setColumnStretch(2, 100)
        layout_sequence.setRowStretch(4, 100)

        layout = QVBoxLayout()
        layout.addLayout(layout_sequence)
        layout.addSpacing(5)
        layout.addLayout(button_box)
        self.setLayout(layout)

        # Signals
        self.button_ok.clicked.connect(self.accept_override)
        self.button_clear.clicked.connect(self.unbind_shortcut)
        self.button_cancel.clicked.connect(self.reject)
        self.button_default.clicked.connect(self.set_sequence_to_default)

        # Set all widget to no focus so that we can register <Tab> key
        # press event.
        widgets = (self.label_warning, self.helper_button,
                   self.text_new_sequence, self.button_clear,
                   self.button_default, self.button_cancel, self.button_ok,
                   self.btn_clear_sequence, self.button_back_sequence)
        for w in widgets:
            w.setFocusPolicy(Qt.NoFocus)
            w.clearFocus()
Example #58
0
def run_python_script_in_terminal(fname, wdir, args, interact,
                                  debug, python_args):
    """
    Run Python script in an external system terminal.

    :str wdir: working directory, may be empty.
    """
    # If fname has spaces on it it can't be ran on Windows, so we have to
    # enclose it in quotes. Also wdir can come with / as os.sep, so we
    # need to take care of it
    if os.name == 'nt':
        fname = '"' + fname + '"'
        wdir = wdir.replace('/', '\\')
    
    p_args = ['python']
    p_args += get_python_args(fname, python_args, interact, debug, args)
    
    if os.name == 'nt':
        cmd = 'start cmd.exe /c "cd %s && ' % wdir + ' '.join(p_args) + '"'
        # Command line and cwd have to be converted to the filesystem
        # encoding before passing them to subprocess, but only for
        # Python 2.
        # See http://bugs.python.org/issue1759845#msg74142 and Issue 1856
        if PY2:
            cmd = encoding.to_fs_from_unicode(cmd)
            wdir = encoding.to_fs_from_unicode(wdir)
        try:
            run_shell_command(cmd, cwd=wdir)
        except WindowsError:
            from qtpy.QtWidgets import QMessageBox
            from spyder.config.base import _
            QMessageBox.critical(None, _('Run'),
                                 _("It was not possible to run this file in "
                                   "an external terminal"),
                                 QMessageBox.Ok)
    elif os.name == 'posix':
        programs = [{'cmd': 'gnome-terminal',
                     'wdir-option': '--working-directory',
                     'execute-option': '-x'},
                    {'cmd': 'konsole',
                     'wdir-option': '--workdir',
                     'execute-option': '-e'},
                    {'cmd': 'xfce4-terminal',
                     'wdir-option': '--working-directory',
                     'execute-option': '-x'},
                    {'cmd': 'xterm',
                     'wdir-option': None,
                     'execute-option': '-e'},]
        for program in programs:
            if is_program_installed(program['cmd']):
                arglist = []
                if program['wdir-option'] and wdir:
                    arglist += [program['wdir-option'], wdir]
                arglist.append(program['execute-option'])
                arglist += p_args
                if wdir:
                    run_program(program['cmd'], arglist, cwd=wdir)
                else:
                    run_program(program['cmd'], arglist)
                return
        # TODO: Add a fallback to OSX
    else:
        raise NotImplementedError
Example #59
0
    def add_table(self):
        """Add table with info about files to be recovered."""
        table = QTableWidget(len(self.data), 3, self)
        self.table = table

        labels = [_('Original file'), _('Autosave file'), _('Actions')]
        table.setHorizontalHeaderLabels(labels)
        table.verticalHeader().hide()

        table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        table.setSelectionMode(QTableWidget.NoSelection)

        # Show horizontal grid lines
        table.setShowGrid(False)
        table.setStyleSheet('::item { border-bottom: 1px solid gray }')

        for idx, (original, autosave) in enumerate(self.data):
            self.add_label_to_table(idx, 0, file_data_to_str(original))
            self.add_label_to_table(idx, 1, file_data_to_str(autosave))

            widget = QWidget()
            layout = QHBoxLayout()

            tooltip = _('Recover the autosave file to its original location, '
                        'replacing the original if it exists.')
            button = QPushButton(_('Restore'))
            button.setToolTip(tooltip)
            button.clicked.connect(
                lambda checked, my_idx=idx: self.restore(my_idx))
            layout.addWidget(button)

            tooltip = _('Delete the autosave file.')
            button = QPushButton(_('Discard'))
            button.setToolTip(tooltip)
            button.clicked.connect(
                lambda checked, my_idx=idx: self.discard(my_idx))
            layout.addWidget(button)

            tooltip = _('Display the autosave file (and the original, if it '
                        'exists) in Spyder\'s Editor. You will have to move '
                        'or delete it manually.')
            button = QPushButton(_('Open'))
            button.setToolTip(tooltip)
            button.clicked.connect(
                lambda checked, my_idx=idx: self.open_files(my_idx))
            layout.addWidget(button)

            widget.setLayout(layout)
            self.table.setCellWidget(idx, 2, widget)

        table.resizeRowsToContents()
        table.resizeColumnsToContents()

        # Need to add the "+ 2" because otherwise the table scrolls a tiny
        # amount; no idea why
        width = table.horizontalHeader().length() + 2
        height = (table.verticalHeader().length() +
                  table.horizontalHeader().height() + 2)
        table.setFixedSize(width, height)
        self.layout.addWidget(table)
Example #60
0
    def setup_toolbar(self):
        """Setup the toolbar"""
        savefig_btn = create_toolbutton(self,
                                        icon=ima.icon('filesave'),
                                        tip=_("Save Image As..."),
                                        triggered=self.save_figure)

        saveall_btn = create_toolbutton(self,
                                        icon=ima.icon('save_all'),
                                        tip=_("Save All Images..."),
                                        triggered=self.save_all_figures)

        copyfig_btn = create_toolbutton(
            self,
            icon=ima.icon('editcopy'),
            tip=_("Copy plot to clipboard as image (%s)" %
                  get_shortcut('plots', 'copy')),
            triggered=self.copy_figure)

        closefig_btn = create_toolbutton(self,
                                         icon=ima.icon('editclear'),
                                         tip=_("Remove image"),
                                         triggered=self.close_figure)

        closeall_btn = create_toolbutton(
            self,
            icon=ima.icon('filecloseall'),
            tip=_("Remove all images from the explorer"),
            triggered=self.close_all_figures)

        vsep1 = QFrame()
        vsep1.setFrameStyle(53)

        goback_btn = create_toolbutton(self,
                                       icon=ima.icon('ArrowBack'),
                                       tip=_("Previous Figure"),
                                       triggered=self.go_previous_thumbnail)

        gonext_btn = create_toolbutton(self,
                                       icon=ima.icon('ArrowForward'),
                                       tip=_("Next Figure"),
                                       triggered=self.go_next_thumbnail)

        vsep2 = QFrame()
        vsep2.setFrameStyle(53)

        zoom_out_btn = create_toolbutton(
            self,
            icon=ima.icon('zoom_out'),
            tip=_("Zoom out (Ctrl + mouse-wheel-down)"),
            triggered=self.zoom_out)

        zoom_in_btn = create_toolbutton(
            self,
            icon=ima.icon('zoom_in'),
            tip=_("Zoom in (Ctrl + mouse-wheel-up)"),
            triggered=self.zoom_in)

        self.zoom_disp = QSpinBox()
        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)
        self.figviewer.sig_zoom_changed.connect(self.zoom_disp.setValue)

        zoom_pan = QWidget()
        layout = QHBoxLayout(zoom_pan)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(zoom_out_btn)
        layout.addWidget(zoom_in_btn)
        layout.addWidget(self.zoom_disp)

        return [
            savefig_btn, saveall_btn, copyfig_btn, closefig_btn, closeall_btn,
            vsep1, goback_btn, gonext_btn, vsep2, zoom_pan
        ]