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)
7
"""Working Directory Plugin"""
9
# pylint: disable=C0103
10
# pylint: disable=R0903
11
# pylint: disable=R0911
12
# pylint: disable=R0201
14
from spyderlib.qt.QtGui import (QToolBar, QLabel, QGroupBox, QVBoxLayout,
15
QHBoxLayout, QButtonGroup)
16
from spyderlib.qt.QtCore import SIGNAL, Signal
17
from spyderlib.qt.compat import getexistingdirectory
23
from spyderlib.utils import encoding
24
from spyderlib.baseconfig import get_conf_path, _
25
from spyderlib.guiconfig import get_icon
26
from spyderlib.utils.qthelpers import get_std_icon, create_action
28
# Package local imports
29
from spyderlib.widgets.comboboxes import PathComboBox
30
from spyderlib.plugins import SpyderPluginMixin, PluginConfigPage
33
class WorkingDirectoryConfigPage(PluginConfigPage):
35
about_label = QLabel(_("The <b>global working directory</b> is "
36
"the working directory for newly opened <i>consoles</i> "
37
"(Python/IPython interpreters and terminals), for the "
38
"<i>file explorer</i>, for the <i>find in files</i> "
39
"plugin and for new files created in the <i>editor</i>."))
40
about_label.setWordWrap(True)
42
startup_group = QGroupBox(_("Startup"))
43
startup_bg = QButtonGroup(startup_group)
44
startup_label = QLabel(_("At startup, the global working "
46
startup_label.setWordWrap(True)
47
lastdir_radio = self.create_radiobutton(
48
_("the same as in last session"),
49
'startup/use_last_directory', True,
50
_("At startup, Spyder will restore the "
51
"global directory from last session"),
52
button_group=startup_bg)
53
thisdir_radio = self.create_radiobutton(
54
_("the following directory:"),
55
'startup/use_fixed_directory', False,
56
_("At startup, the global working "
57
"directory will be the specified path"),
58
button_group=startup_bg)
59
thisdir_bd = self.create_browsedir("", 'startup/fixed_directory',
61
self.connect(thisdir_radio, SIGNAL("toggled(bool)"),
62
thisdir_bd.setEnabled)
63
self.connect(lastdir_radio, SIGNAL("toggled(bool)"),
64
thisdir_bd.setDisabled)
65
thisdir_layout = QHBoxLayout()
66
thisdir_layout.addWidget(thisdir_radio)
67
thisdir_layout.addWidget(thisdir_bd)
69
editor_o_group = QGroupBox(_("Open file"))
70
editor_o_label = QLabel(_("Files are opened from:"))
71
editor_o_label.setWordWrap(True)
72
editor_o_bg = QButtonGroup(editor_o_group)
73
editor_o_radio1 = self.create_radiobutton(
74
_("the current file directory"),
75
'editor/open/browse_scriptdir', True,
76
button_group=editor_o_bg)
77
editor_o_radio2 = self.create_radiobutton(
78
_("the global working directory"),
79
'editor/open/browse_workdir', False,
80
button_group=editor_o_bg)
82
editor_n_group = QGroupBox(_("New file"))
83
editor_n_label = QLabel(_("Files are created in:"))
84
editor_n_label.setWordWrap(True)
85
editor_n_bg = QButtonGroup(editor_n_group)
86
editor_n_radio1 = self.create_radiobutton(
87
_("the current file directory"),
88
'editor/new/browse_scriptdir', False,
89
button_group=editor_n_bg)
90
editor_n_radio2 = self.create_radiobutton(
91
_("the global working directory"),
92
'editor/new/browse_workdir', True,
93
button_group=editor_n_bg)
94
# Note: default values for the options above are set in plugin's
95
# constructor (see below)
97
other_group = QGroupBox(_("Change to file base directory"))
98
newcb = self.create_checkbox
99
open_box = newcb(_("When opening a file"),
100
'editor/open/auto_set_to_basedir', False)
101
save_box = newcb(_("When saving a file"),
102
'editor/save/auto_set_to_basedir', False)
104
startup_layout = QVBoxLayout()
105
startup_layout.addWidget(startup_label)
106
startup_layout.addWidget(lastdir_radio)
107
startup_layout.addLayout(thisdir_layout)
108
startup_group.setLayout(startup_layout)
110
editor_o_layout = QVBoxLayout()
111
editor_o_layout.addWidget(editor_o_label)
112
editor_o_layout.addWidget(editor_o_radio1)
113
editor_o_layout.addWidget(editor_o_radio2)
114
editor_o_group.setLayout(editor_o_layout)
116
editor_n_layout = QVBoxLayout()
117
editor_n_layout.addWidget(editor_n_label)
118
editor_n_layout.addWidget(editor_n_radio1)
119
editor_n_layout.addWidget(editor_n_radio2)
120
editor_n_group.setLayout(editor_n_layout)
122
other_layout = QVBoxLayout()
123
other_layout.addWidget(open_box)
124
other_layout.addWidget(save_box)
125
other_group.setLayout(other_layout)
127
vlayout = QVBoxLayout()
128
vlayout.addWidget(about_label)
129
vlayout.addSpacing(10)
130
vlayout.addWidget(startup_group)
131
vlayout.addWidget(editor_o_group)
132
vlayout.addWidget(editor_n_group)
133
vlayout.addWidget(other_group)
134
vlayout.addStretch(1)
135
self.setLayout(vlayout)
138
class WorkingDirectory(QToolBar, SpyderPluginMixin):
140
Working directory changer widget
142
CONF_SECTION = 'workingdir'
143
CONFIGWIDGET_CLASS = WorkingDirectoryConfigPage
144
LOG_PATH = get_conf_path('.workingdir')
145
sig_option_changed = Signal(str, object)
146
def __init__(self, parent, workdir=None):
147
QToolBar.__init__(self, parent)
148
SpyderPluginMixin.__init__(self, parent)
151
self.initialize_plugin()
153
# Setting default values for editor-related options
154
self.get_option('editor/open/browse_scriptdir', True)
155
self.get_option('editor/open/browse_workdir', False)
156
self.get_option('editor/new/browse_scriptdir', False)
157
self.get_option('editor/new/browse_workdir', True)
158
self.get_option('editor/open/auto_set_to_basedir', False)
159
self.get_option('editor/save/auto_set_to_basedir', False)
161
self.setWindowTitle(self.get_plugin_title()) # Toolbar title
162
self.setObjectName(self.get_plugin_title()) # Used to save Window state
164
# Previous dir action
166
self.histindex = None
167
self.previous_action = create_action(self, "previous", None,
168
get_icon('previous.png'), _('Back'),
169
triggered=self.previous_directory)
170
self.addAction(self.previous_action)
174
self.histindex = None
175
self.next_action = create_action(self, "next", None,
176
get_icon('next.png'), _('Next'),
177
triggered=self.next_directory)
178
self.addAction(self.next_action)
180
# Enable/disable previous/next actions
181
self.connect(self, SIGNAL("set_previous_enabled(bool)"),
182
self.previous_action.setEnabled)
183
self.connect(self, SIGNAL("set_next_enabled(bool)"),
184
self.next_action.setEnabled)
187
adjust = self.get_option('working_dir_adjusttocontents', False)
188
self.pathedit = PathComboBox(self, adjust_to_contents=adjust)
189
self.pathedit.setToolTip(_("This is the working directory for newly\n"
190
"opened consoles (Python interpreters and\n"
191
"terminals), for the file explorer, for the\n"
192
"find in files plugin and for new files\n"
193
"created in the editor"))
194
self.connect(self.pathedit, SIGNAL("open_dir(QString)"), self.chdir)
195
self.pathedit.setMaxCount(self.get_option('working_dir_history', 20))
196
wdhistory = self.load_wdhistory( workdir )
198
if self.get_option('startup/use_last_directory', True):
200
workdir = wdhistory[0]
204
workdir = self.get_option('startup/fixed_directory', ".")
205
if not osp.isdir(workdir):
208
self.pathedit.addItems( wdhistory )
209
self.refresh_plugin()
210
self.addWidget(self.pathedit)
213
browse_action = create_action(self, "browse", None,
214
get_std_icon('DirOpenIcon'),
215
_('Browse a working directory'),
216
triggered=self.select_directory)
217
self.addAction(browse_action)
219
# Set current console working directory action
220
setwd_action = create_action(self, icon=get_icon('set_workdir.png'),
221
text=_("Set as current console's "
222
"working directory"),
223
triggered=self.set_as_current_console_wd)
224
self.addAction(setwd_action)
227
parent_action = create_action(self, "parent", None,
229
_('Change to parent directory'),
230
triggered=self.parent_directory)
231
self.addAction(parent_action)
233
#------ SpyderPluginWidget API ---------------------------------------------
234
def get_plugin_title(self):
235
"""Return widget title"""
236
return _('Global working directory')
238
def get_plugin_icon(self):
239
"""Return widget icon"""
240
return get_std_icon('DirOpenIcon')
242
def get_plugin_actions(self):
246
def register_plugin(self):
247
"""Register plugin in Spyder's main window"""
248
self.connect(self, SIGNAL('redirect_stdio(bool)'),
249
self.main.redirect_internalshell_stdio)
250
self.connect(self.main.console.shell, SIGNAL("refresh()"),
252
self.main.addToolBar(self)
254
def refresh_plugin(self):
256
curdir = os.getcwdu()
257
self.pathedit.add_text(curdir)
258
self.save_wdhistory()
259
self.emit(SIGNAL("set_previous_enabled(bool)"),
260
self.histindex is not None and self.histindex > 0)
261
self.emit(SIGNAL("set_next_enabled(bool)"),
262
self.histindex is not None and \
263
self.histindex < len(self.history)-1)
265
def apply_plugin_settings(self, options):
266
"""Apply configuration file's plugin settings"""
269
def closing_plugin(self, cancelable=False):
270
"""Perform actions before parent main window is closed"""
273
#------ Public API ---------------------------------------------------------
274
def load_wdhistory(self, workdir=None):
275
"""Load history from a text file in user home directory"""
276
if osp.isfile(self.LOG_PATH):
277
wdhistory, _ = encoding.readlines(self.LOG_PATH)
278
wdhistory = [name for name in wdhistory if os.path.isdir(name)]
281
workdir = os.getcwdu()
282
wdhistory = [ workdir ]
285
def save_wdhistory(self):
286
"""Save history to a text file in user home directory"""
287
text = [ unicode( self.pathedit.itemText(index) ) \
288
for index in range(self.pathedit.count()) ]
289
encoding.writelines(text, self.LOG_PATH)
291
def select_directory(self):
292
"""Select directory"""
293
self.emit(SIGNAL('redirect_stdio(bool)'), False)
294
directory = getexistingdirectory(self.main, _("Select directory"),
297
self.chdir(directory)
298
self.emit(SIGNAL('redirect_stdio(bool)'), True)
300
def previous_directory(self):
301
"""Back to previous directory"""
303
self.chdir(browsing_history=True)
305
def next_directory(self):
306
"""Return to next directory"""
308
self.chdir(browsing_history=True)
310
def parent_directory(self):
311
"""Change working directory to parent directory"""
312
self.chdir(os.path.join(os.getcwdu(), os.path.pardir))
314
def chdir(self, directory=None, browsing_history=False,
315
refresh_explorer=True):
316
"""Set directory as working directory"""
317
# Working directory history management
318
if directory is not None:
319
directory = osp.abspath(unicode(directory))
321
directory = self.history[self.histindex]
322
elif directory in self.history:
323
self.histindex = self.history.index(directory)
325
if self.histindex is None:
328
self.history = self.history[:self.histindex+1]
329
self.history.append(directory)
330
self.histindex = len(self.history)-1
332
# Changing working directory
333
os.chdir( unicode(directory) )
334
self.refresh_plugin()
336
self.emit(SIGNAL("set_explorer_cwd(QString)"), directory)
337
self.emit(SIGNAL("refresh_findinfiles()"))
339
def set_as_current_console_wd(self):
340
"""Set as current console working directory"""
341
self.emit(SIGNAL("set_current_console_wd(QString)"), os.getcwdu())
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)
7
"""Working Directory Plugin"""
9
# pylint: disable=C0103
10
# pylint: disable=R0903
11
# pylint: disable=R0911
12
# pylint: disable=R0201
14
from spyderlib.qt.QtGui import (QToolBar, QLabel, QGroupBox, QVBoxLayout,
15
QHBoxLayout, QButtonGroup)
16
from spyderlib.qt.QtCore import SIGNAL, Signal
17
from spyderlib.qt.compat import getexistingdirectory
23
from spyderlib.utils import encoding
24
from spyderlib.baseconfig import get_conf_path, _
25
from spyderlib.utils.qthelpers import get_icon, get_std_icon, create_action
27
# Package local imports
28
from spyderlib.widgets.comboboxes import PathComboBox
29
from spyderlib.plugins import SpyderPluginMixin, PluginConfigPage
32
class WorkingDirectoryConfigPage(PluginConfigPage):
34
about_label = QLabel(_("The <b>global working directory</b> is "
35
"the working directory for newly opened <i>consoles</i> "
36
"(Python/IPython interpreters and terminals), for the "
37
"<i>file explorer</i>, for the <i>find in files</i> "
38
"plugin and for new files created in the <i>editor</i>."))
39
about_label.setWordWrap(True)
41
startup_group = QGroupBox(_("Startup"))
42
startup_bg = QButtonGroup(startup_group)
43
startup_label = QLabel(_("At startup, the global working "
45
startup_label.setWordWrap(True)
46
lastdir_radio = self.create_radiobutton(
47
_("the same as in last session"),
48
'startup/use_last_directory', True,
49
_("At startup, Spyder will restore the "
50
"global directory from last session"),
51
button_group=startup_bg)
52
thisdir_radio = self.create_radiobutton(
53
_("the following directory:"),
54
'startup/use_fixed_directory', False,
55
_("At startup, the global working "
56
"directory will be the specified path"),
57
button_group=startup_bg)
58
thisdir_bd = self.create_browsedir("", 'startup/fixed_directory',
60
self.connect(thisdir_radio, SIGNAL("toggled(bool)"),
61
thisdir_bd.setEnabled)
62
self.connect(lastdir_radio, SIGNAL("toggled(bool)"),
63
thisdir_bd.setDisabled)
64
thisdir_layout = QHBoxLayout()
65
thisdir_layout.addWidget(thisdir_radio)
66
thisdir_layout.addWidget(thisdir_bd)
68
editor_o_group = QGroupBox(_("Open file"))
69
editor_o_label = QLabel(_("Files are opened from:"))
70
editor_o_label.setWordWrap(True)
71
editor_o_bg = QButtonGroup(editor_o_group)
72
editor_o_radio1 = self.create_radiobutton(
73
_("the current file directory"),
74
'editor/open/browse_scriptdir', True,
75
button_group=editor_o_bg)
76
editor_o_radio2 = self.create_radiobutton(
77
_("the global working directory"),
78
'editor/open/browse_workdir', False,
79
button_group=editor_o_bg)
81
editor_n_group = QGroupBox(_("New file"))
82
editor_n_label = QLabel(_("Files are created in:"))
83
editor_n_label.setWordWrap(True)
84
editor_n_bg = QButtonGroup(editor_n_group)
85
editor_n_radio1 = self.create_radiobutton(
86
_("the current file directory"),
87
'editor/new/browse_scriptdir', False,
88
button_group=editor_n_bg)
89
editor_n_radio2 = self.create_radiobutton(
90
_("the global working directory"),
91
'editor/new/browse_workdir', True,
92
button_group=editor_n_bg)
93
# Note: default values for the options above are set in plugin's
94
# constructor (see below)
96
other_group = QGroupBox(_("Change to file base directory"))
97
newcb = self.create_checkbox
98
open_box = newcb(_("When opening a file"),
99
'editor/open/auto_set_to_basedir', False)
100
save_box = newcb(_("When saving a file"),
101
'editor/save/auto_set_to_basedir', False)
103
startup_layout = QVBoxLayout()
104
startup_layout.addWidget(startup_label)
105
startup_layout.addWidget(lastdir_radio)
106
startup_layout.addLayout(thisdir_layout)
107
startup_group.setLayout(startup_layout)
109
editor_o_layout = QVBoxLayout()
110
editor_o_layout.addWidget(editor_o_label)
111
editor_o_layout.addWidget(editor_o_radio1)
112
editor_o_layout.addWidget(editor_o_radio2)
113
editor_o_group.setLayout(editor_o_layout)
115
editor_n_layout = QVBoxLayout()
116
editor_n_layout.addWidget(editor_n_label)
117
editor_n_layout.addWidget(editor_n_radio1)
118
editor_n_layout.addWidget(editor_n_radio2)
119
editor_n_group.setLayout(editor_n_layout)
121
other_layout = QVBoxLayout()
122
other_layout.addWidget(open_box)
123
other_layout.addWidget(save_box)
124
other_group.setLayout(other_layout)
126
vlayout = QVBoxLayout()
127
vlayout.addWidget(about_label)
128
vlayout.addSpacing(10)
129
vlayout.addWidget(startup_group)
130
vlayout.addWidget(editor_o_group)
131
vlayout.addWidget(editor_n_group)
132
vlayout.addWidget(other_group)
133
vlayout.addStretch(1)
134
self.setLayout(vlayout)
137
class WorkingDirectory(QToolBar, SpyderPluginMixin):
139
Working directory changer widget
141
CONF_SECTION = 'workingdir'
142
CONFIGWIDGET_CLASS = WorkingDirectoryConfigPage
143
LOG_PATH = get_conf_path('.workingdir')
144
sig_option_changed = Signal(str, object)
145
def __init__(self, parent, workdir=None):
146
QToolBar.__init__(self, parent)
147
SpyderPluginMixin.__init__(self, parent)
150
self.initialize_plugin()
152
# Setting default values for editor-related options
153
self.get_option('editor/open/browse_scriptdir', True)
154
self.get_option('editor/open/browse_workdir', False)
155
self.get_option('editor/new/browse_scriptdir', False)
156
self.get_option('editor/new/browse_workdir', True)
157
self.get_option('editor/open/auto_set_to_basedir', False)
158
self.get_option('editor/save/auto_set_to_basedir', False)
160
self.setWindowTitle(self.get_plugin_title()) # Toolbar title
161
self.setObjectName(self.get_plugin_title()) # Used to save Window state
163
# Previous dir action
165
self.histindex = None
166
self.previous_action = create_action(self, "previous", None,
167
get_icon('previous.png'), _('Back'),
168
triggered=self.previous_directory)
169
self.addAction(self.previous_action)
173
self.histindex = None
174
self.next_action = create_action(self, "next", None,
175
get_icon('next.png'), _('Next'),
176
triggered=self.next_directory)
177
self.addAction(self.next_action)
179
# Enable/disable previous/next actions
180
self.connect(self, SIGNAL("set_previous_enabled(bool)"),
181
self.previous_action.setEnabled)
182
self.connect(self, SIGNAL("set_next_enabled(bool)"),
183
self.next_action.setEnabled)
186
adjust = self.get_option('working_dir_adjusttocontents', False)
187
self.pathedit = PathComboBox(self, adjust_to_contents=adjust)
188
self.pathedit.setToolTip(_("This is the working directory for newly\n"
189
"opened consoles (Python interpreters and\n"
190
"terminals), for the file explorer, for the\n"
191
"find in files plugin and for new files\n"
192
"created in the editor"))
193
self.connect(self.pathedit, SIGNAL("open_dir(QString)"), self.chdir)
194
self.pathedit.setMaxCount(self.get_option('working_dir_history', 20))
195
wdhistory = self.load_wdhistory( workdir )
197
if self.get_option('startup/use_last_directory', True):
199
workdir = wdhistory[0]
203
workdir = self.get_option('startup/fixed_directory', ".")
204
if not osp.isdir(workdir):
207
self.pathedit.addItems( wdhistory )
208
self.refresh_plugin()
209
self.addWidget(self.pathedit)
212
browse_action = create_action(self, "browse", None,
213
get_std_icon('DirOpenIcon'),
214
_('Browse a working directory'),
215
triggered=self.select_directory)
216
self.addAction(browse_action)
218
# Set current console working directory action
219
setwd_action = create_action(self, icon=get_icon('set_workdir.png'),
220
text=_("Set as current console's "
221
"working directory"),
222
triggered=self.set_as_current_console_wd)
223
self.addAction(setwd_action)
226
parent_action = create_action(self, "parent", None,
228
_('Change to parent directory'),
229
triggered=self.parent_directory)
230
self.addAction(parent_action)
232
#------ SpyderPluginWidget API ---------------------------------------------
233
def get_plugin_title(self):
234
"""Return widget title"""
235
return _('Global working directory')
237
def get_plugin_icon(self):
238
"""Return widget icon"""
239
return get_std_icon('DirOpenIcon')
241
def get_plugin_actions(self):
245
def register_plugin(self):
246
"""Register plugin in Spyder's main window"""
247
self.connect(self, SIGNAL('redirect_stdio(bool)'),
248
self.main.redirect_internalshell_stdio)
249
self.connect(self.main.console.shell, SIGNAL("refresh()"),
251
self.main.addToolBar(self)
253
def refresh_plugin(self):
255
curdir = os.getcwdu()
256
self.pathedit.add_text(curdir)
257
self.save_wdhistory()
258
self.emit(SIGNAL("set_previous_enabled(bool)"),
259
self.histindex is not None and self.histindex > 0)
260
self.emit(SIGNAL("set_next_enabled(bool)"),
261
self.histindex is not None and \
262
self.histindex < len(self.history)-1)
264
def apply_plugin_settings(self, options):
265
"""Apply configuration file's plugin settings"""
268
def closing_plugin(self, cancelable=False):
269
"""Perform actions before parent main window is closed"""
272
#------ Public API ---------------------------------------------------------
273
def load_wdhistory(self, workdir=None):
274
"""Load history from a text file in user home directory"""
275
if osp.isfile(self.LOG_PATH):
276
wdhistory, _ = encoding.readlines(self.LOG_PATH)
277
wdhistory = [name for name in wdhistory if os.path.isdir(name)]
280
workdir = os.getcwdu()
281
wdhistory = [ workdir ]
284
def save_wdhistory(self):
285
"""Save history to a text file in user home directory"""
286
text = [ unicode( self.pathedit.itemText(index) ) \
287
for index in range(self.pathedit.count()) ]
288
encoding.writelines(text, self.LOG_PATH)
290
def select_directory(self):
291
"""Select directory"""
292
self.emit(SIGNAL('redirect_stdio(bool)'), False)
293
directory = getexistingdirectory(self.main, _("Select directory"),
296
self.chdir(directory)
297
self.emit(SIGNAL('redirect_stdio(bool)'), True)
299
def previous_directory(self):
300
"""Back to previous directory"""
302
self.chdir(browsing_history=True)
304
def next_directory(self):
305
"""Return to next directory"""
307
self.chdir(browsing_history=True)
309
def parent_directory(self):
310
"""Change working directory to parent directory"""
311
self.chdir(os.path.join(os.getcwdu(), os.path.pardir))
313
def chdir(self, directory=None, browsing_history=False,
314
refresh_explorer=True):
315
"""Set directory as working directory"""
316
# Working directory history management
317
if directory is not None:
318
directory = osp.abspath(unicode(directory))
320
directory = self.history[self.histindex]
321
elif directory in self.history:
322
self.histindex = self.history.index(directory)
324
if self.histindex is None:
327
self.history = self.history[:self.histindex+1]
328
self.history.append(directory)
329
self.histindex = len(self.history)-1
331
# Changing working directory
332
os.chdir( unicode(directory) )
333
self.refresh_plugin()
335
self.emit(SIGNAL("set_explorer_cwd(QString)"), directory)
336
self.emit(SIGNAL("refresh_findinfiles()"))
338
def set_as_current_console_wd(self):
339
"""Set as current console working directory"""
340
self.emit(SIGNAL("set_current_console_wd(QString)"), os.getcwdu())