2016-04-04 23:37:51 +08:00
|
|
|
import logging
|
2016-04-06 22:15:51 +08:00
|
|
|
import os
|
2016-04-04 23:37:51 +08:00
|
|
|
|
2016-04-05 15:51:04 +08:00
|
|
|
import h5py
|
2016-04-05 17:17:02 +08:00
|
|
|
from PyQt5 import QtCore, QtWidgets, QtGui
|
2016-04-04 23:37:51 +08:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2016-04-06 02:01:25 +08:00
|
|
|
class ResultIconProvider(QtWidgets.QFileIconProvider):
|
|
|
|
def icon(self, info):
|
2016-04-06 18:16:40 +08:00
|
|
|
icon = self.hdf5_thumbnail(info)
|
|
|
|
if icon is None:
|
|
|
|
icon = QtWidgets.QFileIconProvider.icon(self, info)
|
|
|
|
return icon
|
|
|
|
|
|
|
|
def hdf5_thumbnail(self, info):
|
|
|
|
if not (info.isFile() and info.isReadable() and
|
|
|
|
info.suffix() == "h5"):
|
|
|
|
return
|
2016-04-08 11:44:37 +08:00
|
|
|
try:
|
|
|
|
f = h5py.File(info.filePath(), "r")
|
|
|
|
except:
|
|
|
|
return
|
|
|
|
with f:
|
|
|
|
try:
|
|
|
|
t = f["datasets/thumbnail"]
|
|
|
|
except KeyError:
|
|
|
|
return
|
|
|
|
try:
|
|
|
|
img = QtGui.QImage.fromData(t.value)
|
|
|
|
except:
|
|
|
|
logger.warning("unable to read thumbnail", exc_info=True)
|
2016-04-06 18:16:40 +08:00
|
|
|
return
|
|
|
|
pix = QtGui.QPixmap.fromImage(img)
|
|
|
|
return QtGui.QIcon(pix)
|
|
|
|
|
|
|
|
|
2016-04-14 17:55:44 +08:00
|
|
|
class FilesDock(QtWidgets.QDockWidget):
|
2016-04-20 19:20:33 +08:00
|
|
|
def __init__(self, datasets, main_window, root=None):
|
2016-04-14 17:55:44 +08:00
|
|
|
QtWidgets.QDockWidget.__init__(self, "Files")
|
|
|
|
self.setObjectName("Files")
|
2016-04-10 16:22:24 +08:00
|
|
|
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
|
|
|
|
QtWidgets.QDockWidget.DockWidgetFloatable)
|
|
|
|
|
|
|
|
self.splitter = QtWidgets.QSplitter()
|
|
|
|
self.setWidget(self.splitter)
|
2016-04-05 15:51:04 +08:00
|
|
|
|
2016-04-20 19:20:33 +08:00
|
|
|
if root is None:
|
|
|
|
root = QtCore.QDir.currentPath()
|
|
|
|
|
2016-04-05 15:51:04 +08:00
|
|
|
self.datasets = datasets
|
2016-04-10 20:07:46 +08:00
|
|
|
self.main_window = main_window
|
2016-04-05 15:51:04 +08:00
|
|
|
|
2016-04-06 22:15:51 +08:00
|
|
|
self.rt_model = QtWidgets.QFileSystemModel()
|
|
|
|
self.rt_model.setFilter(QtCore.QDir.NoDotAndDotDot |
|
2016-04-20 19:20:33 +08:00
|
|
|
QtCore.QDir.AllDirs)
|
2016-04-04 23:37:51 +08:00
|
|
|
|
|
|
|
self.rt = QtWidgets.QTreeView()
|
|
|
|
self.rt.setModel(self.rt_model)
|
2016-04-20 19:20:33 +08:00
|
|
|
self.rt.setRootIndex(self.rt_model.setRootPath(root))
|
2016-04-05 15:51:04 +08:00
|
|
|
self.rt.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
|
|
|
self.rt.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
|
2016-04-06 15:45:13 +08:00
|
|
|
self.rt.selectionModel().currentChanged.connect(
|
2016-04-06 18:16:40 +08:00
|
|
|
self.tree_current_changed)
|
2016-04-20 19:20:33 +08:00
|
|
|
self.rt.setRootIsDecorated(False)
|
2016-04-10 16:22:24 +08:00
|
|
|
self.splitter.addWidget(self.rt)
|
2016-04-05 16:05:53 +08:00
|
|
|
|
|
|
|
self.rl = QtWidgets.QListView()
|
2016-04-05 17:17:02 +08:00
|
|
|
self.rl.setViewMode(QtWidgets.QListView.IconMode)
|
|
|
|
l = QtGui.QFontMetrics(self.font()).lineSpacing()
|
2016-04-06 18:16:40 +08:00
|
|
|
self.rl.setIconSize(QtCore.QSize(20*l, 15*l))
|
2016-04-06 15:45:13 +08:00
|
|
|
self.rl.setFlow(QtWidgets.QListView.LeftToRight)
|
2016-04-06 18:16:40 +08:00
|
|
|
self.rl.setWrapping(True)
|
2016-04-06 22:15:51 +08:00
|
|
|
self.tree_current_changed(self.rt.currentIndex(), None)
|
2016-04-10 16:22:24 +08:00
|
|
|
self.splitter.addWidget(self.rl)
|
2016-04-05 17:17:02 +08:00
|
|
|
|
2016-04-20 19:20:33 +08:00
|
|
|
def showEvent(self, ev):
|
|
|
|
self.rt.hideColumn(1)
|
|
|
|
self.rt.hideColumn(2)
|
|
|
|
self.rt.hideColumn(3)
|
2016-04-04 23:37:51 +08:00
|
|
|
|
2016-04-06 18:16:40 +08:00
|
|
|
def tree_current_changed(self, current, previous):
|
2016-04-06 22:15:51 +08:00
|
|
|
path = self.rt_model.filePath(current)
|
2016-04-10 20:07:46 +08:00
|
|
|
# create a new model for the ListView here
|
2016-04-06 22:15:51 +08:00
|
|
|
self.rl_model = QtWidgets.QFileSystemModel()
|
|
|
|
self.rl_model.setFilter(QtCore.QDir.Files)
|
|
|
|
self.rl_model.setNameFilters(["*.h5"])
|
|
|
|
self.rl_model.setNameFilterDisables(False)
|
|
|
|
self.rl_model.setIconProvider(ResultIconProvider())
|
|
|
|
self.rl.setModel(self.rl_model)
|
|
|
|
self.rl.setRootIndex(self.rl_model.setRootPath(path))
|
|
|
|
self.rl.selectionModel().currentChanged.connect(
|
|
|
|
self.list_current_changed)
|
2016-04-06 18:16:40 +08:00
|
|
|
|
|
|
|
def list_current_changed(self, current, previous):
|
2016-04-06 22:15:51 +08:00
|
|
|
info = self.rl_model.fileInfo(current)
|
2016-04-06 15:45:13 +08:00
|
|
|
logger.info("opening %s", info.filePath())
|
2016-04-06 18:16:40 +08:00
|
|
|
if not (info.isFile() and info.isReadable() and
|
|
|
|
info.suffix() == "h5"):
|
|
|
|
return
|
2016-04-08 11:44:37 +08:00
|
|
|
try:
|
|
|
|
f = h5py.File(info.filePath(), "r")
|
|
|
|
except:
|
|
|
|
logger.warning("unable to read HDF5 file", exc_info=True)
|
2016-04-08 11:54:49 +08:00
|
|
|
return
|
2016-04-08 11:44:37 +08:00
|
|
|
with f:
|
2016-04-06 18:16:40 +08:00
|
|
|
rd = {}
|
2016-04-08 11:44:37 +08:00
|
|
|
try:
|
|
|
|
group = f["datasets"]
|
|
|
|
except KeyError:
|
2016-04-06 18:16:40 +08:00
|
|
|
return
|
2016-04-08 11:44:37 +08:00
|
|
|
for k in f["datasets"]:
|
2016-04-06 18:16:40 +08:00
|
|
|
rd[k] = True, group[k].value
|
|
|
|
self.datasets.init(rd)
|
2016-04-04 23:37:51 +08:00
|
|
|
|
2016-04-20 19:20:33 +08:00
|
|
|
def select(self, path):
|
2016-04-20 16:38:35 +08:00
|
|
|
idx = self.rt_model.index(os.path.dirname(path))
|
2016-04-20 19:20:33 +08:00
|
|
|
self.rt.expand(idx)
|
|
|
|
self.rt.scrollTo(idx)
|
|
|
|
self.rt.setCurrentIndex(idx)
|
|
|
|
self.rl.setCurrentIndex(self.rl_model.index(path))
|
2016-04-04 23:37:51 +08:00
|
|
|
|
|
|
|
def save_state(self):
|
|
|
|
return {
|
2016-04-20 19:20:33 +08:00
|
|
|
"selected": self.rl_model.filePath(self.rt.currentIndex()),
|
|
|
|
"header": bytes(self.rt.header().saveState()),
|
2016-04-10 16:22:24 +08:00
|
|
|
"splitter": bytes(self.splitter.saveState()),
|
2016-04-04 23:37:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
def restore_state(self, state):
|
2016-04-20 16:38:35 +08:00
|
|
|
selected = state.get("selected")
|
|
|
|
if selected:
|
|
|
|
self.select(selected)
|
|
|
|
header = state.get("header")
|
|
|
|
if header:
|
|
|
|
self.rt.header().restoreState(QtCore.QByteArray(header))
|
|
|
|
splitter = state.get("splitter")
|
|
|
|
if splitter:
|
|
|
|
self.splitter.restoreState(QtCore.QByteArray(splitter))
|