Created
September 9, 2021 15:05
-
-
Save hanjinliu/71fd3d090b72bcf81b94aad3e3a20fb5 to your computer and use it in GitHub Desktop.
Explorer widget
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
from qtpy.QtWidgets import QWidget, QFileSystemModel, QTreeView, QGridLayout, QPushButton, QFileDialog | |
from qtpy.QtCore import Qt, QModelIndex | |
import os | |
from skimage import io | |
import napari | |
class Explorer(QWidget): | |
def __init__(self, viewer:"napari.Viewer", path:str=""): | |
super().__init__(viewer.window._qt_window) | |
self.viewer = viewer | |
self.setLayout(QGridLayout()) | |
self._add_change_root_button() | |
self._add_filetree(path) | |
def _add_change_root_button(self): | |
self.root_button = QPushButton(self) | |
self.root_button.setText("Change root directory") | |
@self.root_button.clicked.connect | |
def _(): | |
dlg = QFileDialog() | |
dlg.setFileMode(QFileDialog.DirectoryOnly) | |
dlg.setHistory([self.tree.rootpath]) | |
dirname = dlg.getExistingDirectory(self, caption="Select root ...", directory=self.tree.rootpath) | |
if dirname: | |
self.tree.rootpath = dirname | |
self.tree._set_file_model(dirname) | |
napari.utils.history.update_open_history(dirname) | |
return None | |
self.layout().addWidget(self.root_button) | |
return None | |
def _add_filetree(self, path:str=""): | |
""" | |
Add tree view of files with root directory set to ``path``. | |
Parameters | |
---------- | |
path : str, default is "" | |
Path of the root directory. If not found, current directory will be used. | |
""" | |
path = os.getcwd() if not os.path.exists(path) else path | |
self.tree = FileTree(self, path) | |
self.layout().addWidget(self.tree) | |
return None | |
class FileTree(QTreeView): | |
def __init__(self, parent, path:str): | |
super().__init__(parent=parent) | |
self.viewer = parent.viewer | |
self.rootpath = path | |
self.setContextMenuPolicy(Qt.CustomContextMenu) | |
self.setUniformRowHeights(True) | |
self.header().hide() | |
# Set QFileSystemModel | |
self.file_system = QFileSystemModel(self) | |
self.file_system.setReadOnly(True) | |
self.file_system.setNameFilterDisables(False) | |
self._set_file_model(path) | |
# hide columns except for name | |
for i in range(1, self.file_system.columnCount()): | |
self.hideColumn(i) | |
self.doubleClicked.connect(self.onDoubleClicked) | |
self.show() | |
def _set_file_model(self, path:str): | |
self.file_system.setRootPath(path) | |
self.setModel(self.file_system) | |
self.setRootIndex(self.file_system.index(path)) | |
return None | |
def open_path_at(self, index:QModelIndex): | |
path = self.file_system.filePath(index) | |
self.viewer.add_image(io.imread(path)) | |
return None | |
def onDoubleClicked(self, index:QModelIndex): | |
path = self.file_system.filePath(index) | |
if os.path.isfile(path): | |
self.open_path_at(index) | |
else: | |
return None | |
def keyPressEvent(self, event): | |
if event.key() == Qt.Key_Return: | |
index = self.selected | |
index is None or self.onDoubleClicked(index) | |
else: | |
return super().keyPressEvent(event) | |
@property | |
def selected(self) -> QModelIndex: | |
inds = self.selectionModel().selectedIndexes() | |
if len(inds) > 0: | |
index = inds[0] | |
else: | |
index = None | |
return index | |
if __name__ == "__main__": | |
viewer = napari.Viewer() | |
ex = Explorer(viewer) | |
viewer.window.add_dock_widget(ex) | |
napari.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment