Ejemplo n.º 1
0
def construct_editor(qtbot, *args, **kwargs):
    os.environ['SPY_TEST_USE_INTROSPECTION'] = 'True'
    app = qapplication()
    lsp_manager = LSPManager(parent=None)
    editor = CodeEditor(parent=None)
    kwargs['language'] = 'Python'
    editor.setup_editor(*args, **kwargs)
    wrapper = LSPEditorWrapper(None, editor, lsp_manager)

    lsp_manager.register_plugin_type(
        LSPEventTypes.DOCUMENT, wrapper.sig_initialize)
    with qtbot.waitSignal(wrapper.sig_initialize, timeout=30000):
        editor.filename = 'test.py'
        editor.language = 'Python'
        lsp_manager.start_lsp_client('python')

    text = ("def some_function():\n"  # D100, D103: Missing docstring
            "    \n"  # W293 trailing spaces
            "    a = 1 # a comment\n"  # E261 two spaces before inline comment
            "\n"
            "    a += s\n"  # Undefined variable s
            "    return a\n"
            )
    editor.set_text(text)
    with qtbot.waitSignal(editor.lsp_response_signal, timeout=30000):
        editor.document_did_open()

    yield editor, lsp_manager
    os.environ['SPY_TEST_USE_INTROSPECTION'] = 'False'
    lsp_manager.closing_plugin()
Ejemplo n.º 2
0
def lsp_codeeditor(lsp_manager, qtbot_module, request):
    """CodeEditor instance with LSP services activated."""
    # Create a CodeEditor instance
    editor = CodeEditor(parent=None)
    editor.setup_editor(language='Python',
                        tab_mode=False,
                        markers=True,
                        close_quotes=True,
                        close_parentheses=True,
                        color_scheme='spyder/dark',
                        font=QFont("Monospace", 10))
    editor.resize(640, 480)
    qtbot_module.addWidget(editor)
    editor.show()

    # Redirect editor LSP requests to lsp_manager
    editor.sig_perform_lsp_request.connect(lsp_manager.send_request)

    editor.filename = 'test.py'
    editor.language = 'Python'
    lsp_manager.register_file('python', 'test.py', editor)
    server_settings = lsp_manager.main.editor.lsp_editor_settings['python']
    editor.start_lsp_services(server_settings)

    with qtbot_module.waitSignal(editor.lsp_response_signal, timeout=30000):
        editor.document_did_open()

    def teardown():
        editor.hide()
        editor.completion_widget.hide()

    request.addfinalizer(teardown)
    return editor, lsp_manager
Ejemplo n.º 3
0
def editor_close_brackets():
    """Set up Editor with close brackets activated."""
    app = qapplication()
    editor = CodeEditor(parent=None)
    kwargs = {}
    kwargs['language'] = 'Python'
    kwargs['close_parentheses'] = True
    editor.setup_editor(**kwargs)
    return editor
Ejemplo n.º 4
0
def findreplace_editor(qtbot, request):
    """Set up PathManager."""
    editor = CodeEditor()
    editor.setup_editor()
    widget = FindReplace(None)
    widget.set_editor(editor)
    qtbot.addWidget(widget)
    qtbot.addWidget(editor)
    return widget, editor
Ejemplo n.º 5
0
def construct_editor(text):
    app = qapplication()
    editor = CodeEditor(parent=None)
    editor.setup_editor(language='Python')
    editor.set_text(text)
    cursor = editor.textCursor()
    cursor.movePosition(QTextCursor.End)
    editor.setTextCursor(cursor)
    return editor
Ejemplo n.º 6
0
def editor_auto_docstring():
    """Set up Editor with auto docstring activated."""
    app = qapplication()
    editor = CodeEditor(parent=None)
    kwargs = {}
    kwargs['language'] = 'Python'
    kwargs['close_quotes'] = True
    kwargs['close_parentheses'] = True
    editor.setup_editor(**kwargs)
    return editor
Ejemplo n.º 7
0
def editor_bot(qtbot):
    widget = CodeEditor(None)
    widget.setup_editor(linenumbers=True,
                        markers=True,
                        show_blanks=True,
                        scrollflagarea=True,
                        font=QFont("Courier New", 10),
                        color_scheme='Zenburn',
                        language='Python')
    qtbot.addWidget(widget)
    return widget
Ejemplo n.º 8
0
def codeeditor_factory():
    editor = CodeEditor(parent=None)
    editor.setup_editor(language='Python',
                        tab_mode=False,
                        markers=True,
                        close_quotes=True,
                        close_parentheses=True,
                        color_scheme='spyder/dark',
                        font=QFont("Monospace", 10))
    editor.resize(640, 480)
    return editor
Ejemplo n.º 9
0
def code_editor_bot(qtbot):
    """
    Setup CodeEditor with some text useful for folding related tests.
    """
    editor = CodeEditor(parent=None)
    indent_chars = " " * 4
    tab_stop_width_spaces = 4
    language = "Python"
    editor.setup_editor(language=language, indent_chars=indent_chars,
                        tab_stop_width_spaces=tab_stop_width_spaces)

    return editor, qtbot
Ejemplo n.º 10
0
def construct_editor(qtbot):
    """Construct editor for testing decorations."""
    editor = CodeEditor(parent=None)
    editor.setup_editor(
        language='Python',
        color_scheme='spyder/dark',
        font=QFont("Monospace", 10),
    )
    editor.resize(640, 480)
    editor.show()
    qtbot.addWidget(editor)
    return editor
Ejemplo n.º 11
0
    def _create_outlineexplorer(code, filename, follow_cursor=False):
        code_editor = CodeEditor(None)
        code_editor.set_language('py', filename)
        code_editor.set_text(code)

        editor = OutlineExplorerProxyEditor(code_editor, filename)

        outlineexplorer = OutlineExplorerWidget(follow_cursor=follow_cursor)
        outlineexplorer.set_current_editor(editor, False, False)
        outlineexplorer.show()
        outlineexplorer.setFixedSize(400, 350)

        qtbot.addWidget(outlineexplorer)
        return outlineexplorer
Ejemplo n.º 12
0
def codeeditor_factory():
    editor = CodeEditor(parent=None)
    editor.setup_editor(language='Python',
                        tab_mode=False,
                        markers=True,
                        close_quotes=True,
                        close_parentheses=True,
                        color_scheme='spyder/dark',
                        font=QFont("Monospace", 10),
                        automatic_completions=True,
                        automatic_completions_after_chars=1,
                        automatic_completions_after_ms=200)
    editor.resize(640, 480)
    return editor
Ejemplo n.º 13
0
def codeeditor(qtbot):
    widget = CodeEditor(None)
    widget.setup_editor(linenumbers=True,
                        markers=True,
                        tab_mode=False,
                        font=QFont("Courier New", 10),
                        show_blanks=True,
                        color_scheme='spyder/dark',
                        scroll_past_end=True)
    widget.setup_editor(language='Python')
    widget.resize(640, 480)
    widget.show()
    yield widget
    widget.close()
Ejemplo n.º 14
0
def construct_editor(*args, **kwargs):
    """Construct editor with some text for testing extra selections."""
    app = qapplication()
    editor = CodeEditor(parent=None)
    kwargs['language'] = 'Python'
    editor.setup_editor(*args, **kwargs)

    text = ("def some_function():\n"
            "    some_variable = 1\n"
            "    some_variable += 2\n"
            "    return some_variable\n"
            "# %%")
    editor.set_text(text)
    return editor
Ejemplo n.º 15
0
def editor_outline_explorer_bot():
    """setup editor and outline_explorer."""
    app = qapplication()
    editor = CodeEditor(parent=None)
    editor.setup_editor(language='Python')
    outlineexplorer = OutlineExplorerWidget(editor)

    editor.set_text(text)

    editor.oe_proxy = OutlineExplorerProxyEditor(editor, "test.py")
    outlineexplorer.set_current_editor(editor.oe_proxy,
                                       update=False,
                                       clear=False)
    outlineexplorer.setEnabled(True)

    return editor, outlineexplorer, editor.oe_proxy
Ejemplo n.º 16
0
def get_indent_fix(text, indent_chars=" " * 4, tab_stop_width_spaces=4,
                   sol=False, forward=True, language='Python'):
    """Return text with last line's indentation fixed."""
    app = qapplication()
    editor = CodeEditor(parent=None)
    editor.setup_editor(language=language, indent_chars=indent_chars,
                        tab_stop_width_spaces=tab_stop_width_spaces)

    editor.set_text(text)
    cursor = editor.textCursor()
    cursor.movePosition(QTextCursor.End)
    if sol:
        lines = text.splitlines(True)
        repeat = len(lines[-1].lstrip())
        cursor.movePosition(QTextCursor.Left, n=repeat)
    editor.setTextCursor(cursor)
    editor.fix_indent(forward=forward)
    return to_text_string(editor.toPlainText())
Ejemplo n.º 17
0
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        font = QFont(get_family(MONOSPACE), 10, QFont.Normal)

        info_icon = QLabel()
        icon = get_std_icon("MessageBoxInformation").pixmap(24, 24)
        info_icon.setPixmap(icon)
        info_icon.setFixedWidth(32)
        info_icon.setAlignment(Qt.AlignTop)
        self.desc_label = QLabel()
        self.desc_label.setWordWrap(True)
        self.desc_label.setAlignment(Qt.AlignTop)
        self.desc_label.setFont(font)
        group_desc = QGroupBox(_("Description"), self)
        layout = QHBoxLayout()
        layout.addWidget(info_icon)
        layout.addWidget(self.desc_label)
        group_desc.setLayout(layout)

        self.editor = CodeEditor(self)
        self.editor.setup_editor(linenumbers=True, font=font)
        self.editor.setReadOnly(True)
        group_code = QGroupBox(_("Source code"), self)
        layout = QVBoxLayout()
        layout.addWidget(self.editor)
        group_code.setLayout(layout)

        self.run_button = QPushButton(get_icon("apply.png"),
                                      _("Run this script"), self)
        self.quit_button = QPushButton(get_icon("exit.png"), _("Quit"), self)
        hlayout = QHBoxLayout()
        hlayout.addWidget(self.run_button)
        hlayout.addStretch()
        hlayout.addWidget(self.quit_button)

        vlayout = QVBoxLayout()
        vlayout.addWidget(group_desc)
        vlayout.addWidget(group_code)
        vlayout.addLayout(hlayout)
        self.setLayout(vlayout)
Ejemplo n.º 18
0
def get_fold_levels():
    """setup editor and return fold levels."""
    app = qapplication()
    editor = CodeEditor(parent=None)
    editor.setup_editor(language='Python')

    text = (
        '# dummy test file\n'
        'class a():\n'  # fold-block level-0
        '    self.b = 1\n'
        '    print(self.b)\n'
        '    \n'
        '    def some_method(self):\n'  # fold-block level-1
        '        self.b = 3\n'
        '\n'
        '    def other_method(self):\n'  # fold-block level-1
        '\n'  # a blank line (should be ignored)
        '  # a comment with arbitrary indentation\n'  # should be ignored
        '         a = (1,\n'  # fold-block level-2
        '              2,\n'
        '              3)\n')

    editor.set_text(text)
    return print_tree(editor, return_list=True)
Ejemplo n.º 19
0
    def __init__(self, parent, language=None, cmd='', host='127.0.0.1',
                 port=2084, args='', external=False, stdio=False,
                 configurations={}, **kwargs):
        super(LSPServerEditor, self).__init__(parent)

        description = _(
            "To create a new server configuration, you need to select a "
            "programming language, set the command to start its associated "
            "server and enter any arguments that should be passed to it on "
            "startup. Additionally, you can set the server's hostname and "
            "port if connecting to an external server, "
            "or to a local one using TCP instead of stdio pipes."
            "<br><br>"
            "<i>Note</i>: You can use the placeholders <tt>{host}</tt> and "
            "<tt>{port}</tt> in the server arguments field to automatically "
            "fill in the respective values.<br>"
        )
        self.parent = parent
        self.external = external

        # Widgets
        self.server_settings_description = QLabel(description)
        self.lang_cb = QComboBox(self)
        self.external_cb = QCheckBox(_('External server'), self)
        self.host_label = QLabel(_('Host:'))
        self.host_input = QLineEdit(self)
        self.port_label = QLabel(_('Port:'))
        self.port_spinner = QSpinBox(self)
        self.cmd_label = QLabel(_('Command:'))
        self.cmd_input = QLineEdit(self)
        self.args_label = QLabel(_('Arguments:'))
        self.args_input = QLineEdit(self)
        self.json_label = QLabel(self.JSON_VALID, self)
        self.conf_label = QLabel(_('<b>Server Configuration:</b>'))
        self.conf_input = CodeEditor(None)

        self.bbox = QDialogButtonBox(QDialogButtonBox.Ok |
                                     QDialogButtonBox.Cancel)
        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel)

        # Widget setup
        self.setMinimumSize(self.MIN_SIZE)
        self.setWindowTitle(_('LSP server editor'))

        self.server_settings_description.setWordWrap(True)

        self.lang_cb.setToolTip(
            _('Programming language provided by the LSP server'))
        self.lang_cb.addItem(_('Select a language'))
        self.lang_cb.addItems(LSP_LANGUAGES)

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

        self.host_input.setPlaceholderText('127.0.0.1')
        self.host_input.setText(host)
        self.host_input.textChanged.connect(lambda x: self.validate())

        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)

        self.cmd_input.setText(cmd)
        self.cmd_input.setPlaceholderText('/absolute/path/to/command')

        self.args_input.setToolTip(
            _('Additional arguments required to start the server'))
        self.args_input.setText(args)
        self.args_input.setPlaceholderText(r'--host {host} --port {port}')

        self.conf_input.setup_editor(
            language='json',
            color_scheme=CONF.get('appearance', 'selected'),
            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',
            folding=False
        )
        self.conf_input.set_language('json', 'config.json')
        self.conf_input.setToolTip(_('Additional LSP server configuration '
                                     'set at runtime. JSON required'))
        try:
            conf_text = json.dumps(configurations, indent=4, sort_keys=True)
        except Exception:
            conf_text = '{}'
        self.conf_input.set_text(conf_text)

        self.external_cb.setToolTip(
            _('Check if the server runs on a remote location'))
        self.external_cb.setChecked(external)

        self.stdio_cb = QCheckBox(_('Use stdio pipes for communication'), self)
        self.stdio_cb.setToolTip(_('Check if the server communicates '
                                   'using stdin/out pipes'))
        self.stdio_cb.setChecked(stdio)

        # Layout setup
        hlayout = QHBoxLayout()
        general_vlayout = QVBoxLayout()
        general_vlayout.addWidget(self.server_settings_description)

        vlayout = QVBoxLayout()

        lang_group = QGroupBox(_('Language'))
        lang_layout = QVBoxLayout()
        lang_layout.addWidget(self.lang_cb)
        lang_group.setLayout(lang_layout)
        vlayout.addWidget(lang_group)

        server_group = QGroupBox(_('Language server'))
        server_layout = QGridLayout()
        server_layout.addWidget(self.cmd_label, 0, 0)
        server_layout.addWidget(self.cmd_input, 0, 1)
        server_layout.addWidget(self.args_label, 1, 0)
        server_layout.addWidget(self.args_input, 1, 1)
        server_group.setLayout(server_layout)
        vlayout.addWidget(server_group)

        address_group = QGroupBox(_('Server address'))
        host_layout = QVBoxLayout()
        host_layout.addWidget(self.host_label)
        host_layout.addWidget(self.host_input)

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

        conn_info_layout = QHBoxLayout()
        conn_info_layout.addLayout(host_layout)
        conn_info_layout.addLayout(port_layout)
        address_group.setLayout(conn_info_layout)
        vlayout.addWidget(address_group)

        advanced_group = QGroupBox(_('Advanced'))
        advanced_layout = QVBoxLayout()
        advanced_layout.addWidget(self.external_cb)
        advanced_layout.addWidget(self.stdio_cb)
        advanced_group.setLayout(advanced_layout)
        vlayout.addWidget(advanced_group)

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

        vlayout.addStretch()
        hlayout.addLayout(vlayout, 2)
        hlayout.addLayout(conf_layout, 3)
        general_vlayout.addLayout(hlayout)

        general_vlayout.addWidget(self.bbox)
        self.setLayout(general_vlayout)
        self.form_status(False)

        # Signals
        if not external:
            self.cmd_input.textChanged.connect(lambda x: self.validate())
        self.external_cb.stateChanged.connect(self.set_local_options)
        self.stdio_cb.stateChanged.connect(self.set_stdio_options)
        self.lang_cb.currentIndexChanged.connect(self.lang_selection_changed)
        self.conf_input.textChanged.connect(self.validate)
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.reject)

        # Final setup
        if language is not None:
            self.form_status(True)
            self.validate()
            if stdio:
                self.set_stdio_options(True)
            if external:
                self.set_local_options(True)
Ejemplo n.º 20
0
def construct_editor(*args, **kwargs):
    app = qapplication()
    editor = CodeEditor(parent=None)
    kwargs['language'] = 'Python'
    editor.setup_editor(*args, **kwargs)
    return editor
Ejemplo n.º 21
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)

        description = _(
            'To create a new server configuration, you need to select a '
            'programming language and the server hostname/IP and port to '
            'use. If starting a local server, also provide the command to '
            'execute it and any arguments that should be passed on startup.'
            '<br><br>'
            'You can use the placeholders <tt>{host}</tt> and '
            '<tt>{port}</tt> in the server arguments field to '
            'automatically fill in the respective values.<br>')
        self.parent = parent
        self.external = external

        # Widgets
        self.server_settings_description = QLabel(description)
        self.lang_label = QLabel(_('Language:'))
        self.lang_cb = QComboBox(self)
        self.external_cb = QCheckBox(_('External server'), self)
        self.host_label = QLabel(_('Host:'))
        self.host_input = QLineEdit(self)
        self.port_label = QLabel(_('Port:'))
        self.port_spinner = QSpinBox(self)
        self.cmd_label = QLabel(_('Command to execute:'))
        self.cmd_input = QLineEdit(self)
        self.args_label = QLabel(_('Server arguments:'))
        self.args_input = QLineEdit(self)
        self.json_label = QLabel(self.JSON_VALID, self)
        self.conf_label = QLabel(_('LSP Server Configuration:'))
        self.conf_input = CodeEditor(None)

        self.bbox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel)

        # Widget setup
        self.setMinimumSize(self.MIN_SIZE)
        self.setWindowTitle(_('LSP server editor'))

        self.server_settings_description.setWordWrap(True)

        self.lang_cb.setToolTip(
            _('Programming language provided by the LSP server'))
        self.lang_cb.addItem(_('Select a language'))
        languages = LSP_LANGUAGES[:]
        # Even if users add a new Python config there, we will not use it
        languages.remove('Python')
        self.lang_cb.addItems(languages)

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

        self.host_input.setPlaceholderText('127.0.0.1')
        self.host_input.setText(host)
        self.host_input.textChanged.connect(lambda x: self.validate())

        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)

        self.cmd_input.setText(cmd)
        self.cmd_input.setPlaceholderText('/absolute/path/to/command')

        self.args_input.setToolTip(
            _('Additional arguments required to start the server'))
        self.args_input.setText(args)
        self.args_input.setPlaceholderText(r'--host {host} --port {port}')

        self.conf_input.setup_editor(
            language='json',
            color_scheme=CONF.get('appearance', 'selected'),
            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.set_language('json', 'config.json')
        self.conf_input.setToolTip(
            _('Additional LSP server configuration '
              'set at runtime. JSON required'))
        try:
            conf_text = json.dumps(configurations, indent=4, sort_keys=True)
        except Exception:
            conf_text = '{}'
        self.conf_input.set_text(conf_text)

        self.external_cb.setToolTip(
            _('Check if the server runs on a remote location'))
        self.external_cb.setChecked(external)

        # Layout setup
        hlayout = QHBoxLayout()
        general_vlayout = QVBoxLayout()
        general_vlayout.addWidget(self.server_settings_description)

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

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

        port_layout = QVBoxLayout()
        port_layout.addWidget(self.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(self.cmd_label)
        cmd_layout.addWidget(self.cmd_input)
        vlayout.addLayout(cmd_layout)

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

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

        vlayout.addStretch()
        hlayout.addLayout(vlayout, 1)
        hlayout.addLayout(conf_layout, 3)
        general_vlayout.addLayout(hlayout)

        general_vlayout.addWidget(self.bbox)
        self.setLayout(general_vlayout)
        self.form_status(False)

        # Signals
        if not external:
            self.cmd_input.textChanged.connect(lambda x: self.validate())
        self.external_cb.stateChanged.connect(self.set_local_options)
        self.lang_cb.currentIndexChanged.connect(self.lang_selection_changed)
        self.conf_input.textChanged.connect(self.validate)
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.reject)

        # Final setup
        if language is not None:
            self.form_status(True)
            self.validate()
Ejemplo n.º 22
0
    def setup_page(self):
        self.ICON = ima.icon('eyedropper')

        names = self.get_option("names")
        try:
            names.pop(names.index(u'Custom'))
        except ValueError:
            pass
        custom_names = self.get_option("custom_names", [])

        # Interface options
        theme_group = QGroupBox(_("Main interface"))

        # Interface Widgets
        ui_themes = ['Automatic', 'Light', 'Dark']
        ui_theme_choices = list(
            zip(ui_themes, [ui_theme.lower() for ui_theme in ui_themes]))
        ui_theme_combo = self.create_combobox(_('Interface theme'),
                                              ui_theme_choices,
                                              'ui_theme',
                                              restart=True)

        styles = [str(txt) for txt in list(QStyleFactory.keys())]
        # Don't offer users the possibility to change to a different
        # style in Gtk-based desktops
        # See spyder-ide/spyder#2036.
        if is_gtk_desktop() and ('GTK+' in styles):
            styles = ['GTK+']
        choices = list(zip(styles, [style.lower() for style in styles]))
        style_combo = self.create_combobox(_('Qt windows style'),
                                           choices,
                                           'windows_style',
                                           default=self.main.default_style)
        self.style_combobox = style_combo.combobox

        themes = ['Spyder 2', 'Spyder 3']
        icon_choices = list(zip(themes, [theme.lower() for theme in themes]))
        icons_combo = self.create_combobox(_('Icon theme'),
                                           icon_choices,
                                           'icon_theme',
                                           restart=True)

        theme_comboboxes_layout = QGridLayout()
        theme_comboboxes_layout.addWidget(ui_theme_combo.label, 0, 0)
        theme_comboboxes_layout.addWidget(ui_theme_combo.combobox, 0, 1)
        theme_comboboxes_layout.addWidget(style_combo.label, 1, 0)
        theme_comboboxes_layout.addWidget(self.style_combobox, 1, 1)
        theme_comboboxes_layout.addWidget(icons_combo.label, 2, 0)
        theme_comboboxes_layout.addWidget(icons_combo.combobox, 2, 1)

        theme_layout = QVBoxLayout()
        theme_layout.addLayout(theme_comboboxes_layout)
        theme_group.setLayout(theme_layout)

        # Syntax coloring options
        syntax_group = QGroupBox(_("Syntax highlighting theme"))

        # Syntax Widgets
        edit_button = QPushButton(_("Edit selected scheme"))
        create_button = QPushButton(_("Create new scheme"))
        self.delete_button = QPushButton(_("Delete scheme"))
        self.reset_button = QPushButton(_("Reset to defaults"))

        self.preview_editor = CodeEditor(self)
        self.stacked_widget = QStackedWidget(self)
        self.scheme_editor_dialog = SchemeEditor(parent=self,
                                                 stack=self.stacked_widget)

        self.scheme_choices_dict = {}
        schemes_combobox_widget = self.create_combobox('', [('', '')],
                                                       'selected')
        self.schemes_combobox = schemes_combobox_widget.combobox

        # Syntax layout
        syntax_layout = QGridLayout(syntax_group)
        btns = [
            self.schemes_combobox, edit_button, self.reset_button,
            create_button, self.delete_button
        ]
        for i, btn in enumerate(btns):
            syntax_layout.addWidget(btn, i, 1)
        syntax_layout.setColumnStretch(0, 1)
        syntax_layout.setColumnStretch(1, 2)
        syntax_layout.setColumnStretch(2, 1)
        syntax_layout.setContentsMargins(0, 12, 0, 12)

        # Fonts options
        fonts_group = QGroupBox(_("Fonts"))

        # Fonts widgets
        plain_text_font = self.create_fontgroup(
            option='font',
            title=_("Plain text"),
            fontfilters=QFontComboBox.MonospacedFonts,
            without_group=True)

        rich_text_font = self.create_fontgroup(option='rich_font',
                                               title=_("Rich text"),
                                               without_group=True)

        # Fonts layouts
        fonts_layout = QGridLayout(fonts_group)
        fonts_layout.addWidget(plain_text_font.fontlabel, 0, 0)
        fonts_layout.addWidget(plain_text_font.fontbox, 0, 1)
        fonts_layout.addWidget(plain_text_font.sizelabel, 0, 2)
        fonts_layout.addWidget(plain_text_font.sizebox, 0, 3)
        fonts_layout.addWidget(rich_text_font.fontlabel, 1, 0)
        fonts_layout.addWidget(rich_text_font.fontbox, 1, 1)
        fonts_layout.addWidget(rich_text_font.sizelabel, 1, 2)
        fonts_layout.addWidget(rich_text_font.sizebox, 1, 3)
        fonts_layout.setRowStretch(fonts_layout.rowCount(), 1)

        # Left options layout
        options_layout = QVBoxLayout()
        options_layout.addWidget(theme_group)
        options_layout.addWidget(syntax_group)
        options_layout.addWidget(fonts_group)

        # Right preview layout
        preview_group = QGroupBox(_("Preview"))
        preview_layout = QVBoxLayout()
        preview_layout.addWidget(self.preview_editor)
        preview_group.setLayout(preview_layout)

        # Combined layout
        combined_layout = QGridLayout()
        combined_layout.setRowStretch(0, 1)
        combined_layout.setColumnStretch(1, 100)
        combined_layout.addLayout(options_layout, 0, 0)
        combined_layout.addWidget(preview_group, 0, 1)
        self.setLayout(combined_layout)

        # Signals and slots
        create_button.clicked.connect(self.create_new_scheme)
        edit_button.clicked.connect(self.edit_scheme)
        self.reset_button.clicked.connect(self.reset_to_default)
        self.delete_button.clicked.connect(self.delete_scheme)
        self.schemes_combobox.currentIndexChanged.connect(self.update_preview)
        self.schemes_combobox.currentIndexChanged.connect(self.update_buttons)

        # Setup
        for name in names:
            self.scheme_editor_dialog.add_color_scheme_stack(name)

        for name in custom_names:
            self.scheme_editor_dialog.add_color_scheme_stack(name, custom=True)

        self.update_combobox()
        self.update_preview()
        self.update_qt_style_combobox()
Ejemplo n.º 23
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)s</tt> and '
                        '<tt>%(port)s</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('color_schemes', '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()
Ejemplo n.º 24
0
def code_editor():
    """setup editor and return fold levels."""
    editor = CodeEditor(parent=None)
    editor.setup_editor(language='Python')
    editor.set_text(text)
    return editor
Ejemplo n.º 25
0
            prev_text = ''
        text = block.text().strip()
        if text in self.open_chars:
            return TextBlockHelper.get_fold_lvl(prev_block) + 1
        if prev_text.endswith(self.open_chars) and prev_text not in \
                self.open_chars:
            return TextBlockHelper.get_fold_lvl(prev_block) + 1
        if self.close_chars in prev_text:
            return TextBlockHelper.get_fold_lvl(prev_block) - 1
        return TextBlockHelper.get_fold_lvl(prev_block)


if __name__ == '__main__':
    """Print folding blocks of this file for debugging"""
    from spyder.plugins.editor.api.folding import print_tree
    from spyder.utils.qthelpers import qapplication
    from spyder.plugins.editor.widgets.codeeditor import CodeEditor

    if len(sys.argv) > 1:
        fname = sys.argv[1]
    else:
        fname = __file__

    app = qapplication()
    editor = CodeEditor(parent=None)
    editor.setup_editor(language='Python')

    editor.set_text_from_file(fname)

    print_tree(editor)
Ejemplo n.º 26
0
    def _setup_views(self):
        """Creates the UI widgets."""
        self.central_splitter = QSplitter(self, orientation=Qt.Vertical)
        layout = create_plugin_layout(self.tools_layout, self.central_splitter)
        self.setLayout(layout)

        # Tree widget
        self.obj_tree = ToggleColumnTreeView(
            dataframe_format=self._dataframe_format)
        self.obj_tree.setAlternatingRowColors(True)
        self.obj_tree.setModel(self._proxy_tree_model)
        self.obj_tree.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.obj_tree.setUniformRowHeights(True)
        self.obj_tree.setAnimated(True)
        self.obj_tree.add_header_context_menu()
        self.obj_tree.sig_option_changed.connect(self.sig_option_changed.emit)

        # Stretch last column?
        # It doesn't play nice when columns are hidden and then shown again.
        obj_tree_header = self.obj_tree.header()
        obj_tree_header.setSectionsMovable(True)
        obj_tree_header.setStretchLastSection(False)
        add_actions(self.show_cols_submenu,
                    self.obj_tree.toggle_column_actions_group.actions())

        self.central_splitter.addWidget(self.obj_tree)

        # Bottom pane
        bottom_pane_widget = QWidget()
        bottom_layout = QHBoxLayout()
        bottom_layout.setSpacing(0)
        bottom_layout.setContentsMargins(5, 5, 5, 5)  # left top right bottom
        bottom_pane_widget.setLayout(bottom_layout)
        self.central_splitter.addWidget(bottom_pane_widget)

        group_box = QGroupBox(_("Details"))
        bottom_layout.addWidget(group_box)

        v_group_layout = QVBoxLayout()
        h_group_layout = QHBoxLayout()
        h_group_layout.setContentsMargins(2, 2, 2, 2)  # left top right bottom
        group_box.setLayout(v_group_layout)
        v_group_layout.addLayout(h_group_layout)

        # Radio buttons
        radio_widget = QWidget()
        radio_layout = QVBoxLayout()
        radio_layout.setContentsMargins(0, 0, 0, 0)  # left top right bottom
        radio_widget.setLayout(radio_layout)

        self.button_group = QButtonGroup(self)
        for button_id, attr_detail in enumerate(self._attr_details):
            radio_button = QRadioButton(attr_detail.name)
            radio_layout.addWidget(radio_button)
            self.button_group.addButton(radio_button, button_id)

        self.button_group.buttonClicked[int].connect(
            self._change_details_field)
        self.button_group.button(0).setChecked(True)

        radio_layout.addStretch(1)
        h_group_layout.addWidget(radio_widget)

        # Editor widget
        self.editor = CodeEditor(self)
        self.editor.setReadOnly(True)
        h_group_layout.addWidget(self.editor)

        # Warining label about repr
        repr_label = QLabel(
            _("(*) Some objects have very large repr's, "
              "which can freeze Spyder. Please use this "
              "with care."))
        v_group_layout.addWidget(repr_label)

        # Save and close buttons
        btn_layout = QHBoxLayout()
        btn_layout.addStretch()

        if not self.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)
        v_group_layout.addLayout(btn_layout)

        # Splitter parameters
        self.central_splitter.setCollapsible(0, False)
        self.central_splitter.setCollapsible(1, True)
        self.central_splitter.setSizes([500, 320])
        self.central_splitter.setStretchFactor(0, 10)
        self.central_splitter.setStretchFactor(1, 0)

        # Connect signals
        # Keep a temporary reference of the selection_model to prevent
        # segfault in PySide.
        # See http://permalink.gmane.org/gmane.comp.lib.qt.pyside.devel/222
        selection_model = self.obj_tree.selectionModel()
        selection_model.currentChanged.connect(self._update_details)

        # Check if the values of the model have been changed
        self._proxy_tree_model.sig_setting_data.connect(
            self.save_and_close_enable)

        self._proxy_tree_model.sig_update_details.connect(
            self._update_details_for_item)
Ejemplo n.º 27
0
"""


# ---- Qt Test Fixtures
@pytest.fixture
def create_outlineexplorer(qtbot):
    def _create_outlineexplorer(case, follow_cursor=False):
        case_info = CASES[case]
        filename = case_info['file']
        with open(case_info['file'], 'r') as f:
            text = f.read()

        symbol_info = json.load(open(case_info['data'], 'r'))
        expected_tree = json.load(open(case_info['tree'], 'r'))

        code_editor = CodeEditor(None)
        code_editor.set_language('py', filename)
        code_editor.set_text(text)

        editor = OutlineExplorerProxyEditor(code_editor, filename)

        outlineexplorer = OutlineExplorerWidget(follow_cursor=follow_cursor,
                                                display_variables=True,
                                                group_cells=True,
                                                show_comments=True)
        outlineexplorer.register_editor(editor)
        outlineexplorer.set_current_editor(editor, False, False)
        outlineexplorer.show()
        outlineexplorer.setFixedSize(400, 350)

        editor.update_outline_info(symbol_info)
Ejemplo n.º 28
0
def test_update_decorations_when_scrolling(qtbot):
    """
    Test how many calls we're doing to update decorations when
    scrolling.
    """
    # NOTE: Here we need to use `patch` from unittest.mock, instead of the
    # mocker fixture, to have the same results when running the test
    # alone and with the other tests in this file.

    patched_object = ('spyder.plugins.editor.utils.decoration.'
                      'TextDecorationsManager._update')

    with patch(patched_object) as _update:
        # NOTE: We can't use a fixture to build a CodeEditor instance here
        # because the testing results are not consistent.
        editor = CodeEditor(parent=None)
        editor.setup_editor(
            language='Python',
            color_scheme='spyder/dark',
            font=QFont("Monospace", 10),
        )
        editor.resize(640, 480)
        editor.show()
        qtbot.addWidget(editor)

        # If there's no waiting after CodeEditor is created, there shouldn't
        # be a call to _update.
        assert _update.call_count == 0

        with open(osp.join(PARENT, 'codeeditor.py'), 'r') as f:
            text = f.read()
        editor.set_text(text)

        # If there's no waiting after setting text, there shouldn't be a
        # call to _update either.
        assert _update.call_count == 0

        # Simulate scrolling
        scrollbar = editor.verticalScrollBar()
        for i in range(6):
            scrollbar.setValue(i * 70)
            qtbot.wait(100)

        # A new call is done here due to __cursor_position_changed being
        # called, which in turn calls highlight_current_cell and
        # highlight_current_line
        assert _update.call_count == 1

        # Wait for decorations to update
        qtbot.wait(editor.UPDATE_DECORATIONS_TIMEOUT + 100)

        # Assert a new call to _update was done
        assert _update.call_count == 2

        # Simulate grabbing and moving the scrollbar with the mouse
        scrollbar = editor.verticalScrollBar()
        value = scrollbar.value()
        for __ in range(400):
            scrollbar.setValue(value + 1)
            value = scrollbar.value()

        # No calls should be done after this.
        assert _update.call_count == 2

        # Wait for decorations to update
        qtbot.wait(editor.UPDATE_DECORATIONS_TIMEOUT + 100)

        # Assert a new call to _update was done
        assert _update.call_count == 3

        # Move to the last visible line
        _, last = editor.get_visible_block_numbers()
        editor.go_to_line(last)

        # Simulate continuously pressing the down arrow key.
        for __ in range(200):
            qtbot.keyPress(editor, Qt.Key_Down)
            if sys.platform.startswith('linux'):
                qtbot.wait(5)

        # Only one call to _update should be done, after releasing the key.
        qtbot.wait(editor.UPDATE_DECORATIONS_TIMEOUT + 100)
        assert _update.call_count == 4

        # Simulate continuously pressing the up arrow key.
        for __ in range(200):
            qtbot.keyPress(editor, Qt.Key_Up)
            if sys.platform.startswith('linux'):
                qtbot.wait(5)

        # Only one call to _update should be done, after releasing the key.
        qtbot.wait(editor.UPDATE_DECORATIONS_TIMEOUT + 100)
        assert _update.call_count == 5