Skip to content

Instantly share code, notes, and snippets.

@hanjinliu
Created September 9, 2021 15:05
Show Gist options
  • Save hanjinliu/71fd3d090b72bcf81b94aad3e3a20fb5 to your computer and use it in GitHub Desktop.
Save hanjinliu/71fd3d090b72bcf81b94aad3e3a20fb5 to your computer and use it in GitHub Desktop.
Explorer widget
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