diff --git a/artiq/frontend/artiq_browser.py b/artiq/frontend/artiq_browser.py index fec5a682a..70188781a 100755 --- a/artiq/frontend/artiq_browser.py +++ b/artiq/frontend/artiq_browser.py @@ -9,10 +9,8 @@ from PyQt5 import QtCore, QtGui, QtWidgets from quamash import QEventLoop from artiq import __artiq_dir__ as artiq_dir -from artiq.tools import * -from artiq.gui import (state, results, - datasets, applets) -from artiq.protocols.sync_struct import process_mod +from artiq.tools import verbosity_args, init_logger, atexit_register_coroutine +from artiq.gui import state, results, datasets, applets, models def get_argparser(): @@ -20,7 +18,7 @@ def get_argparser(): parser.add_argument( "--db-file", default="artiq_browser.pyon", help="database file for local browser settings") - parser.add_argument("PATH", nargs="?", help="browse path") + parser.add_argument("PATH", nargs="?", help="browse path or file") verbosity_args(parser) return parser @@ -66,35 +64,6 @@ class MdiArea(QtWidgets.QMdiArea): painter.drawPixmap(x, y, self.pixmap) -class LocalModelManager: - def __init__(self, model_factory, notify_cb=None): - self.model = None - self._model_factory = model_factory - self._setmodel_callbacks = [] - if notify_cb is None: - notify_cb = [] - if not isinstance(notify_cb, list): - notify_cb = [notify_cb] - self.notify_cbs = notify_cb - - def init(self, struct): - self._create_model(struct) - mod = {"action": "init", "struct": struct} - for notify_cb in self.notify_cbs: - notify_cb(mod) - - def _create_model(self, init): - self.model = self._model_factory(init) - for cb in self._setmodel_callbacks: - cb(self.model) - return self.model - - def add_setmodel_callback(self, cb): - self._setmodel_callbacks.append(cb) - if self.model is not None: - cb(self.model) - - def main(): # initialize application args = get_argparser().parse_args() @@ -106,7 +75,7 @@ def main(): atexit.register(loop.close) smgr = state.StateManager(args.db_file) - datasets_sub = LocalModelManager(datasets.Model) + datasets_sub = models.LocalModelManager(datasets.Model) # initialize main window main_window = MainWindow() @@ -118,7 +87,7 @@ def main(): mdi_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) main_window.setCentralWidget(mdi_area) - d_results = results.ResultsDock(datasets_sub) + d_results = results.ResultsBrowser(datasets_sub) smgr.register(d_results) d_applets = applets.AppletsDock(main_window, datasets_sub) @@ -129,7 +98,7 @@ def main(): None) # TODO: datsets_ctl.delete() smgr.register(d_datasets) - main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d_results) + main_window.setCentralWidget(d_results) main_window.addDockWidget(QtCore.Qt.BottomDockWidgetArea, d_applets) main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_datasets) diff --git a/artiq/gui/results.py b/artiq/gui/results.py index ef65370a7..a832093a0 100644 --- a/artiq/gui/results.py +++ b/artiq/gui/results.py @@ -1,26 +1,17 @@ import logging import h5py -from PyQt5 import QtCore, QtWidgets - -from artiq.gui.tools import LayoutWidget +from PyQt5 import QtCore, QtWidgets, QtGui logger = logging.getLogger(__name__) -class ResultsDock(QtWidgets.QDockWidget): +class ResultsBrowser(QtWidgets.QSplitter): def __init__(self, datasets): - QtWidgets.QDockWidget.__init__(self, "Results") + QtWidgets.QSplitter.__init__(self) self.datasets = datasets - self.setObjectName("Results") - self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | - QtWidgets.QDockWidget.DockWidgetFloatable) - - top_widget = LayoutWidget() - self.setWidget(top_widget) - self.rt_model = QtWidgets.QFileSystemModel() self.rt_model.setRootPath(QtCore.QDir.currentPath()) self.rt_model.setNameFilters(["*.h5"]) @@ -31,15 +22,28 @@ class ResultsDock(QtWidgets.QDockWidget): self.rt.setRootIndex(self.rt_model.index(QtCore.QDir.currentPath())) self.rt.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) self.rt.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) - top_widget.addWidget(self.rt, 0, 0) + self.rt.selectionModel().selectionChanged.connect( + self.selection_changed) + self.rt.setRootIsDecorated(False) + self.addWidget(self.rt) self.rl = QtWidgets.QListView() + self.rl.setViewMode(QtWidgets.QListView.IconMode) self.rl.setModel(self.rt_model) - self.rl.setRootIndex(self.rt_model.index(QtCore.QDir.currentPath())) - self.rl.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) - self.rl.selectionModel().selectionChanged.connect( - self.selection_changed) - top_widget.addWidget(self.rl, 0, 1) + self.rl.setSelectionModel(self.rt.selectionModel()) + self.rl.setRootIndex(self.rt.rootIndex()) + l = QtGui.QFontMetrics(self.font()).lineSpacing() + self.rl.setIconSize(QtCore.QSize(20*l, 20*l)) + self.addWidget(self.rl) + + def showEvent(self, ev): + if hasattr(self, "_shown"): + return + self._shown = True + self.rt.hideColumn(1) + self.rt.hideColumn(2) + self.rt.hideColumn(3) + self.rt.scrollTo(self.rt.selectionModel().currentIndex()) def selection_changed(self, selected, deselected): indexes = selected.indexes() @@ -50,24 +54,23 @@ class ResultsDock(QtWidgets.QDockWidget): try: with h5py.File(path, "r") as f: rd = {} - for k in f["datasets"]: + for k in f: #["datasets"]: rd[k] = False, f[k].value self.datasets.init(rd) except: pass def select(self, path): - s = self.rt_model.index(path) self.rt.selectionModel().setCurrentIndex( - s, + self.rt_model.index(path), QtCore.QItemSelectionModel.ClearAndSelect) - self.rt.scrollTo(s) # TODO: call_soon? def save_state(self): return { "selected": self.rt_model.filePath( self.rt.selectionModel().currentIndex()), "header": bytes(self.rt.header().saveState()), + "splitter": bytes(self.saveState()), } def restore_state(self, state): @@ -77,3 +80,6 @@ class ResultsDock(QtWidgets.QDockWidget): header = state.get("header") if header: self.rt.header().restoreState(QtCore.QByteArray(header)) + splitter = state.get("splitter") + if splitter: + self.restoreState(QtCore.QByteArray(splitter))