1
# -*- coding: utf-8 -*-
3
# Copyright © 2009-2010 Pierre Raybaut
4
# Licensed under the terms of the MIT License
5
# (see spyderlib/__init__.py for details)
9
# pylint: disable=C0103
10
# pylint: disable=R0903
11
# pylint: disable=R0911
12
# pylint: disable=R0201
14
from spyderlib.qt.QtGui import (QVBoxLayout, QPrintDialog, QSplitter, QToolBar,
15
QAction, QApplication, QDialog, QWidget,
16
QPrinter, QActionGroup, QInputDialog, QMenu,
17
QAbstractPrintDialog, QGroupBox, QTabWidget,
18
QLabel, QFontComboBox, QHBoxLayout)
19
from spyderlib.qt.QtCore import SIGNAL, QByteArray, Qt, Slot
20
from spyderlib.qt.compat import to_qvariant, from_qvariant, getopenfilenames
28
from spyderlib.utils import encoding, sourcecode, codeanalysis
29
from spyderlib.baseconfig import get_conf_path, _
30
from spyderlib.config import get_icon, CONF, get_color_scheme, EDIT_FILTERS
31
from spyderlib.utils import programs
32
from spyderlib.utils.qthelpers import (create_action, add_actions,
33
get_std_icon, get_filetype_icon)
34
from spyderlib.widgets.findreplace import FindReplace
35
from spyderlib.widgets.editor import (ReadWriteStatus, EncodingStatus,
36
CursorPositionStatus, EOLStatus,
37
EditorSplitter, EditorStack, Printer,
39
from spyderlib.widgets.sourcecode.codeeditor import CodeEditor
40
from spyderlib.plugins import SpyderPluginWidget, PluginConfigPage
41
from spyderlib.plugins.runconfig import (RunConfigDialog, RunConfigOneDialog,
42
get_run_configuration)
45
def _load_all_breakpoints():
46
bp_dict = CONF.get('run', 'breakpoints', {})
47
for filename in bp_dict.keys():
48
if not osp.isfile(filename):
52
def load_breakpoints(filename):
53
breakpoints = _load_all_breakpoints().get(filename, [])
54
if breakpoints and isinstance(breakpoints[0], int):
55
# Old breakpoints format
56
breakpoints = [(lineno, None) for lineno in breakpoints]
59
def save_breakpoints(filename, breakpoints):
60
if not osp.isfile(filename):
62
bp_dict = _load_all_breakpoints()
63
bp_dict[filename] = breakpoints
64
CONF.set('run', 'breakpoints', bp_dict)
66
def clear_all_breakpoints():
67
CONF.set('run', 'breakpoints', {})
70
WINPDB_PATH = programs.find_program('winpdb')
73
class EditorConfigPage(PluginConfigPage):
74
def __init__(self, plugin, parent):
75
PluginConfigPage.__init__(self, plugin, parent)
76
self.get_name = lambda: _("Editor")
79
template_btn = self.create_button(_("Edit template for new modules"),
80
self.plugin.edit_template)
82
interface_group = QGroupBox(_("Interface"))
83
font_group = self.create_fontgroup(option=None,
84
text=_("Text and margin font style"),
85
fontfilters=QFontComboBox.MonospacedFonts)
86
newcb = self.create_checkbox
87
fpsorting_box = newcb(_("Sort files according to full path"),
89
showtabbar_box = newcb(_("Show tab bar"), 'show_tab_bar')
91
interface_layout = QVBoxLayout()
92
interface_layout.addWidget(fpsorting_box)
93
interface_layout.addWidget(showtabbar_box)
94
interface_group.setLayout(interface_layout)
96
display_group = QGroupBox(_("Source code"))
97
linenumbers_box = newcb(_("Show line numbers"), 'line_numbers')
98
edgeline_box = newcb(_("Show vertical line after"), 'edge_line')
99
edgeline_spin = self.create_spinbox("", _("characters"),
100
'edge_line_column', 79, 1, 500)
101
self.connect(edgeline_box, SIGNAL("toggled(bool)"),
102
edgeline_spin.setEnabled)
103
edgeline_spin.setEnabled(self.get_option('edge_line'))
104
edgeline_layout = QHBoxLayout()
105
edgeline_layout.addWidget(edgeline_box)
106
edgeline_layout.addWidget(edgeline_spin)
107
currentline_box = newcb(_("Highlight current line"),
108
'highlight_current_line', default=True)
109
occurence_box = newcb(_("Highlight occurences after"),
110
'occurence_highlighting', default=True)
111
occurence_spin = self.create_spinbox("", " ms",
112
'occurence_highlighting/timeout',
113
min_=100, max_=1000000, step=100)
114
self.connect(occurence_box, SIGNAL("toggled(bool)"),
115
occurence_spin.setEnabled)
116
occurence_spin.setEnabled(self.get_option('occurence_highlighting'))
117
occurence_layout = QHBoxLayout()
118
occurence_layout.addWidget(occurence_box)
119
occurence_layout.addWidget(occurence_spin)
120
wrap_mode_box = newcb(_("Wrap lines"), 'wrap')
121
names = CONF.get('color_schemes', 'names')
122
choices = zip(names, names)
123
cs_combo = self.create_combobox(_("Syntax color scheme: "),
124
choices, 'color_scheme_name')
126
display_layout = QVBoxLayout()
127
display_layout.addWidget(linenumbers_box)
128
display_layout.addLayout(edgeline_layout)
129
display_layout.addWidget(currentline_box)
130
display_layout.addLayout(occurence_layout)
131
display_layout.addWidget(wrap_mode_box)
132
display_layout.addWidget(cs_combo)
133
display_group.setLayout(display_layout)
135
run_group = QGroupBox(_("Run"))
136
saveall_box = newcb(_("Save all files before running script"),
137
'save_all_before_run', True)
139
introspection_group = QGroupBox(_("Introspection"))
140
rope_is_installed = programs.is_module_installed('rope')
141
if rope_is_installed:
142
completion_box = newcb(_("Automatic code completion"),
143
'codecompletion/auto')
144
case_comp_box = newcb(_("Case sensitive code completion"),
145
'codecompletion/case_sensitive')
146
show_single_box = newcb(_("Show single completion"),
147
'codecompletion/show_single')
148
comp_enter_box = newcb(_("Enter key selects completion"),
149
'codecompletion/enter_key')
150
calltips_box = newcb(_("Balloon tips"), 'calltips')
151
gotodef_box = newcb(_("Link to object definition"),
153
tip=_("If this option is enabled, clicking on an object\n"
154
"name (left-click + Ctrl key) will go this object\n"
155
"definition (if resolved)."))
156
inspector_box = newcb(
157
_("Automatic notification to object inspector"),
158
'object_inspector', default=True,
159
tip=_("If this option is enabled, object inspector\n"
160
"will automatically show informations on functions\n"
161
"entered in editor (this is triggered when entering\n"
162
"a left parenthesis after a valid function name)"))
164
rope_label = QLabel(_("<b>Warning:</b><br>"
165
"The Python module <i>rope</i> is not "
166
"installed on this computer: calltips, "
167
"code completion and go-to-definition "
168
"features won't be available."))
169
rope_label.setWordWrap(True)
171
sourcecode_group = QGroupBox(_("Source code"))
172
closepar_box = newcb(_("Automatic parentheses, braces and "
173
"brackets insertion"),
175
autounindent_box = newcb(_("Automatic indentation after 'else', "
176
"'elif', etc."), 'auto_unindent')
177
indent_chars_box = self.create_combobox(_("Indentation characters: "),
178
((_("4 spaces"), '* *'),
179
(_("2 spaces"), '* *'),
180
(_("tab"), '*\t*')), 'indent_chars')
181
tabwidth_spin = self.create_spinbox(_("Tab stop width:"), _("pixels"),
182
'tab_stop_width', 40, 10, 1000, 10)
183
tab_mode_box = newcb(_("Tab always indent"),
184
'tab_always_indent', default=False,
185
tip=_("If enabled, pressing Tab will always indent,\n"
186
"even when the cursor is not at the beginning\n"
187
"of a line (when this option is enabled, code\n"
188
"completion may be triggered using the alternate\n"
189
"shortcut: Ctrl+Space)"))
190
ibackspace_box = newcb(_("Intelligent backspace"),
191
'intelligent_backspace', default=True)
192
removetrail_box = newcb(_("Automatically remove trailing spaces "
193
"when saving files"),
194
'always_remove_trailing_spaces', default=False)
196
analysis_group = QGroupBox(_("Analysis"))
197
pep8_url = '<a href="http://www.python.org/dev/peps/pep-0008/">PEP8</a>'
198
analysis_label = QLabel(_("<u>Note</u>: add <b>analysis:ignore</b> in "
199
"a comment to ignore code/style analysis "
200
"warnings. For more informations on style "
201
"guide for Python code, please refer to the "
202
"%s page.") % pep8_url)
203
analysis_label.setWordWrap(True)
204
is_pyflakes = codeanalysis.is_pyflakes_installed()
205
is_pep8 = codeanalysis.get_checker_executable('pep8') is not None
206
analysis_label.setEnabled(is_pyflakes or is_pep8)
207
pyflakes_box = newcb(_("Code analysis")+" (pyflakes)",
208
'code_analysis/pyflakes', default=True,
209
tip=_("If enabled, Python source code will be analyzed\n"
210
"using pyflakes, lines containing errors or \n"
211
"warnings will be highlighted"))
212
pyflakes_box.setEnabled(is_pyflakes)
214
pyflakes_box.setToolTip(_("Code analysis requires pyflakes %s+") %
215
codeanalysis.PYFLAKES_REQVER)
216
pep8_box = newcb(_("Style analysis")+' (pep8)',
217
'code_analysis/pep8', default=False,
218
tip=_('If enabled, Python source code will be analyzed\n'
219
'using pep8, lines that are not following PEP8\n'
220
'style guide will be highlighted'))
221
pep8_box.setEnabled(is_pep8)
222
ancb_layout = QHBoxLayout()
223
ancb_layout.addWidget(pyflakes_box)
224
ancb_layout.addWidget(pep8_box)
225
todolist_box = newcb(_("Tasks (TODO, FIXME, XXX, HINT, TIP)"),
226
'todo_list', default=True)
227
realtime_radio = self.create_radiobutton(
228
_("Perform analysis when "
229
"saving file and every"),
230
'realtime_analysis', True)
231
saveonly_radio = self.create_radiobutton(
232
_("Perform analysis only "
234
'onsave_analysis', False)
235
af_spin = self.create_spinbox("", " ms", 'realtime_analysis/timeout',
236
min_=100, max_=1000000, step=100)
237
af_layout = QHBoxLayout()
238
af_layout.addWidget(realtime_radio)
239
af_layout.addWidget(af_spin)
241
run_layout = QVBoxLayout()
242
run_layout.addWidget(saveall_box)
243
run_group.setLayout(run_layout)
245
introspection_layout = QVBoxLayout()
246
if rope_is_installed:
247
introspection_layout.addWidget(calltips_box)
248
introspection_layout.addWidget(completion_box)
249
introspection_layout.addWidget(case_comp_box)
250
introspection_layout.addWidget(show_single_box)
251
introspection_layout.addWidget(comp_enter_box)
252
introspection_layout.addWidget(gotodef_box)
253
introspection_layout.addWidget(inspector_box)
255
introspection_layout.addWidget(rope_label)
256
introspection_group.setLayout(introspection_layout)
258
analysis_layout = QVBoxLayout()
259
analysis_layout.addWidget(analysis_label)
260
analysis_layout.addLayout(ancb_layout)
261
analysis_layout.addWidget(todolist_box)
262
analysis_layout.addLayout(af_layout)
263
analysis_layout.addWidget(saveonly_radio)
264
analysis_group.setLayout(analysis_layout)
266
sourcecode_layout = QVBoxLayout()
267
sourcecode_layout.addWidget(closepar_box)
268
sourcecode_layout.addWidget(autounindent_box)
269
sourcecode_layout.addWidget(indent_chars_box)
270
sourcecode_layout.addWidget(tabwidth_spin)
271
sourcecode_layout.addWidget(tab_mode_box)
272
sourcecode_layout.addWidget(ibackspace_box)
273
sourcecode_layout.addWidget(removetrail_box)
274
sourcecode_group.setLayout(sourcecode_layout)
276
eol_group = QGroupBox(_("End-of-line characters"))
277
eol_label = QLabel(_("When opening a text file containing "
278
"mixed end-of-line characters (this may "
279
"raise syntax errors in Python interpreter "
280
"on Windows platforms), Spyder may fix the "
281
"file automatically."))
282
eol_label.setWordWrap(True)
283
check_eol_box = newcb(_("Fix automatically and show warning "
285
'check_eol_chars', default=True)
287
eol_layout = QVBoxLayout()
288
eol_layout.addWidget(eol_label)
289
eol_layout.addWidget(check_eol_box)
290
eol_group.setLayout(eol_layout)
293
tabs.addTab(self.create_tab(font_group, interface_group, display_group),
295
tabs.addTab(self.create_tab(introspection_group, analysis_group),
296
_("Code Introspection/Analysis"))
297
tabs.addTab(self.create_tab(template_btn, run_group, sourcecode_group,
299
_("Advanced settings"))
301
vlayout = QVBoxLayout()
302
vlayout.addWidget(tabs)
303
self.setLayout(vlayout)
306
class Editor(SpyderPluginWidget):
308
Multi-file Editor widget
310
CONF_SECTION = 'editor'
311
CONFIGWIDGET_CLASS = EditorConfigPage
312
TEMPFILE_PATH = get_conf_path('.temp.py')
313
TEMPLATE_PATH = get_conf_path('template.py')
314
DISABLE_ACTIONS_WHEN_HIDDEN = False # SpyderPluginWidget class attribute
315
def __init__(self, parent, ignore_last_opened_files=False):
316
SpyderPluginWidget.__init__(self, parent)
318
self.__set_eol_chars = True
320
self.set_default_color_scheme()
322
# Creating template if it doesn't already exist
323
if not osp.isfile(self.TEMPLATE_PATH):
324
header = ['# -*- coding: utf-8 -*-', '"""', 'Created on %(date)s',
325
'', '@author: %(username)s', '"""', '']
326
encoding.write(os.linesep.join(header), self.TEMPLATE_PATH, 'utf-8')
328
self.projectexplorer = None
329
self.outlineexplorer = None
330
self.inspector = None
332
self.editorstacks = None
333
self.editorwindows = None
334
self.editorwindows_to_be_created = None
336
self.file_dependent_actions = []
337
self.pythonfile_dependent_actions = []
338
self.dock_toolbar_actions = None
339
self.edit_menu_actions = None #XXX: find another way to notify Spyder
340
# (see spyder.py: 'update_edit_menu' method)
341
self.search_menu_actions = None #XXX: same thing ('update_search_menu')
342
self.stack_menu_actions = None
345
self.initialize_plugin()
347
# Configuration dialog size
348
self.configdialog_size = None
350
statusbar = self.main.statusBar()
351
self.readwrite_status = ReadWriteStatus(self, statusbar)
352
self.eol_status = EOLStatus(self, statusbar)
353
self.encoding_status = EncodingStatus(self, statusbar)
354
self.cursorpos_status = CursorPositionStatus(self, statusbar)
356
layout = QVBoxLayout()
357
self.dock_toolbar = QToolBar(self)
358
add_actions(self.dock_toolbar, self.dock_toolbar_actions)
359
layout.addWidget(self.dock_toolbar)
361
self.last_edit_cursor_pos = None
362
self.cursor_pos_history = []
363
self.cursor_pos_index = None
364
self.__ignore_cursor_position = True
366
self.editorstacks = []
367
self.last_focus_editorstack = {}
368
self.editorwindows = []
369
self.editorwindows_to_be_created = []
370
self.toolbar_list = None
371
self.menu_list = None
374
self.connect(self.main, SIGNAL('all_actions_defined()'),
375
self.setup_other_windows)
378
self.find_widget = FindReplace(self, enable_replace=True)
379
self.find_widget.hide()
380
self.register_widget_shortcuts("Editor", self.find_widget)
382
# Tabbed editor widget + Find/Replace widget
383
editor_widgets = QWidget(self)
384
editor_layout = QVBoxLayout()
385
editor_layout.setContentsMargins(0, 0, 0, 0)
386
editor_widgets.setLayout(editor_layout)
387
self.editorsplitter = EditorSplitter(self, self,
388
self.stack_menu_actions, first=True)
389
editor_layout.addWidget(self.editorsplitter)
390
editor_layout.addWidget(self.find_widget)
392
# Splitter: editor widgets (see above) + outline explorer
393
self.splitter = QSplitter(self)
394
self.splitter.setContentsMargins(0, 0, 0, 0)
395
self.splitter.addWidget(editor_widgets)
396
self.splitter.setStretchFactor(0, 5)
397
self.splitter.setStretchFactor(1, 1)
398
layout.addWidget(self.splitter)
399
self.setLayout(layout)
401
# Editor's splitter state
402
state = self.get_option('splitter_state', None)
403
if state is not None:
404
self.splitter.restoreState( QByteArray().fromHex(str(state)) )
406
self.recent_files = self.get_option('recent_files', [])
408
self.untitled_num = 0
410
filenames = self.get_option('filenames', [])
411
if filenames and not ignore_last_opened_files:
413
layout = self.get_option('layout_settings', None)
414
if layout is not None:
415
self.editorsplitter.set_layout_settings(layout)
416
win_layout = self.get_option('windows_layout_settings', None)
418
for layout_settings in win_layout:
419
self.editorwindows_to_be_created.append(layout_settings)
420
self.set_last_focus_editorstack(self, self.editorstacks[0])
422
self.__load_temp_file()
424
# Parameters of last file execution:
425
self.__last_ic_exec = None # internal console
426
self.__last_ec_exec = None # external console
428
self.__ignore_cursor_position = False
429
current_editor = self.get_current_editor()
430
if current_editor is not None:
431
filename = self.get_current_filename()
432
position = current_editor.get_position('cursor')
433
self.add_cursor_position_to_history(filename, position)
434
self.update_cursorpos_actions()
436
def set_projectexplorer(self, projectexplorer):
437
self.projectexplorer = projectexplorer
439
def show_hide_project_explorer(self):
440
if self.projectexplorer is not None:
441
dw = self.projectexplorer.dockwidget
447
self.switch_to_plugin()
449
def set_outlineexplorer(self, outlineexplorer):
450
self.outlineexplorer = outlineexplorer
451
for editorstack in self.editorstacks:
452
editorstack.set_outlineexplorer(self.outlineexplorer)
453
self.connect(self.outlineexplorer,
454
SIGNAL("edit_goto(QString,int,QString)"),
455
lambda filenames, goto, word:
456
self.load(filenames=filenames, goto=goto, word=word,
459
def show_hide_outline_explorer(self):
460
if self.outlineexplorer is not None:
461
dw = self.outlineexplorer.dockwidget
467
self.switch_to_plugin()
469
def set_inspector(self, inspector):
470
self.inspector = inspector
471
for editorstack in self.editorstacks:
472
editorstack.set_inspector(self.inspector)
474
#------ Private API --------------------------------------------------------
475
def restore_scrollbar_position(self):
476
"""Restoring scrollbar position after main window is visible"""
477
# Widget is now visible, we may center cursor on top level editor:
478
self.get_current_editor().centerCursor()
480
#------ SpyderPluginWidget API ---------------------------------------------
481
def get_plugin_title(self):
482
"""Return widget title"""
484
filename = self.get_current_filename()
486
title += ' - '+unicode(filename)
489
def get_plugin_icon(self):
490
"""Return widget icon"""
491
return get_icon('edit.png')
493
def get_focus_widget(self):
495
Return the widget to give focus to when
496
this plugin's dockwidget is raised on top-level
498
return self.get_current_editor()
500
def visibility_changed(self, enable):
501
"""DockWidget visibility has changed"""
502
SpyderPluginWidget.visibility_changed(self, enable)
503
if self.dockwidget.isWindow():
504
self.dock_toolbar.show()
506
self.dock_toolbar.hide()
508
self.refresh_plugin()
510
def refresh_plugin(self):
511
"""Refresh editor plugin"""
512
editorstack = self.get_current_editorstack()
513
editorstack.refresh()
514
self.refresh_save_all_action()
516
def closing_plugin(self, cancelable=False):
517
"""Perform actions before parent main window is closed"""
518
state = self.splitter.saveState()
519
self.set_option('splitter_state', str(state.toHex()))
521
editorstack = self.editorstacks[0]
522
filenames += [finfo.filename for finfo in editorstack.data]
523
self.set_option('layout_settings',
524
self.editorsplitter.get_layout_settings())
525
self.set_option('windows_layout_settings',
526
[win.get_layout_settings() for win in self.editorwindows])
527
self.set_option('filenames', filenames)
528
self.set_option('recent_files', self.recent_files)
530
for editorstack in self.editorstacks:
531
is_ok = is_ok and editorstack.save_if_changed(cancelable)
532
if not is_ok and cancelable:
535
for win in self.editorwindows[:]:
539
def get_plugin_actions(self):
540
"""Return a list of actions related to plugin"""
541
self.toggle_outline_action = create_action(self,
542
_("Show/hide outline explorer"),
543
triggered=self.show_hide_outline_explorer,
544
context=Qt.WidgetWithChildrenShortcut)
545
self.register_shortcut(self.toggle_outline_action, context="Editor",
546
name="Show/hide outline", default="Ctrl+Alt+O")
547
self.toggle_project_action = create_action(self,
548
_("Show/hide project explorer"),
549
triggered=self.show_hide_project_explorer,
550
context=Qt.WidgetWithChildrenShortcut)
551
self.register_shortcut(self.toggle_project_action, context="Editor",
552
name="Show/hide project explorer",
553
default="Ctrl+Alt+P")
554
self.addActions([self.toggle_outline_action, self.toggle_project_action])
556
self.new_action = create_action(self, _("&New file..."),
557
icon='filenew.png', tip=_("Create a new Python script"),
559
self.register_shortcut(self.new_action, context="Editor",
560
name="New file", default="Ctrl+N")
561
self.open_action = create_action(self, _("&Open..."),
562
icon='fileopen.png', tip=_("Open text file"),
564
self.revert_action = create_action(self, _("&Revert"),
565
icon='revert.png', tip=_("Revert file from disk"),
566
triggered=self.revert)
567
self.register_shortcut(self.open_action, context="Editor",
568
name="Open file", default="Ctrl+O")
569
self.save_action = create_action(self, _("&Save"),
570
icon='filesave.png', tip=_("Save current file"),
572
self.register_shortcut(self.save_action, context="Editor",
573
name="Save file", default="Ctrl+S")
574
self.save_all_action = create_action(self, _("Sav&e all"),
575
icon='save_all.png', tip=_("Save all opened files"),
576
triggered=self.save_all)
577
self.register_shortcut(self.save_all_action, context="Editor",
578
name="Save all", default="Ctrl+Shift+S")
579
save_as_action = create_action(self, _("Save &as..."), None,
580
'filesaveas.png', _("Save current file as..."),
581
triggered=self.save_as)
582
print_preview_action = create_action(self, _("Print preview..."),
583
tip=_("Print preview..."), triggered=self.print_preview)
584
self.print_action = create_action(self, _("&Print..."),
585
icon='print.png', tip=_("Print current file..."),
586
triggered=self.print_file)
587
self.register_shortcut(self.print_action, context="Editor",
588
name="Print", default="Ctrl+P")
589
self.close_action = create_action(self, _("&Close"),
590
icon='fileclose.png', tip=_("Close current file"),
591
triggered=self.close_file)
592
self.register_shortcut(self.close_action, context="Editor",
593
name="Close file", default="Ctrl+W")
594
self.close_all_action = create_action(self, _("C&lose all"),
595
icon='filecloseall.png', tip=_("Close all opened files"),
596
triggered=self.close_all_files)
597
self.register_shortcut(self.close_all_action, context="Editor",
598
name="Close all", default="Ctrl+Shift+W")
600
set_clear_breakpoint_action = create_action(self,
601
_("Set/Clear breakpoint"),
602
icon=get_icon("breakpoint.png"),
603
triggered=self.set_or_clear_breakpoint,
604
context=Qt.WidgetShortcut)
605
self.register_shortcut(set_clear_breakpoint_action, context="Editor",
606
name="Breakpoint", default="F12")
607
set_cond_breakpoint_action = create_action(self,
608
_("Set/Edit conditional breakpoint"),
609
icon=get_icon("breakpoint_cond.png"),
610
triggered=self.set_or_edit_conditional_breakpoint,
611
context=Qt.WidgetShortcut)
612
self.register_shortcut(set_cond_breakpoint_action, context="Editor",
613
name="Conditional breakpoint",
615
clear_all_breakpoints_action = create_action(self,
616
_("Clear breakpoints in all files"),
617
triggered=self.clear_all_breakpoints)
618
breakpoints_menu = QMenu(_("Breakpoints"), self)
619
add_actions(breakpoints_menu, (set_clear_breakpoint_action,
620
set_cond_breakpoint_action, None,
621
clear_all_breakpoints_action))
623
run_action = create_action(self, _("&Run"), icon='run.png',
624
tip=_("Run active script in a new Python interpreter"),
625
triggered=self.run_file)
626
self.register_shortcut(run_action, context="Editor",
627
name="Run", default="F5")
628
debug_action = create_action(self, _("&Debug"), icon='bug.png',
629
tip=_("Debug current script in external console"
630
"\n(external console is executed in a "
631
"separate process)"),
632
triggered=self.debug_file)
633
self.register_shortcut(debug_action, context="Editor",
634
name="Debug", default="Ctrl+F5")
635
configure_action = create_action(self,
636
_("&Configure..."), icon='configure.png',
637
tip=_("Edit run configurations"), menurole=QAction.NoRole,
638
triggered=self.edit_run_configurations)
639
self.register_shortcut(configure_action, context="Editor",
640
name="Configure", default="F6")
641
re_run_action = create_action(self,
642
_("Re-run &last script"), icon='run_again.png',
643
tip=_("Run again last script in external console "
644
"with the same options"),
645
triggered=self.re_run_file)
646
self.register_shortcut(re_run_action, context="Editor",
647
name="Re-run last script", default="Ctrl+F6")
649
run_selected_action = create_action(self,
650
_("Run &selection or current block"),
651
icon='run_selection.png',
652
tip=_("Run selected text or current block of lines \n"
653
"inside current external console's interpreter"),
654
triggered=self.run_selection_or_block)
655
self.register_shortcut(run_selected_action, context="Editor",
656
name="Run selection", default="F9")
658
self.todo_list_action = create_action(self,
659
_("Show todo list"), icon='todo_list.png',
660
tip=_("Show TODO/FIXME/XXX/HINT/TIP comments list"),
661
triggered=self.go_to_next_todo)
662
self.todo_menu = QMenu(self)
663
self.todo_list_action.setMenu(self.todo_menu)
664
self.connect(self.todo_menu, SIGNAL("aboutToShow()"),
665
self.update_todo_menu)
667
self.warning_list_action = create_action(self,
668
_("Show warning/error list"), icon='wng_list.png',
669
tip=_("Show code analysis warnings/errors"),
670
triggered=self.go_to_next_warning)
671
self.warning_menu = QMenu(self)
672
self.warning_list_action.setMenu(self.warning_menu)
673
self.connect(self.warning_menu, SIGNAL("aboutToShow()"),
674
self.update_warning_menu)
675
self.previous_warning_action = create_action(self,
676
_("Previous warning/error"), icon='prev_wng.png',
677
tip=_("Go to previous code analysis warning/error"),
678
triggered=self.go_to_previous_warning)
679
self.next_warning_action = create_action(self,
680
_("Next warning/error"), icon='next_wng.png',
681
tip=_("Go to next code analysis warning/error"),
682
triggered=self.go_to_next_warning)
684
self.previous_edit_cursor_action = create_action(self,
685
_("Last edit location"), icon='last_edit_location.png',
686
tip=_("Go to last edit location"),
687
triggered=self.go_to_last_edit_location)
688
self.register_shortcut(self.previous_edit_cursor_action,
690
name="Last edit location",
691
default="Ctrl+Alt+Shift+Left")
692
self.previous_cursor_action = create_action(self,
693
_("Previous cursor position"), icon='prev_cursor.png',
694
tip=_("Go to previous cursor position"),
695
triggered=self.go_to_previous_cursor_position)
696
self.register_shortcut(self.previous_cursor_action,
698
name="Previous cursor position",
699
default="Ctrl+Alt+Left")
700
self.next_cursor_action = create_action(self,
701
_("Next cursor position"), icon='next_cursor.png',
702
tip=_("Go to next cursor position"),
703
triggered=self.go_to_next_cursor_position)
704
self.register_shortcut(self.next_cursor_action,
705
context="Editor", name="Next cursor position",
706
default="Ctrl+Alt+Right")
708
self.toggle_comment_action = create_action(self,
709
_("Comment")+"/"+_("Uncomment"), icon='comment.png',
710
tip=_("Comment current line or selection"),
711
triggered=self.toggle_comment, context=Qt.WidgetShortcut)
712
self.register_shortcut(self.toggle_comment_action, context="Editor",
713
name="Toggle comment", default="Ctrl+1")
714
blockcomment_action = create_action(self, _("Add &block comment"),
715
tip=_("Add block comment around "
716
"current line or selection"),
717
triggered=self.blockcomment, context=Qt.WidgetShortcut)
718
self.register_shortcut(blockcomment_action, context="Editor",
719
name="Blockcomment", default="Ctrl+4")
720
unblockcomment_action = create_action(self,
721
_("R&emove block comment"),
722
tip = _("Remove comment block around "
723
"current line or selection"),
724
triggered=self.unblockcomment, context=Qt.WidgetShortcut)
725
self.register_shortcut(unblockcomment_action, context="Editor",
726
name="Unblockcomment", default="Ctrl+5")
728
# ----------------------------------------------------------------------
729
# The following action shortcuts are hard-coded in CodeEditor
730
# keyPressEvent handler (the shortcut is here only to inform user):
731
# (context=Qt.WidgetShortcut -> disable shortcut for other widgets)
732
self.indent_action = create_action(self,
733
_("Indent"), "Tab", icon='indent.png',
734
tip=_("Indent current line or selection"),
735
triggered=self.indent, context=Qt.WidgetShortcut)
736
self.unindent_action = create_action(self,
737
_("Unindent"), "Shift+Tab", icon='unindent.png',
738
tip=_("Unindent current line or selection"),
739
triggered=self.unindent, context=Qt.WidgetShortcut)
740
# ----------------------------------------------------------------------
742
self.winpdb_action = create_action(self, _("Debug with winpdb"),
743
triggered=self.run_winpdb)
744
self.winpdb_action.setEnabled(WINPDB_PATH is not None)
745
self.register_shortcut(self.winpdb_action, context="Editor",
746
name="Debug with winpdb", default="F7")
748
self.win_eol_action = create_action(self,
749
_("Carriage return and line feed (Windows)"),
750
toggled=lambda: self.toggle_eol_chars('nt'))
751
self.linux_eol_action = create_action(self,
752
_("Line feed (UNIX)"),
753
toggled=lambda: self.toggle_eol_chars('posix'))
754
self.mac_eol_action = create_action(self,
755
_("Carriage return (Mac)"),
756
toggled=lambda: self.toggle_eol_chars('mac'))
757
eol_action_group = QActionGroup(self)
758
eol_actions = (self.win_eol_action, self.linux_eol_action,
760
add_actions(eol_action_group, eol_actions)
761
eol_menu = QMenu(_("Convert end-of-line characters"), self)
762
add_actions(eol_menu, eol_actions)
764
trailingspaces_action = create_action(self,
765
_("Remove trailing spaces"),
766
triggered=self.remove_trailing_spaces)
767
fixindentation_action = create_action(self, _("Fix indentation"),
768
tip=_("Replace tab characters by space characters"),
769
triggered=self.fix_indentation)
771
gotoline_action = create_action(self, _("Go to line..."),
772
icon=get_icon("gotoline.png"),
773
triggered=self.go_to_line,
774
context=Qt.WidgetShortcut)
775
self.register_shortcut(gotoline_action, context="Editor",
776
name="Go to line", default="Ctrl+L")
778
workdir_action = create_action(self,
779
_("Set console working directory"),
780
icon=get_std_icon('DirOpenIcon'),
781
tip=_("Set current console (and file explorer) working "
782
"directory to current script directory"),
783
triggered=self.__set_workdir)
785
self.max_recent_action = create_action(self,
786
_("Maximum number of recent files..."),
787
triggered=self.change_max_recent_files)
788
self.clear_recent_action = create_action(self,
789
_("Clear this list"), tip=_("Clear recent files list"),
790
triggered=self.clear_recent_files)
791
self.recent_file_menu = QMenu(_("Open &recent"), self)
792
self.connect(self.recent_file_menu, SIGNAL("aboutToShow()"),
793
self.update_recent_file_menu)
795
file_menu_actions = [self.new_action, self.open_action,
796
self.recent_file_menu, self.save_action,
797
self.save_all_action, save_as_action,
799
None, print_preview_action, self.print_action,
800
None, self.close_action,
801
self.close_all_action, None]
802
self.main.file_menu_actions += file_menu_actions
803
file_toolbar_actions = [self.new_action, self.open_action,
804
self.save_action, self.save_all_action,
806
self.main.file_toolbar_actions += file_toolbar_actions
808
self.edit_menu_actions = [self.toggle_comment_action,
809
blockcomment_action, unblockcomment_action,
810
self.indent_action, self.unindent_action]
811
self.main.edit_menu_actions += [None]+self.edit_menu_actions
812
edit_toolbar_actions = [self.toggle_comment_action,
813
self.unindent_action, self.indent_action]
814
self.main.edit_toolbar_actions += edit_toolbar_actions
816
self.search_menu_actions = [gotoline_action]
817
self.main.search_menu_actions += self.search_menu_actions
818
self.main.search_toolbar_actions += [gotoline_action]
820
run_menu_actions = [run_action, debug_action, configure_action,
821
breakpoints_menu, None,
822
re_run_action, run_selected_action, None,
824
self.main.run_menu_actions += run_menu_actions
825
run_toolbar_actions = [run_action, debug_action, configure_action,
826
run_selected_action, re_run_action]
827
self.main.run_toolbar_actions += run_toolbar_actions
829
source_menu_actions = [eol_menu, trailingspaces_action,
830
fixindentation_action]
831
self.main.source_menu_actions += source_menu_actions
833
source_toolbar_actions = [self.todo_list_action,
834
self.warning_list_action, self.previous_warning_action,
835
self.next_warning_action, None,
836
self.previous_edit_cursor_action,
837
self.previous_cursor_action, self.next_cursor_action]
838
self.main.source_toolbar_actions += source_toolbar_actions
840
self.dock_toolbar_actions = file_toolbar_actions + [None] + \
841
source_toolbar_actions + [None] + \
842
run_toolbar_actions + [None] + \
844
self.pythonfile_dependent_actions = [run_action, configure_action,
845
set_clear_breakpoint_action, set_cond_breakpoint_action,
846
debug_action, re_run_action, run_selected_action,
847
blockcomment_action, unblockcomment_action, self.winpdb_action]
848
self.file_dependent_actions = self.pythonfile_dependent_actions + \
849
[self.save_action, save_as_action, print_preview_action,
850
self.print_action, self.save_all_action, gotoline_action,
851
workdir_action, self.close_action, self.close_all_action,
852
self.toggle_comment_action, self.revert_action,
853
self.indent_action, self.unindent_action]
854
self.stack_menu_actions = [self.save_action, save_as_action,
855
self.print_action, None, run_action, debug_action,
856
configure_action, None, gotoline_action,
857
workdir_action, None, self.close_action]
859
return self.file_dependent_actions
861
def register_plugin(self):
862
"""Register plugin in Spyder's main window"""
863
self.connect(self.main, SIGNAL('restore_scrollbar_position()'),
864
self.restore_scrollbar_position)
865
self.connect(self.main.console,
866
SIGNAL("edit_goto(QString,int,QString)"), self.load)
867
self.connect(self, SIGNAL('external_console_execute_lines(QString)'),
868
self.main.execute_python_code_in_external_console)
869
self.connect(self, SIGNAL('redirect_stdio(bool)'),
870
self.main.redirect_internalshell_stdio)
871
self.connect(self, SIGNAL("open_dir(QString)"),
872
self.main.workingdirectory.chdir)
873
self.set_inspector(self.main.inspector)
874
if self.main.outlineexplorer is not None:
875
self.set_outlineexplorer(self.main.outlineexplorer)
876
self.main.add_dockwidget(self)
879
#------ Focus tabwidget
880
def __get_focus_editorstack(self):
881
fwidget = QApplication.focusWidget()
882
if isinstance(fwidget, EditorStack):
885
for editorstack in self.editorstacks:
886
if editorstack.isAncestorOf(fwidget):
889
def set_last_focus_editorstack(self, editorwindow, editorstack):
890
self.last_focus_editorstack[editorwindow] = editorstack
891
self.last_focus_editorstack[None] = editorstack # very last editorstack
893
def get_last_focus_editorstack(self, editorwindow=None):
894
return self.last_focus_editorstack[editorwindow]
896
def remove_last_focus_editorstack(self, editorstack):
897
for editorwindow, widget in self.last_focus_editorstack.items():
898
if widget is editorstack:
899
self.last_focus_editorstack[editorwindow] = None
901
def save_focus_editorstack(self):
902
editorstack = self.__get_focus_editorstack()
903
if editorstack is not None:
904
for win in [self]+self.editorwindows:
905
if win.isAncestorOf(editorstack):
906
self.set_last_focus_editorstack(win, editorstack)
909
#------ Handling editorstacks
910
def register_editorstack(self, editorstack):
911
self.editorstacks.append(editorstack)
913
self.register_widget_shortcuts("Editor", editorstack)
915
if self.isAncestorOf(editorstack):
916
# editorstack is a child of the Editor plugin
917
self.set_last_focus_editorstack(self, editorstack)
918
editorstack.set_closable( len(self.editorstacks) > 1 )
919
if self.outlineexplorer is not None:
920
editorstack.set_outlineexplorer(self.outlineexplorer)
921
editorstack.set_find_widget(self.find_widget)
922
self.connect(editorstack, SIGNAL('reset_statusbar()'),
923
self.readwrite_status.hide)
924
self.connect(editorstack, SIGNAL('reset_statusbar()'),
925
self.encoding_status.hide)
926
self.connect(editorstack, SIGNAL('reset_statusbar()'),
927
self.cursorpos_status.hide)
928
self.connect(editorstack, SIGNAL('readonly_changed(bool)'),
929
self.readwrite_status.readonly_changed)
930
self.connect(editorstack, SIGNAL('encoding_changed(QString)'),
931
self.encoding_status.encoding_changed)
932
self.connect(editorstack,
933
SIGNAL('editor_cursor_position_changed(int,int)'),
934
self.cursorpos_status.cursor_position_changed)
935
self.connect(editorstack, SIGNAL('refresh_eol_chars(QString)'),
936
self.eol_status.eol_changed)
938
editorstack.set_inspector(self.inspector)
939
editorstack.set_io_actions(self.new_action, self.open_action,
940
self.save_action, self.revert_action)
941
editorstack.set_tempfile_path(self.TEMPFILE_PATH)
943
('set_pyflakes_enabled', 'code_analysis/pyflakes'),
944
('set_pep8_enabled', 'code_analysis/pep8'),
945
('set_todolist_enabled', 'todo_list'),
946
('set_realtime_analysis_enabled', 'realtime_analysis'),
947
('set_realtime_analysis_timeout', 'realtime_analysis/timeout'),
948
('set_linenumbers_enabled', 'line_numbers'),
949
('set_edgeline_enabled', 'edge_line'),
950
('set_edgeline_column', 'edge_line_column'),
951
('set_outlineexplorer_enabled', 'outline_explorer'),
952
('set_codecompletion_auto_enabled', 'codecompletion/auto'),
953
('set_codecompletion_case_enabled', 'codecompletion/case_sensitive'),
954
('set_codecompletion_single_enabled', 'codecompletion/show_single'),
955
('set_codecompletion_enter_enabled', 'codecompletion/enter_key'),
956
('set_calltips_enabled', 'calltips'),
957
('set_go_to_definition_enabled', 'go_to_definition'),
958
('set_close_parentheses_enabled', 'close_parentheses'),
959
('set_auto_unindent_enabled', 'auto_unindent'),
960
('set_indent_chars', 'indent_chars'),
961
('set_tab_stop_width', 'tab_stop_width'),
962
('set_inspector_enabled', 'object_inspector'),
963
('set_wrap_enabled', 'wrap'),
964
('set_tabmode_enabled', 'tab_always_indent'),
965
('set_intelligent_backspace_enabled', 'intelligent_backspace'),
966
('set_highlight_current_line_enabled', 'highlight_current_line'),
967
('set_occurence_highlighting_enabled', 'occurence_highlighting'),
968
('set_occurence_highlighting_timeout', 'occurence_highlighting/timeout'),
969
('set_checkeolchars_enabled', 'check_eol_chars'),
970
('set_fullpath_sorting_enabled', 'fullpath_sorting'),
971
('set_tabbar_visible', 'show_tab_bar'),
972
('set_always_remove_trailing_spaces', 'always_remove_trailing_spaces'),
974
for method, setting in settings:
975
getattr(editorstack, method)(self.get_option(setting))
976
color_scheme = get_color_scheme(self.get_option('color_scheme_name'))
977
editorstack.set_default_font(self.get_plugin_font(), color_scheme)
979
self.connect(editorstack, SIGNAL('starting_long_process(QString)'),
980
self.starting_long_process)
981
self.connect(editorstack, SIGNAL('ending_long_process(QString)'),
982
self.ending_long_process)
985
self.connect(editorstack, SIGNAL('redirect_stdio(bool)'),
987
self.emit(SIGNAL('redirect_stdio(bool)'), state))
988
self.connect(editorstack,
989
SIGNAL('external_console_execute_lines(QString)'),
990
lambda text: self.emit(
991
SIGNAL('external_console_execute_lines(QString)'), text))
992
self.connect(editorstack, SIGNAL("update_plugin_title()"),
993
lambda: self.emit(SIGNAL("update_plugin_title()")))
995
self.connect(editorstack, SIGNAL("editor_focus_changed()"),
996
self.save_focus_editorstack)
997
self.connect(editorstack, SIGNAL('editor_focus_changed()'),
998
self.main.plugin_focus_changed)
1000
self.connect(editorstack, SIGNAL('close_file(long,long)'),
1001
self.close_file_in_all_editorstacks)
1002
self.connect(editorstack, SIGNAL('file_saved(long,long)'),
1003
self.file_saved_in_editorstack)
1005
self.connect(editorstack, SIGNAL("create_new_window()"),
1006
self.create_new_window)
1008
self.connect(editorstack, SIGNAL('opened_files_list_changed()'),
1009
self.opened_files_list_changed)
1010
self.connect(editorstack, SIGNAL('analysis_results_changed()'),
1011
self.analysis_results_changed)
1012
self.connect(editorstack, SIGNAL('todo_results_changed()'),
1013
self.todo_results_changed)
1014
self.connect(editorstack, SIGNAL('update_code_analysis_actions()'),
1015
self.update_code_analysis_actions)
1016
self.connect(editorstack, SIGNAL('update_code_analysis_actions()'),
1017
self.update_todo_actions)
1018
self.connect(editorstack,
1019
SIGNAL('refresh_file_dependent_actions()'),
1020
self.refresh_file_dependent_actions)
1021
self.connect(editorstack, SIGNAL('refresh_save_all_action()'),
1022
self.refresh_save_all_action)
1023
self.connect(editorstack, SIGNAL('refresh_eol_chars(QString)'),
1024
self.refresh_eol_chars)
1026
self.connect(editorstack, SIGNAL("save_breakpoints(QString,QString)"),
1027
self.save_breakpoints)
1029
self.connect(editorstack, SIGNAL('text_changed_at(QString,int)'),
1030
self.text_changed_at)
1031
self.connect(editorstack, SIGNAL('current_file_changed(QString,int)'),
1032
self.current_file_changed)
1034
self.connect(editorstack, SIGNAL('plugin_load(QString)'), self.load)
1035
self.connect(editorstack, SIGNAL("edit_goto(QString,int,QString)"),
1038
def unregister_editorstack(self, editorstack):
1039
"""Removing editorstack only if it's not the last remaining"""
1040
self.remove_last_focus_editorstack(editorstack)
1041
if len(self.editorstacks) > 1:
1042
index = self.editorstacks.index(editorstack)
1043
self.editorstacks.pop(index)
1046
# editorstack was not removed!
1049
def clone_editorstack(self, editorstack):
1050
editorstack.clone_from(self.editorstacks[0])
1051
for finfo in editorstack.data:
1052
self.register_widget_shortcuts("Editor", finfo.editor)
1055
def close_file_in_all_editorstacks(self, editorstack_id, index):
1056
for editorstack in self.editorstacks:
1057
if id(editorstack) != editorstack_id:
1058
editorstack.blockSignals(True)
1059
editorstack.close_file(index, force=True)
1060
editorstack.blockSignals(False)
1063
def file_saved_in_editorstack(self, editorstack_id, index):
1064
"""A file was saved in editorstack, this notifies others"""
1065
for editorstack in self.editorstacks:
1066
if id(editorstack) != editorstack_id:
1067
editorstack.file_saved_in_other_editorstack(index)
1070
#------ Handling editor windows
1071
def setup_other_windows(self):
1072
"""Setup toolbars and menus for 'New window' instances"""
1073
self.toolbar_list = (
1074
(_("File toolbar"), self.main.file_toolbar_actions),
1075
(_("Search toolbar"), self.main.search_menu_actions),
1076
(_("Source toolbar"), self.main.source_toolbar_actions),
1077
(_("Run toolbar"), self.main.run_toolbar_actions),
1078
(_("Edit toolbar"), self.main.edit_toolbar_actions),
1081
(_("&File"), self.main.file_menu_actions),
1082
(_("&Edit"), self.main.edit_menu_actions),
1083
(_("&Search"), self.main.search_menu_actions),
1084
(_("Sour&ce"), self.main.source_menu_actions),
1085
(_("&Run"), self.main.run_menu_actions),
1086
(_("&Tools"), self.main.tools_menu_actions),
1087
(_("?"), self.main.help_menu_actions),
1089
# Create pending new windows:
1090
for layout_settings in self.editorwindows_to_be_created:
1091
win = self.create_new_window()
1092
win.set_layout_settings(layout_settings)
1094
def create_new_window(self):
1095
oe_options = self.outlineexplorer.get_options()
1096
fullpath_sorting=self.get_option('fullpath_sorting', True),
1097
window = EditorMainWindow(self, self.stack_menu_actions,
1098
self.toolbar_list, self.menu_list,
1099
show_fullpath=oe_options['show_fullpath'],
1100
fullpath_sorting=fullpath_sorting,
1101
show_all_files=oe_options['show_all_files'],
1102
show_comments=oe_options['show_comments'])
1103
window.resize(self.size())
1105
self.register_editorwindow(window)
1106
self.connect(window, SIGNAL("destroyed()"),
1107
lambda win=window: self.unregister_editorwindow(win))
1110
def register_editorwindow(self, window):
1111
self.editorwindows.append(window)
1113
def unregister_editorwindow(self, window):
1114
self.editorwindows.pop(self.editorwindows.index(window))
1118
def get_filenames(self):
1119
return [finfo.filename for finfo in self.editorstacks[0].data]
1121
def get_filename_index(self, filename):
1122
return self.editorstacks[0].has_filename(filename)
1124
def get_current_editorstack(self, editorwindow=None):
1125
if self.editorstacks is not None:
1126
if len(self.editorstacks) == 1:
1127
return self.editorstacks[0]
1129
editorstack = self.__get_focus_editorstack()
1130
if editorstack is None or editorwindow is not None:
1131
return self.get_last_focus_editorstack(editorwindow)
1134
def get_current_editor(self):
1135
editorstack = self.get_current_editorstack()
1136
if editorstack is not None:
1137
return editorstack.get_current_editor()
1139
def get_current_finfo(self):
1140
editorstack = self.get_current_editorstack()
1141
if editorstack is not None:
1142
return editorstack.get_current_finfo()
1144
def get_current_filename(self):
1145
editorstack = self.get_current_editorstack()
1146
if editorstack is not None:
1147
return editorstack.get_current_filename()
1149
def is_file_opened(self, filename=None):
1150
return self.editorstacks[0].is_file_opened(filename)
1152
def set_current_filename(self, filename, editorwindow=None):
1153
"""Set focus to *filename* if this file has been opened
1154
Return the editor instance associated to *filename*"""
1155
editorstack = self.get_current_editorstack(editorwindow)
1156
return editorstack.set_current_filename(filename)
1159
#------ Refresh methods
1160
def refresh_file_dependent_actions(self):
1161
"""Enable/disable file dependent actions
1162
(only if dockwidget is visible)"""
1163
if self.dockwidget and self.dockwidget.isVisible():
1164
enable = self.get_current_editor() is not None
1165
for action in self.file_dependent_actions:
1166
action.setEnabled(enable)
1168
def refresh_save_all_action(self):
1170
editorstack = self.editorstacks[0]
1171
if editorstack.get_stack_count() > 1:
1172
state = state or any([finfo.editor.document().isModified()
1173
for finfo in editorstack.data])
1174
self.save_all_action.setEnabled(state)
1176
def update_warning_menu(self):
1177
"""Update warning list menu"""
1178
editorstack = self.get_current_editorstack()
1179
check_results = editorstack.get_analysis_results()
1180
self.warning_menu.clear()
1181
filename = self.get_current_filename()
1182
for message, line_number in check_results:
1183
error = 'syntax' in message
1184
text = message[:1].upper()+message[1:]
1185
icon = get_icon('error.png' if error else 'warning.png')
1186
slot = lambda _l=line_number: self.load(filename, goto=_l)
1187
action = create_action(self, text=text, icon=icon, triggered=slot)
1188
self.warning_menu.addAction(action)
1190
def analysis_results_changed(self):
1192
Synchronize analysis results between editorstacks
1193
Refresh analysis navigation buttons
1195
editorstack = self.get_current_editorstack()
1196
results = editorstack.get_analysis_results()
1197
index = editorstack.get_stack_index()
1199
for other_editorstack in self.editorstacks:
1200
if other_editorstack is not editorstack:
1201
other_editorstack.set_analysis_results(index, results)
1202
self.update_code_analysis_actions()
1204
def update_todo_menu(self):
1205
"""Update todo list menu"""
1206
editorstack = self.get_current_editorstack()
1207
results = editorstack.get_todo_results()
1208
self.todo_menu.clear()
1209
filename = self.get_current_filename()
1210
for text, line0 in results:
1211
icon = get_icon('todo.png')
1212
slot = lambda _l=line0: self.load(filename, goto=_l)
1213
action = create_action(self, text=text, icon=icon, triggered=slot)
1214
self.todo_menu.addAction(action)
1215
self.update_todo_actions()
1217
def todo_results_changed(self):
1219
Synchronize todo results between editorstacks
1220
Refresh todo list navigation buttons
1222
editorstack = self.get_current_editorstack()
1223
results = editorstack.get_todo_results()
1224
index = editorstack.get_stack_index()
1226
for other_editorstack in self.editorstacks:
1227
if other_editorstack is not editorstack:
1228
other_editorstack.set_todo_results(index, results)
1229
self.update_todo_actions()
1231
def refresh_eol_chars(self, os_name):
1232
os_name = unicode(os_name)
1233
self.__set_eol_chars = False
1235
self.win_eol_action.setChecked(True)
1236
elif os_name == 'posix':
1237
self.linux_eol_action.setChecked(True)
1239
self.mac_eol_action.setChecked(True)
1240
self.__set_eol_chars = True
1244
def opened_files_list_changed(self):
1246
Opened files list has changed:
1247
--> open/close file action
1248
--> modification ('*' added to title)
1249
--> current edited file has changed
1251
# Refresh Python file dependent actions:
1252
editor = self.get_current_editor()
1254
enable = editor.is_python()
1255
for action in self.pythonfile_dependent_actions:
1256
if action is self.winpdb_action:
1257
action.setEnabled(enable and WINPDB_PATH is not None)
1259
action.setEnabled(enable)
1261
def update_code_analysis_actions(self):
1262
editorstack = self.get_current_editorstack()
1263
results = editorstack.get_analysis_results()
1265
# Update code analysis buttons
1266
state = (self.get_option('code_analysis/pyflakes') \
1267
or self.get_option('code_analysis/pep8')) \
1268
and results is not None and len(results)
1269
for action in (self.warning_list_action, self.previous_warning_action,
1270
self.next_warning_action):
1271
action.setEnabled(state)
1273
def update_todo_actions(self):
1274
editorstack = self.get_current_editorstack()
1275
results = editorstack.get_todo_results()
1276
state = self.get_option('todo_list') \
1277
and results is not None and len(results)
1278
self.todo_list_action.setEnabled(state)
1282
def save_breakpoints(self, filename, breakpoints):
1283
filename, breakpoints = unicode(filename), unicode(breakpoints)
1284
filename = osp.normpath(osp.abspath(filename))
1286
breakpoints = eval(breakpoints)
1289
save_breakpoints(filename, breakpoints)
1293
def __load_temp_file(self):
1294
"""Load temporary file from a text file in user home directory"""
1295
if not osp.isfile(self.TEMPFILE_PATH):
1296
# Creating temporary file
1297
default = ['# -*- coding: utf-8 -*-',
1298
'"""', _("Spyder Editor"), '',
1299
_("This temporary script file is located here:"),
1302
text = os.linesep.join([encoding.to_unicode(qstr)
1303
for qstr in default])
1304
encoding.write(unicode(text), self.TEMPFILE_PATH, 'utf-8')
1305
self.load(self.TEMPFILE_PATH)
1307
def __set_workdir(self):
1308
"""Set current script directory as working directory"""
1309
fname = self.get_current_filename()
1310
if fname is not None:
1311
directory = osp.dirname(osp.abspath(fname))
1312
self.emit(SIGNAL("open_dir(QString)"), directory)
1314
def __add_recent_file(self, fname):
1315
"""Add to recent file list"""
1318
if fname in self.recent_files:
1319
self.recent_files.remove(fname)
1320
self.recent_files.insert(0, fname)
1321
if len(self.recent_files) > self.get_option('max_recent_files'):
1322
self.recent_files.pop(-1)
1324
def _clone_file_everywhere(self, finfo):
1325
"""Clone file (*src_editor* widget) in all editorstacks
1326
Cloning from the first editorstack in which every single new editor
1327
is created (when loading or creating a new file)"""
1328
for editorstack in self.editorstacks[1:]:
1329
editor = editorstack.clone_editor_from(finfo, set_current=False)
1330
self.register_widget_shortcuts("Editor", editor)
1332
def new(self, fname=None, editorstack=None):
1334
Create a new file - Untitled
1336
fname=None --> fname will be 'untitledXX.py' but do not create file
1337
fname=<basestring> --> create file
1340
text, enc = encoding.read(self.TEMPLATE_PATH)
1341
encoding_match = re.search('-*- coding: ?([a-z0-9A-Z\-]*) -*-', text)
1343
enc = encoding_match.group(1)
1344
# Initialize template variables
1346
username = encoding.to_unicode_from_fs(os.environ.get('USERNAME',
1350
username = encoding.to_unicode_from_fs(os.environ.get('USER',
1353
'date':time.ctime(),
1354
'username':username,
1360
create_fname = lambda n: unicode(_("untitled")) + ("%d.py" % n)
1361
# Creating editor widget
1362
if editorstack is None:
1363
current_es = self.get_current_editorstack()
1365
current_es = editorstack
1366
created_from_here = fname is None
1367
if created_from_here:
1369
fname = create_fname(self.untitled_num)
1370
self.untitled_num += 1
1371
if not osp.isfile(fname):
1373
basedir = os.getcwdu()
1374
if CONF.get('workingdir', 'editor/new/browse_scriptdir'):
1375
c_fname = self.get_current_filename()
1376
if c_fname is not None and c_fname != self.TEMPFILE_PATH:
1377
basedir = osp.dirname(c_fname)
1378
fname = osp.abspath(osp.join(basedir, fname))
1380
# QString when triggered by a Qt signal
1381
fname = osp.abspath(unicode(fname))
1382
index = current_es.has_filename(fname)
1383
if index and not current_es.close_file(index):
1386
# Creating the editor widget in the first editorstack (the one that
1387
# can't be destroyed), then cloning this editor widget in all other
1389
finfo = self.editorstacks[0].new(fname, enc, text)
1390
self._clone_file_everywhere(finfo)
1391
current_editor = current_es.set_current_filename(finfo.filename)
1392
self.register_widget_shortcuts("Editor", current_editor)
1393
if not created_from_here:
1394
self.save(force=True)
1396
def edit_template(self):
1397
"""Edit new file template"""
1398
self.load(self.TEMPLATE_PATH)
1400
def update_recent_file_menu(self):
1401
"""Update recent file menu"""
1403
for fname in self.recent_files:
1404
if not self.is_file_opened(fname) and osp.isfile(fname):
1405
recent_files.append(fname)
1406
self.recent_file_menu.clear()
1408
for i, fname in enumerate(recent_files):
1410
accel = "%d" % ((i+1) % 10)
1412
accel = chr(i-10+ord('a'))
1413
action = create_action(self, "&%s %s" % (accel, fname),
1414
icon=get_filetype_icon(fname),
1415
triggered=self.load)
1416
action.setData(to_qvariant(fname))
1417
self.recent_file_menu.addAction(action)
1418
self.clear_recent_action.setEnabled(len(recent_files) > 0)
1419
add_actions(self.recent_file_menu, (None, self.max_recent_action,
1420
self.clear_recent_action))
1422
def clear_recent_files(self):
1423
"""Clear recent files list"""
1424
self.recent_files = []
1426
def change_max_recent_files(self):
1427
"Change max recent files entries"""
1428
editorstack = self.get_current_editorstack()
1429
mrf, valid = QInputDialog.getInteger(editorstack, _('Editor'),
1430
_('Maximum number of recent files'),
1431
self.get_option('max_recent_files'), 1, 35)
1433
self.set_option('max_recent_files', mrf)
1435
def load(self, filenames=None, goto=None, word='', editorwindow=None):
1438
editorwindow: load in this editorwindow (useful when clicking on
1439
outline explorer with multiple editor windows)
1441
editor0 = self.get_current_editor()
1442
if editor0 is not None:
1443
position0 = editor0.get_position('cursor')
1444
filename0 = self.get_current_filename()
1446
position0, filename0 = None, None
1448
# Recent files action
1449
action = self.sender()
1450
if isinstance(action, QAction):
1451
filenames = from_qvariant(action.data(), unicode)
1453
basedir = os.getcwdu()
1454
if CONF.get('workingdir', 'editor/open/browse_scriptdir'):
1455
c_fname = self.get_current_filename()
1456
if c_fname is not None and c_fname != self.TEMPFILE_PATH:
1457
basedir = osp.dirname(c_fname)
1458
self.emit(SIGNAL('redirect_stdio(bool)'), False)
1459
parent_widget = self.get_current_editorstack()
1460
filenames, _selfilter = getopenfilenames(parent_widget,
1461
_("Open file"), basedir, EDIT_FILTERS)
1462
self.emit(SIGNAL('redirect_stdio(bool)'), True)
1464
filenames = [osp.normpath(fname) for fname in filenames]
1465
if CONF.get('workingdir', 'editor/open/auto_set_to_basedir'):
1466
directory = osp.dirname(filenames[0])
1467
self.emit(SIGNAL("open_dir(QString)"), directory)
1472
focus_widget = QApplication.focusWidget()
1473
if self.dockwidget and not self.ismaximized and\
1474
(not self.dockwidget.isAncestorOf(focus_widget)\
1475
and not isinstance(focus_widget, CodeEditor)):
1476
self.dockwidget.setVisible(True)
1477
self.dockwidget.setFocus()
1478
self.dockwidget.raise_()
1480
def _convert(fname):
1481
fname = osp.abspath(encoding.to_unicode_from_fs(fname))
1482
if os.name == 'nt' and len(fname) >= 2 and fname[1] == ':':
1483
fname = fname[0].upper()+fname[1:]
1486
if hasattr(filenames, 'replaceInStrings'):
1487
# This is a QStringList instance (PyQt API #1), converting to list:
1488
filenames = list(filenames)
1489
if not isinstance(filenames, list):
1490
filenames = [_convert(filenames)]
1492
filenames = [_convert(fname) for fname in list(filenames)]
1493
if isinstance(goto, int):
1495
elif goto is not None and len(goto) != len(filenames):
1498
for index, filename in enumerate(filenames):
1499
# -- Do not open an already opened file
1500
current_editor = self.set_current_filename(filename, editorwindow)
1501
if current_editor is None:
1502
# -- Not a valid filename:
1503
if not osp.isfile(filename):
1506
current_es = self.get_current_editorstack(editorwindow)
1508
# Creating the editor widget in the first editorstack (the one
1509
# that can't be destroyed), then cloning this editor widget in
1510
# all other editorstacks:
1511
finfo = self.editorstacks[0].load(filename, set_current=False)
1512
self._clone_file_everywhere(finfo)
1513
current_editor = current_es.set_current_filename(filename)
1514
current_editor.set_breakpoints(load_breakpoints(filename))
1515
self.register_widget_shortcuts("Editor", current_editor)
1517
current_es.analyze_script()
1518
self.__add_recent_file(filename)
1519
if goto is not None: # 'word' is assumed to be None as well
1520
current_editor.go_to_line(goto[index], word=word)
1521
position = current_editor.get_position('cursor')
1522
self.cursor_moved(filename0, position0, filename, position)
1523
current_editor.clearFocus()
1524
current_editor.setFocus()
1525
current_editor.window().raise_()
1526
QApplication.processEvents()
1528
def print_file(self):
1529
"""Print current file"""
1530
editor = self.get_current_editor()
1531
filename = self.get_current_filename()
1532
printer = Printer(mode=QPrinter.HighResolution,
1533
header_font=self.get_plugin_font('printer_header'))
1534
printDialog = QPrintDialog(printer, editor)
1535
if editor.has_selected_text():
1536
printDialog.addEnabledOption(QAbstractPrintDialog.PrintSelection)
1537
self.emit(SIGNAL('redirect_stdio(bool)'), False)
1538
answer = printDialog.exec_()
1539
self.emit(SIGNAL('redirect_stdio(bool)'), True)
1540
if answer == QDialog.Accepted:
1541
self.starting_long_process(_("Printing..."))
1542
printer.setDocName(filename)
1543
editor.print_(printer)
1544
self.ending_long_process()
1546
def print_preview(self):
1547
"""Print preview for current file"""
1548
from spyderlib.qt.QtGui import QPrintPreviewDialog
1549
editor = self.get_current_editor()
1550
printer = Printer(mode=QPrinter.HighResolution,
1551
header_font=self.get_plugin_font('printer_header'))
1552
preview = QPrintPreviewDialog(printer, self)
1553
preview.setWindowFlags(Qt.Window)
1554
self.connect(preview, SIGNAL("paintRequested(QPrinter*)"),
1555
lambda printer: editor.print_(printer))
1556
self.emit(SIGNAL('redirect_stdio(bool)'), False)
1558
self.emit(SIGNAL('redirect_stdio(bool)'), True)
1560
def close_file(self):
1561
"""Close current file"""
1562
editorstack = self.get_current_editorstack()
1563
editorstack.close_file()
1565
def close_all_files(self):
1566
"""Close all opened scripts"""
1567
self.editorstacks[0].close_all_files()
1569
def save(self, index=None, force=False):
1571
editorstack = self.get_current_editorstack()
1572
return editorstack.save(index=index, force=force)
1575
"""Save *as* the currently edited file"""
1576
editorstack = self.get_current_editorstack()
1577
if editorstack.save_as():
1578
fname = editorstack.get_current_filename()
1579
if CONF.get('workingdir', 'editor/save/auto_set_to_basedir'):
1580
self.emit(SIGNAL("open_dir(QString)"), osp.dirname(fname))
1581
self.__add_recent_file(fname)
1584
"""Save all opened files"""
1585
self.get_current_editorstack().save_all()
1588
"""Revert the currently edited file from disk"""
1589
editorstack = self.get_current_editorstack()
1590
editorstack.revert()
1593
#------ Explorer widget
1594
def __close(self, filename):
1595
filename = osp.abspath(unicode(filename))
1596
index = self.editorstacks[0].has_filename(filename)
1597
if index is not None:
1598
self.editorstacks[0].close_file(index)
1600
def removed(self, filename):
1601
"""File was removed in file explorer widget or in project explorer"""
1602
self.__close(filename)
1604
def removed_tree(self, dirname):
1605
"""Directory was removed in project explorer widget"""
1606
dirname = osp.abspath(unicode(dirname))
1607
for fname in self.get_filenames():
1608
if osp.abspath(fname).startswith(dirname):
1611
def renamed(self, source, dest):
1612
"""File was renamed in file explorer widget or in project explorer"""
1613
filename = osp.abspath(unicode(source))
1614
index = self.editorstacks[0].has_filename(filename)
1615
if index is not None:
1616
for editorstack in self.editorstacks:
1617
editorstack.rename_in_data(index, new_filename=unicode(dest))
1622
"""Indent current line or selection"""
1623
editor = self.get_current_editor()
1624
if editor is not None:
1628
"""Unindent current line or selection"""
1629
editor = self.get_current_editor()
1630
if editor is not None:
1633
def toggle_comment(self):
1634
"""Comment current line or selection"""
1635
editor = self.get_current_editor()
1636
if editor is not None:
1637
editor.toggle_comment()
1639
def blockcomment(self):
1640
"""Block comment current line or selection"""
1641
editor = self.get_current_editor()
1642
if editor is not None:
1643
editor.blockcomment()
1645
def unblockcomment(self):
1646
"""Un-block comment current line or selection"""
1647
editor = self.get_current_editor()
1648
if editor is not None:
1649
editor.unblockcomment()
1651
def go_to_next_todo(self):
1652
editor = self.get_current_editor()
1653
position = editor.go_to_next_todo()
1654
filename = self.get_current_filename()
1655
self.add_cursor_position_to_history(filename, position)
1657
def go_to_next_warning(self):
1658
editor = self.get_current_editor()
1659
position = editor.go_to_next_warning()
1660
filename = self.get_current_filename()
1661
self.add_cursor_position_to_history(filename, position)
1663
def go_to_previous_warning(self):
1664
editor = self.get_current_editor()
1665
position = editor.go_to_previous_warning()
1666
filename = self.get_current_filename()
1667
self.add_cursor_position_to_history(filename, position)
1669
def run_winpdb(self):
1670
"""Run winpdb to debug current file"""
1672
fname = self.get_current_filename()
1673
runconf = get_run_configuration(fname)
1678
args = runconf.get_arguments().split()
1679
wdir = runconf.get_working_directory()
1680
# Handle the case where wdir comes back as an empty string
1681
# when the working directory dialog checkbox is unchecked.
1684
programs.run_program(WINPDB_PATH, [fname]+args, wdir)
1686
def toggle_eol_chars(self, os_name):
1687
editor = self.get_current_editor()
1688
if self.__set_eol_chars:
1689
editor.set_eol_chars(sourcecode.get_eol_chars_from_os_name(os_name))
1691
def remove_trailing_spaces(self):
1692
editorstack = self.get_current_editorstack()
1693
editorstack.remove_trailing_spaces()
1695
def fix_indentation(self):
1696
editorstack = self.get_current_editorstack()
1697
editorstack.fix_indentation()
1699
#------ Cursor position history management
1700
def update_cursorpos_actions(self):
1701
self.previous_edit_cursor_action.setEnabled(
1702
self.last_edit_cursor_pos is not None)
1703
self.previous_cursor_action.setEnabled(
1704
self.cursor_pos_index is not None and self.cursor_pos_index > 0)
1705
self.next_cursor_action.setEnabled(self.cursor_pos_index is not None \
1706
and self.cursor_pos_index < len(self.cursor_pos_history)-1)
1708
def add_cursor_position_to_history(self, filename, position, fc=False):
1709
if self.__ignore_cursor_position:
1711
for index, (fname, pos) in enumerate(self.cursor_pos_history[:]):
1712
if fname == filename:
1713
if pos == position or pos == 0:
1715
self.cursor_pos_history[index] = (filename, position)
1716
self.cursor_pos_index = index
1717
self.update_cursorpos_actions()
1720
if self.cursor_pos_index >= index:
1721
self.cursor_pos_index -= 1
1722
self.cursor_pos_history.pop(index)
1724
if self.cursor_pos_index is not None:
1725
self.cursor_pos_history = \
1726
self.cursor_pos_history[:self.cursor_pos_index+1]
1727
self.cursor_pos_history.append((filename, position))
1728
self.cursor_pos_index = len(self.cursor_pos_history)-1
1729
self.update_cursorpos_actions()
1731
def cursor_moved(self, filename0, position0, filename1, position1):
1732
"""Cursor was just moved: 'go to'"""
1733
if position0 is not None:
1734
self.add_cursor_position_to_history(filename0, position0)
1735
self.add_cursor_position_to_history(filename1, position1)
1737
def text_changed_at(self, filename, position):
1738
self.last_edit_cursor_pos = (unicode(filename), position)
1740
def current_file_changed(self, filename, position):
1741
self.add_cursor_position_to_history(unicode(filename), position,
1744
def go_to_last_edit_location(self):
1745
if self.last_edit_cursor_pos is not None:
1746
filename, position = self.last_edit_cursor_pos
1747
if not osp.isfile(filename):
1748
self.last_edit_cursor_pos = None
1752
editor = self.get_current_editor()
1753
if position < editor.document().characterCount():
1754
editor.set_cursor_position(position)
1756
def __move_cursor_position(self, index_move):
1757
if self.cursor_pos_index is None:
1759
filename, _position = self.cursor_pos_history[self.cursor_pos_index]
1760
self.cursor_pos_history[self.cursor_pos_index] = ( filename,
1761
self.get_current_editor().get_position('cursor') )
1762
self.__ignore_cursor_position = True
1763
old_index = self.cursor_pos_index
1764
self.cursor_pos_index = min([
1765
len(self.cursor_pos_history)-1,
1766
max([0, self.cursor_pos_index+index_move])
1768
filename, position = self.cursor_pos_history[self.cursor_pos_index]
1769
if not osp.isfile(filename):
1770
self.cursor_pos_history.pop(self.cursor_pos_index)
1771
if self.cursor_pos_index < old_index:
1773
self.cursor_pos_index = old_index
1776
editor = self.get_current_editor()
1777
if position < editor.document().characterCount():
1778
editor.set_cursor_position(position)
1779
self.__ignore_cursor_position = False
1780
self.update_cursorpos_actions()
1782
def go_to_previous_cursor_position(self):
1783
self.__move_cursor_position(-1)
1785
def go_to_next_cursor_position(self):
1786
self.__move_cursor_position(1)
1788
def go_to_line(self):
1789
"""Open 'go to line' dialog"""
1790
editorstack = self.get_current_editorstack()
1791
if editorstack is not None:
1792
editorstack.go_to_line()
1794
def set_or_clear_breakpoint(self):
1795
"""Set/Clear breakpoint"""
1796
editorstack = self.get_current_editorstack()
1797
if editorstack is not None:
1798
editorstack.set_or_clear_breakpoint()
1800
def set_or_edit_conditional_breakpoint(self):
1801
"""Set/Edit conditional breakpoint"""
1802
editorstack = self.get_current_editorstack()
1803
if editorstack is not None:
1804
editorstack.set_or_edit_conditional_breakpoint()
1806
def clear_all_breakpoints(self):
1807
"""Clear breakpoints in all files"""
1808
clear_all_breakpoints()
1809
editorstack = self.get_current_editorstack()
1810
if editorstack is not None:
1811
for data in editorstack.data:
1812
data.editor.clear_breakpoints()
1815
#------ Run Python script
1816
def edit_run_configurations(self):
1817
dialog = RunConfigDialog(self)
1818
fname = osp.abspath(self.get_current_filename())
1820
if self.configdialog_size is not None:
1821
dialog.resize(self.configdialog_size)
1823
self.configdialog_size = dialog.get_window_size()
1824
fname = dialog.file_to_run
1825
if fname is not None:
1829
def run_file(self, debug=False):
1830
"""Run script inside current interpreter or in a new one"""
1831
editorstack = self.get_current_editorstack()
1832
if editorstack.save():
1833
editor = self.get_current_editor()
1834
fname = osp.abspath(self.get_current_filename())
1836
runconf = get_run_configuration(fname)
1838
dialog = RunConfigOneDialog(self)
1840
if self.configdialog_size is not None:
1841
dialog.resize(self.configdialog_size)
1842
if not dialog.exec_():
1844
self.configdialog_size = dialog.get_window_size()
1845
runconf = dialog.get_configuration()
1847
wdir = runconf.get_working_directory()
1848
args = runconf.get_arguments()
1849
python_args = runconf.get_python_arguments()
1850
interact = runconf.interact
1851
current = runconf.current
1852
systerm = runconf.systerm
1854
python = True # Note: in the future, it may be useful to run
1855
# something in a terminal instead of a Python interp.
1856
self.__last_ec_exec = (fname, wdir, args, interact, debug,
1857
python, python_args, current, systerm)
1859
if not interact and not debug:
1860
# If external console dockwidget is hidden, it will be
1861
# raised in top-level and so focus will be given to the
1862
# current external shell automatically
1863
# (see SpyderPluginWidget.visibility_changed method)
1866
def debug_file(self):
1867
"""Debug current script"""
1868
self.run_file(debug=True)
1870
def re_run_file(self):
1871
"""Re-run last script"""
1872
if self.get_option('save_all_before_run', True):
1874
if self.__last_ec_exec is None:
1876
(fname, wdir, args, interact, debug,
1877
python, python_args, current, systerm) = self.__last_ec_exec
1879
self.emit(SIGNAL('run_in_current_console(QString,QString,QString,bool)'),
1880
fname, wdir, args, debug)
1882
self.main.open_external_console(fname, wdir, args, interact,
1883
debug, python, python_args,
1886
def run_selection_or_block(self):
1887
"""Run selection or current line in external console"""
1888
editorstack = self.get_current_editorstack()
1889
editorstack.run_selection_or_block()
1893
def apply_plugin_settings(self, options):
1894
"""Apply configuration file's plugin settings"""
1895
# toggle_fullpath_sorting
1896
if self.editorstacks is not None:
1897
color_scheme_n = 'color_scheme_name'
1898
color_scheme_o = get_color_scheme(self.get_option(color_scheme_n))
1899
font_n = 'plugin_font'
1900
font_o = self.get_plugin_font()
1901
fpsorting_n = 'fullpath_sorting'
1902
fpsorting_o = self.get_option(fpsorting_n)
1903
tabbar_n = 'show_tab_bar'
1904
tabbar_o = self.get_option(tabbar_n)
1905
linenb_n = 'line_numbers'
1906
linenb_o = self.get_option(linenb_n)
1907
edgeline_n = 'edge_line'
1908
edgeline_o = self.get_option(edgeline_n)
1909
edgelinecol_n = 'edge_line_column'
1910
edgelinecol_o = self.get_option(edgelinecol_n)
1911
currentline_n = 'highlight_current_line'
1912
currentline_o = self.get_option(currentline_n)
1913
occurence_n = 'occurence_highlighting'
1914
occurence_o = self.get_option(occurence_n)
1915
occurence_timeout_n = 'occurence_highlighting/timeout'
1916
occurence_timeout_o = self.get_option(occurence_timeout_n)
1918
wrap_o = self.get_option(wrap_n)
1919
tabindent_n = 'tab_always_indent'
1920
tabindent_o = self.get_option(tabindent_n)
1921
ibackspace_n = 'intelligent_backspace'
1922
ibackspace_o = self.get_option(ibackspace_n)
1923
removetrail_n = 'always_remove_trailing_spaces'
1924
removetrail_o = self.get_option(removetrail_n)
1925
autocomp_n = 'codecompletion/auto'
1926
autocomp_o = self.get_option(autocomp_n)
1927
case_comp_n = 'codecompletion/case_sensitive'
1928
case_comp_o = self.get_option(case_comp_n)
1929
show_single_n = 'codecompletion/show_single'
1930
show_single_o = self.get_option(show_single_n)
1931
enter_key_n = 'codecompletion/enter_key'
1932
enter_key_o = self.get_option(enter_key_n)
1933
calltips_n = 'calltips'
1934
calltips_o = self.get_option(calltips_n)
1935
gotodef_n = 'go_to_definition'
1936
gotodef_o = self.get_option(gotodef_n)
1937
closepar_n = 'close_parentheses'
1938
closepar_o = self.get_option(closepar_n)
1939
autounindent_n = 'auto_unindent'
1940
autounindent_o = self.get_option(autounindent_n)
1941
indent_chars_n = 'indent_chars'
1942
indent_chars_o = self.get_option(indent_chars_n)
1943
tab_stop_width_n = 'tab_stop_width'
1944
tab_stop_width_o = self.get_option(tab_stop_width_n)
1945
inspector_n = 'object_inspector'
1946
inspector_o = self.get_option(inspector_n)
1947
todo_n = 'todo_list'
1948
todo_o = self.get_option(todo_n)
1949
pyflakes_n = 'code_analysis/pyflakes'
1950
pyflakes_o = self.get_option(pyflakes_n)
1951
pep8_n = 'code_analysis/pep8'
1952
pep8_o = self.get_option(pep8_n)
1953
rt_analysis_n = 'realtime_analysis'
1954
rt_analysis_o = self.get_option(rt_analysis_n)
1955
rta_timeout_n = 'realtime_analysis/timeout'
1956
rta_timeout_o = self.get_option(rta_timeout_n)
1957
finfo = self.get_current_finfo()
1958
if fpsorting_n in options:
1959
if self.outlineexplorer is not None:
1960
self.outlineexplorer.set_fullpath_sorting(fpsorting_o)
1961
for window in self.editorwindows:
1962
window.editorwidget.outlineexplorer.set_fullpath_sorting(
1964
for editorstack in self.editorstacks:
1965
if font_n in options:
1966
scs = color_scheme_o if color_scheme_n in options else None
1967
editorstack.set_default_font(font_o, scs)
1968
elif color_scheme_n in options:
1969
editorstack.set_color_scheme(color_scheme_o)
1970
if fpsorting_n in options:
1971
editorstack.set_fullpath_sorting_enabled(fpsorting_o)
1972
if tabbar_n in options:
1973
editorstack.set_tabbar_visible(tabbar_o)
1974
if linenb_n in options:
1975
editorstack.set_linenumbers_enabled(linenb_o,
1976
current_finfo=finfo)
1977
if edgeline_n in options:
1978
editorstack.set_edgeline_enabled(edgeline_o)
1979
if edgelinecol_n in options:
1980
editorstack.set_edgeline_column(edgelinecol_o)
1981
if currentline_n in options:
1982
editorstack.set_highlight_current_line_enabled(
1984
if occurence_n in options:
1985
editorstack.set_occurence_highlighting_enabled(occurence_o)
1986
if occurence_timeout_n in options:
1987
editorstack.set_occurence_highlighting_timeout(
1988
occurence_timeout_o)
1989
if wrap_n in options:
1990
editorstack.set_wrap_enabled(wrap_o)
1991
if tabindent_n in options:
1992
editorstack.set_tabmode_enabled(tabindent_o)
1993
if ibackspace_n in options:
1994
editorstack.set_intelligent_backspace_enabled(ibackspace_o)
1995
if removetrail_n in options:
1996
editorstack.set_always_remove_trailing_spaces(removetrail_o)
1997
if autocomp_n in options:
1998
editorstack.set_codecompletion_auto_enabled(autocomp_o)
1999
if case_comp_n in options:
2000
editorstack.set_codecompletion_case_enabled(case_comp_o)
2001
if show_single_n in options:
2002
editorstack.set_codecompletion_single_enabled(show_single_o)
2003
if enter_key_n in options:
2004
editorstack.set_codecompletion_enter_enabled(enter_key_o)
2005
if calltips_n in options:
2006
editorstack.set_calltips_enabled(calltips_o)
2007
if gotodef_n in options:
2008
editorstack.set_go_to_definition_enabled(gotodef_o)
2009
if closepar_n in options:
2010
editorstack.set_close_parentheses_enabled(closepar_o)
2011
if autounindent_n in options:
2012
editorstack.set_auto_unindent_enabled(autounindent_o)
2013
if indent_chars_n in options:
2014
editorstack.set_indent_chars(indent_chars_o)
2015
if tab_stop_width_n in options:
2016
editorstack.set_tab_stop_width(tab_stop_width_o)
2017
if inspector_n in options:
2018
editorstack.set_inspector_enabled(inspector_o)
2019
if todo_n in options:
2020
editorstack.set_todolist_enabled(todo_o,
2021
current_finfo=finfo)
2022
if pyflakes_n in options:
2023
editorstack.set_pyflakes_enabled(pyflakes_o,
2024
current_finfo=finfo)
2025
if pep8_n in options:
2026
editorstack.set_pep8_enabled(pep8_o, current_finfo=finfo)
2027
if rt_analysis_n in options:
2028
editorstack.set_realtime_analysis_enabled(rt_analysis_o)
2029
if rta_timeout_n in options:
2030
editorstack.set_realtime_analysis_timeout(rta_timeout_o)
2031
# We must update the current editor after the others:
2032
# (otherwise, code analysis buttons state would correspond to the
2033
# last editor instead of showing the one of the current editor)
2034
if finfo is not None:
2035
if todo_n in options and todo_o:
2036
finfo.run_todo_finder()
2037
if pyflakes_n in options or pep8_n in options:
2038
finfo.run_code_analysis(pyflakes_o, pep8_o)