Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c80510287b92
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 40b47b844011
Choose a head ref
  • 7 commits
  • 2 files changed
  • 1 contributor

Commits on Apr 20, 2016

  1. Copy the full SHA
    1f92e03 View commit details
  2. Revert "browser: simplify and fix state restore"

    This reverts commit b00089c.
    jordens committed Apr 20, 2016
    Copy the full SHA
    f09bfa2 View commit details
  3. 6
    Copy the full SHA
    686f670 View commit details
  4. browser: expid from h5

    jordens committed Apr 20, 2016
    Copy the full SHA
    ba24bbc View commit details
  5. browser: double click

    jordens committed Apr 20, 2016
    2
    Copy the full SHA
    0b1b99b View commit details
  6. Copy the full SHA
    5ebdd5c View commit details
  7. browser: robustify loading

    jordens committed Apr 20, 2016
    Copy the full SHA
    40b47b8 View commit details
Showing with 130 additions and 87 deletions.
  1. +124 −84 artiq/browser/files.py
  2. +6 −3 artiq/frontend/artiq_browser.py
208 changes: 124 additions & 84 deletions artiq/browser/files.py
Original file line number Diff line number Diff line change
@@ -4,23 +4,34 @@
import h5py
from PyQt5 import QtCore, QtWidgets, QtGui

from artiq.protocols import pyon

logger = logging.getLogger(__name__)


class ResultIconProvider(QtWidgets.QFileIconProvider):
def open_h5(info):
if not (info.isFile() and info.isReadable() and
info.suffix() == "h5"):
return
try:
f = h5py.File(info.filePath(), "r")
except:
logger.warning("unable to read HDF5 file %s", info.filePath(),
exc_info=True)
return
return f


class ThumbnailIconProvider(QtWidgets.QFileIconProvider):
def icon(self, info):
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
try:
f = h5py.File(info.filePath(), "r")
except:
f = open_h5(info)
if not f:
return
with f:
try:
@@ -30,122 +41,151 @@ def hdf5_thumbnail(self, info):
try:
img = QtGui.QImage.fromData(t.value)
except:
logger.warning("unable to read thumbnail", exc_info=True)
logger.warning("unable to read thumbnail from %s",
info.filePath(), exc_info=True)
return
pix = QtGui.QPixmap.fromImage(img)
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):
def __init__(self, datasets, main_window, path):
def __init__(self, datasets, main_window, root=""):
QtWidgets.QDockWidget.__init__(self, "Files")
self.setObjectName("Files")
self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable |
QtWidgets.QDockWidget.DockWidgetFloatable)
self.setFeatures(self.DockWidgetMovable | self.DockWidgetFloatable)

self.splitter = QtWidgets.QSplitter()
self.setWidget(self.splitter)

self.datasets = datasets
self.main_window = main_window

self.rt_model = QtWidgets.QFileSystemModel()
self.rt_model.setFilter(QtCore.QDir.NoDotAndDotDot |
QtCore.QDir.AllDirs | QtCore.QDir.Drives)
self.model = QtWidgets.QFileSystemModel()
self.model.setFilter(QtCore.QDir.Drives | QtCore.QDir.NoDotAndDotDot |
QtCore.QDir.AllDirs | QtCore.QDir.Files)
self.model.setNameFilterDisables(False)
self.model.setIconProvider(ThumbnailIconProvider())

self.rt = QtWidgets.QTreeView()
self.rt.setModel(self.rt_model)
self.rt.setRootIndex(self.rt_model.setRootPath(""))
self.rt.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.rt.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
rt_model = DirsOnlyProxy()
rt_model.setDynamicSortFilter(True)
rt_model.setSourceModel(self.model)
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.tree_current_changed)
self.rt.hideColumn(1)
self.rt.hideColumn(2)
self.rt.hideColumn(3)
self.rt.setRootIsDecorated(False)
for i in range(1, 4):
self.rt.hideColumn(i)
self.splitter.addWidget(self.rt)

self.rl = QtWidgets.QListView()
self.rl.setViewMode(QtWidgets.QListView.IconMode)
self.rl.setViewMode(self.rl.IconMode)
l = QtGui.QFontMetrics(self.font()).lineSpacing()
self.rl.setIconSize(QtCore.QSize(20*l, 15*l))
self.rl.setFlow(QtWidgets.QListView.LeftToRight)
self.rl.setFlow(self.rl.LeftToRight)
self.rl.setWrapping(True)
self.rl.setResizeMode(QtWidgets.QListView.Adjust)
self.tree_current_changed(self.rt.currentIndex(), None)
self.rl.activated.connect(self.open_experiment)
self.rl.setModel(self.model)
self.rl.selectionModel().currentChanged.connect(
self.list_current_changed)
self.rl.doubleClicked.connect(self.double_clicked)
self.splitter.addWidget(self.rl)

if path is not None:
self.select(path)
self.already_selected = True
else:
self.already_selected = False

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.list_current_changed)
idx = self.rt.model().mapToSource(current)
self.rl.setRootIndex(idx)

def list_current_changed(self, current, previous):
info = self.rl_model.fileInfo(current)
logger.info("opening %s", info.filePath())
if not (info.isFile() and info.isReadable() and
info.suffix() == "h5"):
return
try:
f = h5py.File(info.filePath(), "r")
except:
logger.warning("unable to read HDF5 file", exc_info=True)
info = self.model.fileInfo(current)
f = open_h5(info)
if not f:
return
logger.info("loading datasets from %s", info.filePath())
with f:
rd = {}
try:
group = f["datasets"]
except KeyError:
if "datasets" not in f:
return
for k in f["datasets"]:
rd[k] = True, group[k].value
rd = dict((k, (True, v.value)) for k, v in f["datasets"].items())
self.datasets.init(rd)

def select(self, file_or_dir):
file_or_dir = os.path.abspath(file_or_dir)
if os.path.isdir(file_or_dir):
idx = self.rt_model.index(file_or_dir)
if idx.isValid():
self.rt.expand(idx)
self.rt.setCurrentIndex(idx)
self.rt.scrollTo(idx)
else:
idx = self.rt_model.index(os.path.dirname(file_or_dir))
if idx.isValid():
self.rt.expand(idx)
self.rt.setCurrentIndex(idx)
self.rt.scrollTo(idx)

idx = self.rl_model.index(file_or_dir)
if idx.isValid():
self.rl.setCurrentIndex(idx)
self.rl.scrollTo(idx)

def open_experiment(self, index):
print(self.rl_model.filePath(index))
def double_clicked(self, current):
info = self.model.fileInfo(current)
if info.isDir():
self.rl.setRootIndex(current)
idx = self.rt.model().mapFromSource(current)
self.rt.expand(idx)
self.rt.setCurrentIndex(idx)
return
f = open_h5(info)
if not f:
return
logger.info("loading experiment for %s", info.filePath())
with f:
if "expid" not in f:
return
expid = pyon.decode(f["expid"].value)

def select_dir(self, path):
if not os.path.exists(path):
return
idx = self.model.index(path)
if not idx.isValid():
return
self.rl.setRootIndex(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)
idx = self.rt.model().mapFromSource(idx)
self.rt.expand(idx)
self.rt.setCurrentIndex(idx)

def select_file(self, path):
if not os.path.exists(path):
return
self.select_dir(os.path.dirname(path))
idx = self.model.index(path)
if not idx.isValid():
return
self.rl.setCurrentIndex(idx)

def save_state(self):
return {
"selected": self.rl_model.filePath(self.rl.currentIndex()),
"dir": self.model.filePath(self.rl.rootIndex()),
"file": self.model.filePath(self.rl.currentIndex()),
"header": bytes(self.rt.header().saveState()),
"splitter": bytes(self.splitter.saveState()),
}

def restore_state(self, state):
self.splitter.restoreState(QtCore.QByteArray(state["splitter"]))
if not self.already_selected:
self.select(state["selected"])
dir = state.get("dir")
if dir:
self.select_dir(dir)
file = state.get("file")
if file:
self.select_file(file)
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))
9 changes: 6 additions & 3 deletions artiq/frontend/artiq_browser.py
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ def get_argparser():
"--db-file", default=default_db_file,
help="database file for local browser settings "
"(default: %(default)s)")
parser.add_argument("path", nargs="?", help="browse path or file")
parser.add_argument("PATH", nargs="?", help="browse path or file")
verbosity_args(parser)
return parser

@@ -71,7 +71,6 @@ def paintEvent(self, event):
painter.drawPixmap(x, y, self.pixmap)



def main():
# initialize application
args = get_argparser().parse_args()
@@ -91,7 +90,7 @@ def main():
status_bar = QtWidgets.QStatusBar()
main_window.setStatusBar(status_bar)

d_files = files.FilesDock(datasets_sub, main_window, args.path)
d_files = files.FilesDock(datasets_sub, main_window)
smgr.register(d_files)

d_applets = applets.AppletsDock(main_window, datasets_sub)
@@ -124,6 +123,10 @@ def main():

# run
main_window.show()

if args.PATH:
d_files.select_file(os.path.normpath(args.PATH))

loop.run_until_complete(main_window.exit_request.wait())

if __name__ == "__main__":