# -*- coding: utf-8 -*- # # Copyright © Spyder Project Contributors # Licensed under the terms of the MIT License # (see spyder/__init__.py for details) """ Explorer Main Widget. """ # Standard library imports import os.path as osp # Third-party imports from qtpy.QtCore import Qt, Signal from qtpy.QtWidgets import QHBoxLayout, QLabel, QVBoxLayout, QWidget # Local imports from spyder.api.translations import get_translation from spyder.api.widgets.main_widget import PluginMainWidget from spyder.plugins.explorer.widgets.explorer import ( DirViewActions, ExplorerTreeWidget, ExplorerTreeWidgetActions) from spyder.utils.misc import getcwd_or_home _ = get_translation('spyder') # ---- Constants class ExplorerWidgetOptionsMenuSections: Files = 'files_section' Header = 'header_section' Common = 'common_section' class ExplorerWidgetMainToolbarSections: Main = 'main_section' # ---- Main widget class ExplorerWidget(PluginMainWidget): """Explorer widget""" # --- Signals # ------------------------------------------------------------------------ sig_dir_opened = Signal(str) """ This signal is emitted to indicate a folder has been opened. Parameters ---------- directory: str The path to the directory opened. """ sig_module_created = Signal(str) """ This signal is emitted when a new python module is created. Parameters ---------- module: str Path to the new module created. """ sig_file_created = Signal(str) """ This signal is emitted to request creating a new file with Spyder. Parameters ---------- path: str File path to create. """ sig_open_file_requested = Signal(str) """ This signal is emitted to request opening a new file with Spyder. Parameters ---------- path: str File path to run. """ sig_removed = Signal(str) """ This signal is emitted when a file is removed. Parameters ---------- path: str File path removed. """ sig_renamed = Signal(str, str) """ This signal is emitted when a file is renamed. Parameters ---------- old_path: str Old path for renamed file. new_path: str New path for renamed file. """ sig_tree_removed = Signal(str) """ This signal is emitted when a folder is removed. Parameters ---------- path: str Folder to remove. """ sig_tree_renamed = Signal(str) """ This signal is emitted when a folder is renamed. Parameters ---------- path: str Folder to remove. """ sig_run_requested = Signal(str) """ This signal is emitted to request running a file. Parameters ---------- path: str File path to run. """ sig_open_interpreter_requested = Signal(str) """ This signal is emitted to request opening an interpreter with the given path as working directory. Parameters ---------- path: str Path to use as working directory of interpreter. """ def __init__(self, name, plugin, parent=None): """ Initialize the widget. Parameters ---------- name: str Name of the container. plugin: SpyderDockablePlugin Plugin of the container parent: QWidget Parent of this widget """ super().__init__(name, plugin=plugin, parent=parent) # Widgets self.treewidget = ExplorerTreeWidget(parent=self) # Setup widgets self.treewidget.setup() self.chdir(getcwd_or_home()) # Layouts layout = QHBoxLayout() layout.addWidget(self.treewidget) self.setLayout(layout) # Signals self.treewidget.sig_dir_opened.connect(self.sig_dir_opened) self.treewidget.sig_file_created.connect(self.sig_file_created) self.treewidget.sig_open_file_requested.connect( self.sig_open_file_requested) self.treewidget.sig_module_created.connect(self.sig_module_created) self.treewidget.sig_open_interpreter_requested.connect( self.sig_open_interpreter_requested) self.treewidget.sig_renamed.connect(self.sig_renamed) self.treewidget.sig_removed.connect(self.sig_removed) self.treewidget.sig_run_requested.connect(self.sig_run_requested) self.treewidget.sig_tree_removed.connect(self.sig_tree_removed) self.treewidget.sig_tree_renamed.connect(self.sig_tree_renamed) self.treewidget.sig_redirect_stdio_requested.connect( self.sig_redirect_stdio_requested) # ---- PluginMainWidget API # ------------------------------------------------------------------------ def get_focus_widget(self): """Define the widget to focus.""" return self.treewidget def get_title(self): """Return the title of the plugin tab.""" return _("Files") def setup(self): """Performs the setup of plugin's menu and actions.""" # Menu menu = self.get_options_menu() for item in [self.get_action(DirViewActions.ToggleHiddenFiles), self.get_action(DirViewActions.EditNameFilters)]: self.add_item_to_menu( item, menu=menu, section=ExplorerWidgetOptionsMenuSections.Common) for item in [self.get_action(DirViewActions.ToggleSizeColumn), self.get_action(DirViewActions.ToggleTypeColumn), self.get_action(DirViewActions.ToggleDateColumn)]: self.add_item_to_menu( item, menu=menu, section=ExplorerWidgetOptionsMenuSections.Header) single_click_action = self.get_action(DirViewActions.ToggleSingleClick) self.add_item_to_menu( single_click_action, menu=menu, section=ExplorerWidgetOptionsMenuSections.Files) # Toolbar toolbar = self.get_main_toolbar() for item in [self.get_action(ExplorerTreeWidgetActions.Previous), self.get_action(ExplorerTreeWidgetActions.Next), self.get_action(ExplorerTreeWidgetActions.Parent), self.get_action(ExplorerTreeWidgetActions.ToggleFilter)]: self.add_item_to_toolbar( item, toolbar=toolbar, section=ExplorerWidgetMainToolbarSections.Main) def update_actions(self): """Handle the update of actions of the plugin.""" pass # ---- Public API # ------------------------------------------------------------------------ def chdir(self, directory, emit=True): """ Set working directory. Parameters ---------- directory: str Directory to set as working directory. emit: bool, optional Default is True. """ self.treewidget.chdir(directory, emit=emit) def get_current_folder(self): """Get current folder in the tree widget.""" return self.treewidget.get_current_folder() def set_current_folder(self, folder): """ Set the current folder in the tree widget. Parameters ---------- folder: str Folder path to set as current folder. """ self.treewidget.set_current_folder(folder) def go_to_parent_directory(self): """Move to parent directory.""" self.treewidget.go_to_parent_directory() def go_to_previous_directory(self): """Move to previous directory in history.""" self.treewidget.go_to_previous_directory() def go_to_next_directory(self): """Move to next directory in history.""" self.treewidget.go_to_next_directory() def refresh(self, new_path=None, force_current=False): """ Refresh history. Parameters ---------- new_path: str, optional Path to add to history. Default is None. force_current: bool, optional Default is True. """ self.treewidget.refresh(new_path, force_current) def update_history(self, directory): """ Update history with directory. Parameters ---------- directory: str Path to add to history. """ self.treewidget.update_history(directory) # ============================================================================= # Tests # ============================================================================= class FileExplorerTest(QWidget): def __init__(self, directory=None, file_associations={}): self.CONF_SECTION = 'explorer' super().__init__() if directory is not None: self.directory = directory else: self.directory = osp.dirname(osp.abspath(__file__)) self.explorer = ExplorerWidget('explorer', self, parent=self) self.explorer.set_conf('file_associations', file_associations) self.explorer._setup() self.explorer.setup() self.label_dir = QLabel("Open dir:") self.label_file = QLabel("Open file:") self.label1 = QLabel() self.label_dir.setAlignment(Qt.AlignRight) self.label2 = QLabel() self.label_option = QLabel("Option changed:") self.label3 = QLabel() # Setup self.explorer.set_current_folder(self.directory) self.label_file.setAlignment(Qt.AlignRight) self.label_option.setAlignment(Qt.AlignRight) # Layout hlayout1 = QHBoxLayout() hlayout1.addWidget(self.label_file) hlayout1.addWidget(self.label1) hlayout2 = QHBoxLayout() hlayout2.addWidget(self.label_dir) hlayout2.addWidget(self.label2) hlayout3 = QHBoxLayout() hlayout3.addWidget(self.label_option) hlayout3.addWidget(self.label3) vlayout = QVBoxLayout() vlayout.addWidget(self.explorer) vlayout.addLayout(hlayout1) vlayout.addLayout(hlayout2) vlayout.addLayout(hlayout3) self.setLayout(vlayout) # Signals self.explorer.sig_dir_opened.connect(self.label2.setText) self.explorer.sig_dir_opened.connect( lambda: self.explorer.treewidget.refresh('..')) self.explorer.sig_open_file_requested.connect(self.label1.setText) def test(): from spyder.utils.qthelpers import qapplication app = qapplication() test = FileExplorerTest() test.resize(640, 480) test.show() app.exec_() if __name__ == "__main__": test()