browser: redo tree/list models

This commit is contained in:
Robert Jördens 2016-04-17 10:34:10 +02:00
parent f09bfa258d
commit 686f670a3c
2 changed files with 74 additions and 45 deletions

View File

@ -7,7 +7,7 @@ from PyQt5 import QtCore, QtWidgets, QtGui
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class ResultIconProvider(QtWidgets.QFileIconProvider): class ThumbnailIconProvider(QtWidgets.QFileIconProvider):
def icon(self, info): def icon(self, info):
icon = self.hdf5_thumbnail(info) icon = self.hdf5_thumbnail(info)
if icon is None: if icon is None:
@ -30,14 +30,23 @@ class ResultIconProvider(QtWidgets.QFileIconProvider):
try: try:
img = QtGui.QImage.fromData(t.value) img = QtGui.QImage.fromData(t.value)
except: except:
logger.warning("unable to read thumbnail", exc_info=True) logger.warning("unable to read thumbnail from %s",
info.filePath(), exc_info=True)
return return
pix = QtGui.QPixmap.fromImage(img) pix = QtGui.QPixmap.fromImage(img)
return QtGui.QIcon(pix) return QtGui.QIcon(pix)
class DirsOnlyProxy(QtCore.QSortFilterProxyModel):
def filterAcceptsRow(self, row, parent):
idx = self.sourceModel().index(row, 0, parent)
if not self.sourceModel().fileInfo(idx).isDir():
return False
return QtCore.QSortFilterProxyModel.filterAcceptsRow(self, row, parent)
class FilesDock(QtWidgets.QDockWidget): class FilesDock(QtWidgets.QDockWidget):
def __init__(self, datasets, main_window, root=None): def __init__(self, datasets, main_window, root=""):
QtWidgets.QDockWidget.__init__(self, "Files") QtWidgets.QDockWidget.__init__(self, "Files")
self.setObjectName("Files") self.setObjectName("Files")
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
@ -46,24 +55,32 @@ class FilesDock(QtWidgets.QDockWidget):
self.splitter = QtWidgets.QSplitter() self.splitter = QtWidgets.QSplitter()
self.setWidget(self.splitter) self.setWidget(self.splitter)
if root is None:
root = QtCore.QDir.currentPath()
self.datasets = datasets self.datasets = datasets
self.main_window = main_window self.main_window = main_window
self.rt_model = QtWidgets.QFileSystemModel() self.model = QtWidgets.QFileSystemModel()
self.rt_model.setFilter(QtCore.QDir.NoDotAndDotDot | self.model.setFilter(QtCore.QDir.Drives | QtCore.QDir.NoDotAndDotDot |
QtCore.QDir.AllDirs) QtCore.QDir.AllDirs | QtCore.QDir.Files)
self.model.setNameFilterDisables(False)
self.model.setIconProvider(ThumbnailIconProvider())
self.rt = QtWidgets.QTreeView() self.rt = QtWidgets.QTreeView()
self.rt.setModel(self.rt_model) rt_model = DirsOnlyProxy()
self.rt.setRootIndex(self.rt_model.setRootPath(root)) rt_model.setDynamicSortFilter(True)
self.rt.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) rt_model.setSourceModel(self.model)
self.rt.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) self.rt.setModel(rt_model)
self.model.directoryLoaded.connect(
lambda: self.rt.resizeColumnToContents(0))
self.rt.setAnimated(False)
self.rt.setRootIndex(rt_model.mapFromSource(
self.model.setRootPath(root)))
self.rt.setSelectionBehavior(self.rt.SelectRows)
self.rt.setSelectionMode(self.rt.SingleSelection)
self.rt.selectionModel().currentChanged.connect( self.rt.selectionModel().currentChanged.connect(
self.tree_current_changed) self.tree_current_changed)
self.rt.setRootIsDecorated(False) self.rt.setRootIsDecorated(False)
for i in range(1, 4):
self.rt.hideColumn(i)
self.splitter.addWidget(self.rt) self.splitter.addWidget(self.rt)
self.rl = QtWidgets.QListView() self.rl = QtWidgets.QListView()
@ -72,29 +89,17 @@ class FilesDock(QtWidgets.QDockWidget):
self.rl.setIconSize(QtCore.QSize(20*l, 15*l)) self.rl.setIconSize(QtCore.QSize(20*l, 15*l))
self.rl.setFlow(QtWidgets.QListView.LeftToRight) self.rl.setFlow(QtWidgets.QListView.LeftToRight)
self.rl.setWrapping(True) self.rl.setWrapping(True)
self.tree_current_changed(self.rt.currentIndex(), None) self.rl.setModel(self.model)
self.splitter.addWidget(self.rl)
def showEvent(self, ev):
self.rt.hideColumn(1)
self.rt.hideColumn(2)
self.rt.hideColumn(3)
def tree_current_changed(self, current, previous):
path = self.rt_model.filePath(current)
# create a new model for the ListView here
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.rl.selectionModel().currentChanged.connect(
self.list_current_changed) self.list_current_changed)
self.splitter.addWidget(self.rl)
def tree_current_changed(self, current, previous):
idx = self.rt.model().mapToSource(current)
self.rl.setRootIndex(idx)
def list_current_changed(self, current, previous): def list_current_changed(self, current, previous):
info = self.rl_model.fileInfo(current) info = self.model.fileInfo(current)
logger.info("opening %s", info.filePath()) logger.info("opening %s", info.filePath())
if not (info.isFile() and info.isReadable() and if not (info.isFile() and info.isReadable() and
info.suffix() == "h5"): info.suffix() == "h5"):
@ -102,7 +107,8 @@ class FilesDock(QtWidgets.QDockWidget):
try: try:
f = h5py.File(info.filePath(), "r") f = h5py.File(info.filePath(), "r")
except: except:
logger.warning("unable to read HDF5 file", exc_info=True) logger.warning("unable to read HDF5 file %s", info.filePath(),
exc_info=True)
return return
with f: with f:
rd = {} rd = {}
@ -114,24 +120,47 @@ class FilesDock(QtWidgets.QDockWidget):
rd[k] = True, group[k].value rd[k] = True, group[k].value
self.datasets.init(rd) self.datasets.init(rd)
def select(self, path): def select_dir(self, path):
idx = self.rt_model.index(os.path.dirname(path)) if not os.path.exists(path):
return
idx = self.model.index(path)
self.rl.setRootIndex(idx)
idx = self.rt.model().mapFromSource(idx)
self.rt.expand(idx) self.rt.expand(idx)
self.rt.scrollTo(idx)
def scroll_when_loaded(p):
if p != path:
return
self.model.directoryLoaded.disconnect(scroll_when_loaded)
QtCore.QTimer.singleShot(
100, lambda:
self.rt.scrollTo(self.rt.model().mapFromSource(
self.model.index(path)), self.rt.PositionAtCenter))
self.model.directoryLoaded.connect(scroll_when_loaded)
self.rt.setCurrentIndex(idx) self.rt.setCurrentIndex(idx)
self.rl.setCurrentIndex(self.rl_model.index(path))
def select_file(self, path):
if not os.path.exists(path):
return
self.select_dir(os.path.dirname(path))
self.rl.setCurrentIndex(self.model.index(path))
def save_state(self): def save_state(self):
return { return {
"selected": self.rl_model.filePath(self.rt.currentIndex()), "dir": self.model.filePath(self.rt.model().mapToSource(
self.rt.currentIndex())),
"file": self.model.filePath(self.rl.currentIndex()),
"header": bytes(self.rt.header().saveState()), "header": bytes(self.rt.header().saveState()),
"splitter": bytes(self.splitter.saveState()), "splitter": bytes(self.splitter.saveState()),
} }
def restore_state(self, state): def restore_state(self, state):
selected = state.get("selected") dir = state.get("dir")
if selected: if dir:
self.select(selected) self.select_dir(dir)
file = state.get("file")
if file:
self.select_file(file)
header = state.get("header") header = state.get("header")
if header: if header:
self.rt.header().restoreState(QtCore.QByteArray(header)) self.rt.header().restoreState(QtCore.QByteArray(header))

View File

@ -71,7 +71,6 @@ class MdiArea(QtWidgets.QMdiArea):
painter.drawPixmap(x, y, self.pixmap) painter.drawPixmap(x, y, self.pixmap)
def main(): def main():
# initialize application # initialize application
args = get_argparser().parse_args() args = get_argparser().parse_args()
@ -119,14 +118,15 @@ def main():
smgr.load() smgr.load()
if args.PATH:
d_files.select(args.PATH)
smgr.start() smgr.start()
atexit_register_coroutine(smgr.stop) atexit_register_coroutine(smgr.stop)
# run # run
main_window.show() main_window.show()
if args.PATH:
d_files.select_file(os.path.normpath(args.PATH))
loop.run_until_complete(main_window.exit_request.wait()) loop.run_until_complete(main_window.exit_request.wait())
if __name__ == "__main__": if __name__ == "__main__":