From daf49efa04cd0991ec5fb7b3d062e1dd9d90d835 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 14 Feb 2016 12:15:57 +0100 Subject: [PATCH 1/8] gui: rough conversion to the Qt docking system --- artiq/frontend/artiq_gui.py | 48 ++++++++++++-------------- artiq/gui/applets.py | 46 ++++++++++++------------- artiq/gui/datasets.py | 14 ++++---- artiq/gui/experiments.py | 68 ++++++++++++++++++++++--------------- artiq/gui/explorer.py | 25 ++++++++------ artiq/gui/log.py | 35 ++++++++++++------- artiq/gui/moninj.py | 11 +++--- artiq/gui/schedule.py | 11 +++--- artiq/gui/shortcuts.py | 31 ++++++++++------- 9 files changed, 159 insertions(+), 130 deletions(-) diff --git a/artiq/frontend/artiq_gui.py b/artiq/frontend/artiq_gui.py index 4de976196..1a882c45e 100755 --- a/artiq/frontend/artiq_gui.py +++ b/artiq/frontend/artiq_gui.py @@ -6,11 +6,8 @@ import atexit import os import PyQt5 -from quamash import QEventLoop, QtGui, QtCore +from quamash import QEventLoop, QtGui, QtCore, QtWidgets assert QtGui is PyQt5.QtGui -# pyqtgraph will pick up any already imported Qt binding. -from pyqtgraph import dockarea - from artiq import __artiq_dir__ as artiq_dir from artiq.tools import * @@ -88,33 +85,30 @@ def main(): sub_clients[notifier_name] = subscriber # initialize main window - win = MainWindow(args.server) - dock_area = dockarea.DockArea() - smgr.register(dock_area) - smgr.register(win) - win.setCentralWidget(dock_area) + main_window = MainWindow(args.server) + smgr.register(main_window) status_bar = QtGui.QStatusBar() status_bar.showMessage("Connected to {}".format(args.server)) - win.setStatusBar(status_bar) + main_window.setStatusBar(status_bar) # create UI components - expmgr = experiments.ExperimentManager(status_bar, dock_area, + expmgr = experiments.ExperimentManager(main_window, sub_clients["explist"], sub_clients["schedule"], rpc_clients["schedule"], rpc_clients["experiment_db"]) smgr.register(expmgr) - d_shortcuts = shortcuts.ShortcutsDock(win, expmgr) + d_shortcuts = shortcuts.ShortcutsDock(main_window, expmgr) smgr.register(d_shortcuts) d_explorer = explorer.ExplorerDock(status_bar, expmgr, d_shortcuts, sub_clients["explist"], rpc_clients["schedule"], rpc_clients["experiment_db"]) - d_datasets = datasets.DatasetsDock(win, sub_clients["datasets"], + d_datasets = datasets.DatasetsDock(sub_clients["datasets"], rpc_clients["dataset_db"]) - d_applets = applets.AppletsDock(dock_area, sub_clients["datasets"]) + d_applets = applets.AppletsDock(main_window, sub_clients["datasets"]) atexit_register_coroutine(d_applets.stop) smgr.register(d_applets) @@ -126,21 +120,21 @@ def main(): d_schedule = schedule.ScheduleDock( status_bar, rpc_clients["schedule"], sub_clients["schedule"]) - logmgr = log.LogDockManager(dock_area, sub_clients["log"]) + logmgr = log.LogDockManager(main_window, sub_clients["log"]) smgr.register(logmgr) # lay out docks if os.name != "nt": - dock_area.addDock(d_ttl_dds.dds_dock, "top") - dock_area.addDock(d_ttl_dds.ttl_dock, "above", d_ttl_dds.dds_dock) - dock_area.addDock(d_applets, "above", d_ttl_dds.ttl_dock) - dock_area.addDock(d_datasets, "above", d_applets) + main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_ttl_dds.dds_dock) + main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_ttl_dds.ttl_dock) + main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_applets) + main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_datasets) else: - dock_area.addDock(d_applets, "top") - dock_area.addDock(d_datasets, "above", d_applets) - dock_area.addDock(d_shortcuts, "above", d_datasets) - dock_area.addDock(d_explorer, "above", d_shortcuts) - dock_area.addDock(d_schedule, "bottom") + main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_applets) + main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_datasets) + main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d_shortcuts) + main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d_explorer) + main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d_schedule) # load/initialize state smgr.load() @@ -150,11 +144,11 @@ def main(): # create first log dock if not already in state d_log0 = logmgr.first_log_dock() if d_log0 is not None: - dock_area.addDock(d_log0, "right", d_explorer) + main_window.addDockWidget(QtCore.Qt.TopDockWidgetArea, d_log0) # run - win.show() - loop.run_until_complete(win.exit_request.wait()) + main_window.show() + loop.run_until_complete(main_window.exit_request.wait()) if __name__ == "__main__": main() diff --git a/artiq/gui/applets.py b/artiq/gui/applets.py index 811713f42..9507c87c3 100644 --- a/artiq/gui/applets.py +++ b/artiq/gui/applets.py @@ -5,7 +5,6 @@ import shlex from functools import partial from quamash import QtCore, QtGui, QtWidgets -from pyqtgraph import dockarea from artiq.protocols.pipe_ipc import AsyncioParentComm from artiq.protocols import pyon @@ -85,12 +84,13 @@ class AppletIPCServer(AsyncioParentComm): await asyncio.wait([self.server_task]) -class AppletDock(dockarea.Dock): +class AppletDock(QtWidgets.QDockWidget): + sigClosed = QtCore.pyqtSignal() + def __init__(self, datasets_sub, uid, name, command): - dockarea.Dock.__init__(self, "applet" + str(uid), - label="Applet: " + name, - closable=True) - self.setMinimumSize(QtCore.QSize(500, 400)) + QtWidgets.QDockWidget.__init__(self, "Applet: " + name) + self.setObjectName("applet" + str(uid)) + self.datasets_sub = datasets_sub self.applet_name = name self.command = command @@ -99,7 +99,7 @@ class AppletDock(dockarea.Dock): def rename(self, name): self.applet_name = name - self.label.setText("Applet: " + name) + self.setWindowTitle("Applet: " + name) async def start(self): if self.starting_stopping: @@ -127,7 +127,7 @@ class AppletDock(dockarea.Dock): self.embed_window = QtGui.QWindow.fromWinId(win_id) self.embed_widget = QtWidgets.QWidget.createWindowContainer( self.embed_window) - self.addWidget(self.embed_widget) + self.setWidget(self.embed_widget) # HACK: This function would not be needed if Qt window embedding # worked correctly. @@ -164,6 +164,10 @@ class AppletDock(dockarea.Dock): await self.terminate() await self.start() + def closeEvent(self, event): + QtWidgets.QDockWidget.closeEvent(self, event) + self.sigClosed.emit() + _templates = [ ("Big number", "{python} -m artiq.applets.big_number " @@ -181,16 +185,16 @@ _templates = [ ] -class AppletsDock(dockarea.Dock): - def __init__(self, dock_area, datasets_sub): - self.dock_area = dock_area +class AppletsDock(QtWidgets.QDockWidget): + def __init__(self, main_window, datasets_sub): + QtWidgets.QDockWidget.__init__(self, "Applets") + self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFloatable) + + self.main_window = main_window self.datasets_sub = datasets_sub self.dock_to_checkbox = dict() self.applet_uids = set() - self.workaround_pyqtgraph_bug = False - - dockarea.Dock.__init__(self, "Applets") - self.setMinimumSize(QtCore.QSize(850, 450)) self.table = QtWidgets.QTableWidget(0, 3) self.table.setHorizontalHeaderLabels(["Enable", "Name", "Command"]) @@ -203,7 +207,7 @@ class AppletsDock(dockarea.Dock): QtGui.QHeaderView.ResizeToContents) self.table.verticalHeader().hide() self.table.setTextElideMode(QtCore.Qt.ElideNone) - self.addWidget(self.table) + self.setWidget(self.table) self.table.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) new_action = QtGui.QAction("New applet", self.table) @@ -232,12 +236,8 @@ class AppletsDock(dockarea.Dock): def create(self, uid, name, command): dock = AppletDock(self.datasets_sub, uid, name, command) - # If a dock is floated and then dock state is restored, pyqtgraph - # leaves a "phantom" window open. - if self.workaround_pyqtgraph_bug: - self.dock_area.addDock(dock) - else: - self.dock_area.floatDock(dock) + self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) + dock.setFloating(True) asyncio.ensure_future(dock.start()) dock.sigClosed.connect(partial(self.on_dock_closed, dock)) return dock @@ -340,7 +340,6 @@ class AppletsDock(dockarea.Dock): return state def restore_state(self, state): - self.workaround_pyqtgraph_bug = True for uid, enabled, name, command in state: row = self.new(uid) item = QtWidgets.QTableWidgetItem() @@ -351,4 +350,3 @@ class AppletsDock(dockarea.Dock): self.table.setItem(row, 2, item) if enabled: self.table.item(row, 0).setCheckState(QtCore.Qt.Checked) - self.workaround_pyqtgraph_bug = False diff --git a/artiq/gui/datasets.py b/artiq/gui/datasets.py index ccb0c19f3..50f4e60b8 100644 --- a/artiq/gui/datasets.py +++ b/artiq/gui/datasets.py @@ -3,8 +3,7 @@ from collections import OrderedDict from functools import partial import logging -from quamash import QtGui, QtCore -from pyqtgraph import dockarea +from quamash import QtGui, QtCore, QtWidgets from pyqtgraph import LayoutWidget from artiq.tools import short_format @@ -29,14 +28,15 @@ class Model(DictSyncTreeSepModel): raise ValueError -class DatasetsDock(dockarea.Dock): - def __init__(self, dialog_parent, datasets_sub, dataset_ctl): - dockarea.Dock.__init__(self, "Datasets") - self.dialog_parent = dialog_parent +class DatasetsDock(QtWidgets.QDockWidget): + def __init__(self, datasets_sub, dataset_ctl): + QtWidgets.QDockWidget.__init__(self, "Datasets") + self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFloatable) self.dataset_ctl = dataset_ctl grid = LayoutWidget() - self.addWidget(grid) + self.setWidget(grid) self.search = QtGui.QLineEdit() self.search.setPlaceholderText("search...") diff --git a/artiq/gui/experiments.py b/artiq/gui/experiments.py index 8b8b90590..5a964df1c 100644 --- a/artiq/gui/experiments.py +++ b/artiq/gui/experiments.py @@ -3,9 +3,9 @@ import asyncio from functools import partial from collections import OrderedDict -from quamash import QtGui, QtCore +from quamash import QtGui, QtCore, QtWidgets -from pyqtgraph import dockarea, LayoutWidget +from pyqtgraph import LayoutWidget from artiq.gui.tools import log_level_to_name from artiq.gui.entries import argty_to_entry @@ -133,10 +133,16 @@ class _ArgumentEditor(QtGui.QTreeWidget): pass -class _ExperimentDock(dockarea.Dock): +class _ExperimentDock(QtWidgets.QDockWidget): + sigClosed = QtCore.pyqtSignal() + def __init__(self, manager, expurl): - dockarea.Dock.__init__(self, "Exp: " + expurl, closable=True) - self.setMinimumSize(QtCore.QSize(740, 470)) + QtWidgets.QDockWidget.__init__(self, "Exp: " + expurl) + + self.layout = QtWidgets.QGridLayout() + top_widget = QtWidgets.QWidget() + top_widget.setLayout(self.layout) + self.setWidget(top_widget) self.layout.setSpacing(5) self.layout.setContentsMargins(5, 5, 5, 5) @@ -144,7 +150,7 @@ class _ExperimentDock(dockarea.Dock): self.expurl = expurl self.argeditor = _ArgumentEditor(self.manager, self, self.expurl) - self.addWidget(self.argeditor, 0, 0, colspan=5) + self.layout.addWidget(self.argeditor, 0, 0, 1, 5) self.layout.setRowStretch(0, 1) scheduling = manager.get_submission_scheduling(expurl) @@ -153,8 +159,8 @@ class _ExperimentDock(dockarea.Dock): datetime = QtGui.QDateTimeEdit() datetime.setDisplayFormat("MMM d yyyy hh:mm:ss") datetime_en = QtGui.QCheckBox("Due date:") - self.addWidget(datetime_en, 1, 0) - self.addWidget(datetime, 1, 1) + self.layout.addWidget(datetime_en, 1, 0) + self.layout.addWidget(datetime, 1, 1) if scheduling["due_date"] is None: datetime.setDate(QtCore.QDate.currentDate()) @@ -175,8 +181,8 @@ class _ExperimentDock(dockarea.Dock): datetime_en.stateChanged.connect(update_datetime_en) pipeline_name = QtGui.QLineEdit() - self.addWidget(QtGui.QLabel("Pipeline:"), 1, 2) - self.addWidget(pipeline_name, 1, 3) + self.layout.addWidget(QtGui.QLabel("Pipeline:"), 1, 2) + self.layout.addWidget(pipeline_name, 1, 3) pipeline_name.setText(scheduling["pipeline_name"]) def update_pipeline_name(text): @@ -185,8 +191,8 @@ class _ExperimentDock(dockarea.Dock): priority = QtGui.QSpinBox() priority.setRange(-99, 99) - self.addWidget(QtGui.QLabel("Priority:"), 2, 0) - self.addWidget(priority, 2, 1) + self.layout.addWidget(QtGui.QLabel("Priority:"), 2, 0) + self.layout.addWidget(priority, 2, 1) priority.setValue(scheduling["priority"]) def update_priority(value): @@ -195,7 +201,7 @@ class _ExperimentDock(dockarea.Dock): flush = QtGui.QCheckBox("Flush") flush.setToolTip("Flush the pipeline before starting the experiment") - self.addWidget(flush, 2, 2, colspan=2) + self.layout.addWidget(flush, 2, 2, 1, 2) flush.setChecked(scheduling["flush"]) def update_flush(checked): @@ -209,8 +215,8 @@ class _ExperimentDock(dockarea.Dock): log_level.setToolTip("Minimum level for log entry production") log_level_label = QtGui.QLabel("Logging level:") log_level_label.setToolTip("Minimum level for log message production") - self.addWidget(log_level_label, 3, 0) - self.addWidget(log_level, 3, 1) + self.layout.addWidget(log_level_label, 3, 0) + self.layout.addWidget(log_level, 3, 1) log_level.setCurrentIndex(log_levels.index( log_level_to_name(options["log_level"]))) @@ -224,8 +230,8 @@ class _ExperimentDock(dockarea.Dock): repo_rev_label = QtGui.QLabel("Revision:") repo_rev_label.setToolTip("Experiment repository revision " "(commit ID) to use") - self.addWidget(repo_rev_label, 3, 2) - self.addWidget(repo_rev, 3, 3) + self.layout.addWidget(repo_rev_label, 3, 2) + self.layout.addWidget(repo_rev, 3, 3) if options["repo_rev"] is not None: repo_rev.setText(options["repo_rev"]) @@ -243,7 +249,7 @@ class _ExperimentDock(dockarea.Dock): submit.setShortcut("CTRL+RETURN") submit.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) - self.addWidget(submit, 1, 4, rowspan=2) + self.layout.addWidget(submit, 1, 4, 2, 1) submit.clicked.connect(self.submit_clicked) reqterm = QtGui.QPushButton("Terminate instances") @@ -253,7 +259,7 @@ class _ExperimentDock(dockarea.Dock): reqterm.setShortcut("CTRL+BACKSPACE") reqterm.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) - self.addWidget(reqterm, 3, 4) + self.layout.addWidget(reqterm, 3, 4) reqterm.clicked.connect(self.reqterm_clicked) def submit_clicked(self): @@ -287,7 +293,11 @@ class _ExperimentDock(dockarea.Dock): self.argeditor.deleteLater() self.argeditor = _ArgumentEditor(self.manager, self, self.expurl) - self.addWidget(self.argeditor, 0, 0, colspan=5) + self.layout.addWidget(self.argeditor, 0, 0, 1, 5) + + def closeEvent(self, event): + QtWidgets.QDockWidget.closeEvent(self, event) + self.sigClosed.emit() def save_state(self): return self.argeditor.save_state() @@ -297,11 +307,10 @@ class _ExperimentDock(dockarea.Dock): class ExperimentManager: - def __init__(self, status_bar, dock_area, + def __init__(self, main_window, explist_sub, schedule_sub, schedule_ctl, experiment_db_ctl): - self.status_bar = status_bar - self.dock_area = dock_area + self.main_window = main_window self.schedule_ctl = schedule_ctl self.experiment_db_ctl = experiment_db_ctl @@ -385,11 +394,12 @@ class ExperimentManager: def open_experiment(self, expurl): if expurl in self.open_experiments: dock = self.open_experiments[expurl] - self.dock_area.floatDock(dock) + dock.setFloating(True) return dock dock = _ExperimentDock(self, expurl) self.open_experiments[expurl] = dock - self.dock_area.floatDock(dock) + self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) + dock.setFloating(True) dock.sigClosed.connect(partial(self.on_dock_closed, expurl)) return dock @@ -398,7 +408,8 @@ class ExperimentManager: async def _submit_task(self, *args): rid = await self.schedule_ctl.submit(*args) - self.status_bar.showMessage("Submitted RID {}".format(rid)) + self.main_window.statusBar().showMessage( + "Submitted RID {}".format(rid)) def submit(self, expurl): file, class_name, _ = self.resolve_expurl(expurl) @@ -436,8 +447,9 @@ class ExperimentManager: rid, exc_info=True) def request_inst_term(self, expurl): - self.status_bar.showMessage("Requesting termination of all instances " - "of '{}'".format(expurl)) + self.main_window.statusBar().showMessage( + "Requesting termination of all instances " + "of '{}'".format(expurl)) file, class_name, use_repository = self.resolve_expurl(expurl) rids = [] for rid, desc in self.schedule.items(): diff --git a/artiq/gui/explorer.py b/artiq/gui/explorer.py index bdb456323..73ce6ce96 100644 --- a/artiq/gui/explorer.py +++ b/artiq/gui/explorer.py @@ -2,8 +2,7 @@ import asyncio import logging from functools import partial -from quamash import QtGui, QtCore -from pyqtgraph import dockarea +from quamash import QtGui, QtCore, QtWidgets from pyqtgraph import LayoutWidget from artiq.gui.models import DictSyncTreeSepModel @@ -116,13 +115,19 @@ class Model(DictSyncTreeSepModel): DictSyncTreeSepModel.__init__(self, "/", ["Experiment"], init) -class ExplorerDock(dockarea.Dock): +class ExplorerDock(QtWidgets.QDockWidget): def __init__(self, status_bar, exp_manager, d_shortcuts, explist_sub, schedule_ctl, experiment_db_ctl): - dockarea.Dock.__init__(self, "Explorer") - self.setMinimumSize(QtCore.QSize(300, 300)) - self.layout.setSpacing(5) - self.layout.setContentsMargins(5, 5, 5, 5) + QtWidgets.QDockWidget.__init__(self, "Explorer") + self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFloatable) + + layout = QtWidgets.QGridLayout() + top_widget = QtWidgets.QWidget() + top_widget.setLayout(layout) + self.setWidget(top_widget) + layout.setSpacing(5) + layout.setContentsMargins(5, 5, 5, 5) self.status_bar = status_bar self.exp_manager = exp_manager @@ -132,7 +137,7 @@ class ExplorerDock(dockarea.Dock): self.el = QtGui.QTreeView() self.el.setHeaderHidden(True) self.el.setSelectionBehavior(QtGui.QAbstractItemView.SelectItems) - self.addWidget(self.el, 0, 0, colspan=2) + layout.addWidget(self.el, 0, 0, 1, 2) self.el.doubleClicked.connect( partial(self.expname_action, "open_experiment")) @@ -140,7 +145,7 @@ class ExplorerDock(dockarea.Dock): open.setIcon(QtGui.QApplication.style().standardIcon( QtGui.QStyle.SP_DialogOpenButton)) open.setToolTip("Open the selected experiment (Return)") - self.addWidget(open, 1, 0) + layout.addWidget(open, 1, 0) open.clicked.connect( partial(self.expname_action, "open_experiment")) @@ -148,7 +153,7 @@ class ExplorerDock(dockarea.Dock): submit.setIcon(QtGui.QApplication.style().standardIcon( QtGui.QStyle.SP_DialogOkButton)) submit.setToolTip("Schedule the selected experiment (Ctrl+Return)") - self.addWidget(submit, 1, 1) + layout.addWidget(submit, 1, 1) submit.clicked.connect( partial(self.expname_action, "submit")) diff --git a/artiq/gui/log.py b/artiq/gui/log.py index afa981593..d853e0f1b 100644 --- a/artiq/gui/log.py +++ b/artiq/gui/log.py @@ -4,8 +4,8 @@ import time import re from functools import partial -from quamash import QtGui, QtCore -from pyqtgraph import dockarea, LayoutWidget +from quamash import QtGui, QtCore, QtWidgets +from pyqtgraph import LayoutWidget from artiq.gui.tools import log_level_to_name @@ -140,13 +140,15 @@ class _LogFilterProxyModel(QtCore.QSortFilterProxyModel): self.invalidateFilter() -class _LogDock(dockarea.Dock): +class _LogDock(QtWidgets.QDockWidget): + sigClosed = QtCore.pyqtSignal() + def __init__(self, manager, name, log_sub): - dockarea.Dock.__init__(self, name, label="Log") - self.setMinimumSize(QtCore.QSize(720, 250)) + QtWidgets.QDockWidget.__init__(self, "Log") + self.setObjectName(name) grid = LayoutWidget() - self.addWidget(grid) + self.setWidget(grid) grid.addWidget(QtGui.QLabel("Minimum level: "), 0, 0) self.filter_level = QtGui.QComboBox() @@ -252,6 +254,10 @@ class _LogDock(dockarea.Dock): self.table_model_filter.rowsInserted.connect(self.rows_inserted_after) self.table_model_filter.rowsRemoved.connect(self.rows_removed) + def closeEvent(self, event): + QtWidgets.QDockWidget.closeEvent(self, event) + self.sigClosed.emit() + def save_state(self): return { "min_level_idx": self.filter_level.currentIndex(), @@ -279,8 +285,8 @@ class _LogDock(dockarea.Dock): class LogDockManager: - def __init__(self, dock_area, log_sub): - self.dock_area = dock_area + def __init__(self, main_window, log_sub): + self.main_window = main_window self.log_sub = log_sub self.docks = dict() @@ -294,7 +300,8 @@ class LogDockManager: dock = _LogDock(self, name, self.log_sub) self.docks[name] = dock if add_to_area: - self.dock_area.floatDock(dock) + self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) + dock.setFloating(True) dock.sigClosed.connect(partial(self.on_dock_closed, name)) self.update_closable() return dock @@ -304,9 +311,12 @@ class LogDockManager: self.update_closable() def update_closable(self): - closable = len(self.docks) > 1 + flags = (QtWidgets.QDockWidget.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFloatable) + if len(self.docks) > 1: + flags |= QtWidgets.QDockWidget.DockWidgetClosable for dock in self.docks.values(): - dock.setClosable(closable) + dock.setFeatures(flags) def save_state(self): return {name: dock.save_state() for name, dock in self.docks.items()} @@ -317,8 +327,9 @@ class LogDockManager: for name, dock_state in state.items(): dock = _LogDock(self, name, self.log_sub) dock.restore_state(dock_state) - self.dock_area.addDock(dock) + self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock) self.docks[name] = dock + self.update_closable() def first_log_dock(self): if self.docks: diff --git a/artiq/gui/moninj.py b/artiq/gui/moninj.py index 8982fa297..755ceecad 100644 --- a/artiq/gui/moninj.py +++ b/artiq/gui/moninj.py @@ -4,8 +4,7 @@ import socket import struct from operator import itemgetter -from quamash import QtGui, QtCore -from pyqtgraph import dockarea +from quamash import QtGui, QtCore, QtWidgets from artiq.tools import TaskObject from artiq.protocols.sync_struct import Subscriber @@ -213,14 +212,16 @@ class _DeviceManager: return None -class _MonInjDock(dockarea.Dock): +class _MonInjDock(QtWidgets.QDockWidget): def __init__(self, name): - dockarea.Dock.__init__(self, name) + QtWidgets.QDockWidget.__init__(self, name) + self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFloatable) self.grid = QtGui.QGridLayout() gridw = QtGui.QWidget() gridw.setLayout(self.grid) - self.addWidget(gridw) + self.setWidget(gridw) def layout_widgets(self, widgets): w = self.grid.itemAt(0) diff --git a/artiq/gui/schedule.py b/artiq/gui/schedule.py index 1bac023c8..4265c5ea7 100644 --- a/artiq/gui/schedule.py +++ b/artiq/gui/schedule.py @@ -2,7 +2,7 @@ import asyncio import time from functools import partial -from quamash import QtGui, QtCore +from quamash import QtGui, QtCore, QtWidgets from pyqtgraph import dockarea from artiq.gui.models import DictSyncModel @@ -55,10 +55,11 @@ class Model(DictSyncModel): raise ValueError -class ScheduleDock(dockarea.Dock): +class ScheduleDock(QtWidgets.QDockWidget): def __init__(self, status_bar, schedule_ctl, schedule_sub): - dockarea.Dock.__init__(self, "Schedule") - self.setMinimumSize(QtCore.QSize(740, 200)) + QtWidgets.QDockWidget.__init__(self, "Schedule") + self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFloatable) self.status_bar = status_bar self.schedule_ctl = schedule_ctl @@ -71,7 +72,7 @@ class ScheduleDock(dockarea.Dock): self.table.verticalHeader().setResizeMode( QtGui.QHeaderView.ResizeToContents) self.table.verticalHeader().hide() - self.addWidget(self.table) + self.setWidget(self.table) self.table.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) request_termination_action = QtGui.QAction("Request termination", self.table) diff --git a/artiq/gui/shortcuts.py b/artiq/gui/shortcuts.py index db05bfa2b..7ffec34db 100644 --- a/artiq/gui/shortcuts.py +++ b/artiq/gui/shortcuts.py @@ -2,53 +2,60 @@ import logging from functools import partial from quamash import QtGui, QtCore, QtWidgets -from pyqtgraph import dockarea +from pyqtgraph import LayoutWidget logger = logging.getLogger(__name__) -class ShortcutsDock(dockarea.Dock): +class ShortcutsDock(QtWidgets.QDockWidget): def __init__(self, main_window, exp_manager): - dockarea.Dock.__init__(self, "Shortcuts") - self.layout.setSpacing(5) - self.layout.setContentsMargins(5, 5, 5, 5) + QtWidgets.QDockWidget.__init__(self, "Shortcuts") + self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | + QtWidgets.QDockWidget.DockWidgetFloatable) + + layout = QtWidgets.QGridLayout() + top_widget = QtWidgets.QWidget() + top_widget.setLayout(layout) + self.setWidget(top_widget) + layout.setSpacing(5) + layout.setContentsMargins(5, 5, 5, 5) self.exp_manager = exp_manager self.shortcut_widgets = dict() for n, title in enumerate(["Key", "Experiment"]): label = QtGui.QLabel("" + title + "") - self.addWidget(label, 0, n) + layout.addWidget(label, 0, n) label.setMaximumHeight(label.sizeHint().height()) - self.layout.setColumnStretch(1, 1) + layout.setColumnStretch(1, 1) for i in range(12): row = i + 1 - self.addWidget(QtGui.QLabel("F" + str(i+1)), row, 0) + layout.addWidget(QtGui.QLabel("F" + str(i+1)), row, 0) label = QtGui.QLabel() label.setSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Ignored) - self.addWidget(label, row, 1) + layout.addWidget(label, row, 1) clear = QtGui.QToolButton() clear.setIcon(QtGui.QApplication.style().standardIcon( QtGui.QStyle.SP_DialogResetButton)) - self.addWidget(clear, row, 2) + layout.addWidget(clear, row, 2) clear.clicked.connect(partial(self.set_shortcut, i, "")) open = QtGui.QToolButton() open.setIcon(QtGui.QApplication.style().standardIcon( QtGui.QStyle.SP_DialogOpenButton)) - self.addWidget(open, row, 3) + layout.addWidget(open, row, 3) open.clicked.connect(partial(self._open_experiment, i)) submit = QtGui.QPushButton("Submit") submit.setIcon(QtGui.QApplication.style().standardIcon( QtGui.QStyle.SP_DialogOkButton)) - self.addWidget(submit, row, 4) + layout.addWidget(submit, row, 4) submit.clicked.connect(partial(self._activated, i)) clear.hide() From 3c12c13a67d5082a25bcf93b0a05a788a0fc8cbb Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 14 Feb 2016 13:46:15 +0100 Subject: [PATCH 2/8] gui: dock state save/restore --- artiq/frontend/artiq_gui.py | 4 ++-- artiq/gui/applets.py | 1 + artiq/gui/datasets.py | 1 + artiq/gui/experiments.py | 4 +++- artiq/gui/explorer.py | 1 + artiq/gui/moninj.py | 1 + artiq/gui/schedule.py | 1 + artiq/gui/shortcuts.py | 1 + 8 files changed, 11 insertions(+), 3 deletions(-) diff --git a/artiq/frontend/artiq_gui.py b/artiq/frontend/artiq_gui.py index 1a882c45e..7f5394f78 100755 --- a/artiq/frontend/artiq_gui.py +++ b/artiq/frontend/artiq_gui.py @@ -47,10 +47,10 @@ class MainWindow(QtGui.QMainWindow): self.exit_request.set() def save_state(self): - return bytes(self.saveGeometry()) + return bytes(self.saveState()) def restore_state(self, state): - self.restoreGeometry(QtCore.QByteArray(state)) + self.restoreState(QtCore.QByteArray(state)) def main(): diff --git a/artiq/gui/applets.py b/artiq/gui/applets.py index 9507c87c3..ddc801726 100644 --- a/artiq/gui/applets.py +++ b/artiq/gui/applets.py @@ -188,6 +188,7 @@ _templates = [ class AppletsDock(QtWidgets.QDockWidget): def __init__(self, main_window, datasets_sub): QtWidgets.QDockWidget.__init__(self, "Applets") + self.setObjectName("Applets") self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | QtWidgets.QDockWidget.DockWidgetFloatable) diff --git a/artiq/gui/datasets.py b/artiq/gui/datasets.py index 50f4e60b8..ac0c7d430 100644 --- a/artiq/gui/datasets.py +++ b/artiq/gui/datasets.py @@ -31,6 +31,7 @@ class Model(DictSyncTreeSepModel): class DatasetsDock(QtWidgets.QDockWidget): def __init__(self, datasets_sub, dataset_ctl): QtWidgets.QDockWidget.__init__(self, "Datasets") + self.setObjectName("Datasets") self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | QtWidgets.QDockWidget.DockWidgetFloatable) self.dataset_ctl = dataset_ctl diff --git a/artiq/gui/experiments.py b/artiq/gui/experiments.py index 5a964df1c..8b81edc92 100644 --- a/artiq/gui/experiments.py +++ b/artiq/gui/experiments.py @@ -137,7 +137,9 @@ class _ExperimentDock(QtWidgets.QDockWidget): sigClosed = QtCore.pyqtSignal() def __init__(self, manager, expurl): - QtWidgets.QDockWidget.__init__(self, "Exp: " + expurl) + name = "Exp: " + expurl + QtWidgets.QDockWidget.__init__(self, name) + self.setObjectName(name) self.layout = QtWidgets.QGridLayout() top_widget = QtWidgets.QWidget() diff --git a/artiq/gui/explorer.py b/artiq/gui/explorer.py index 73ce6ce96..079b1dcbe 100644 --- a/artiq/gui/explorer.py +++ b/artiq/gui/explorer.py @@ -119,6 +119,7 @@ class ExplorerDock(QtWidgets.QDockWidget): def __init__(self, status_bar, exp_manager, d_shortcuts, explist_sub, schedule_ctl, experiment_db_ctl): QtWidgets.QDockWidget.__init__(self, "Explorer") + self.setObjectName("Explorer") self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | QtWidgets.QDockWidget.DockWidgetFloatable) diff --git a/artiq/gui/moninj.py b/artiq/gui/moninj.py index 755ceecad..32b8f9656 100644 --- a/artiq/gui/moninj.py +++ b/artiq/gui/moninj.py @@ -215,6 +215,7 @@ class _DeviceManager: class _MonInjDock(QtWidgets.QDockWidget): def __init__(self, name): QtWidgets.QDockWidget.__init__(self, name) + self.setObjectName(name) self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | QtWidgets.QDockWidget.DockWidgetFloatable) diff --git a/artiq/gui/schedule.py b/artiq/gui/schedule.py index 4265c5ea7..f43baf5ae 100644 --- a/artiq/gui/schedule.py +++ b/artiq/gui/schedule.py @@ -58,6 +58,7 @@ class Model(DictSyncModel): class ScheduleDock(QtWidgets.QDockWidget): def __init__(self, status_bar, schedule_ctl, schedule_sub): QtWidgets.QDockWidget.__init__(self, "Schedule") + self.setObjectName("Schedule") self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | QtWidgets.QDockWidget.DockWidgetFloatable) diff --git a/artiq/gui/shortcuts.py b/artiq/gui/shortcuts.py index 7ffec34db..9bc90c365 100644 --- a/artiq/gui/shortcuts.py +++ b/artiq/gui/shortcuts.py @@ -11,6 +11,7 @@ logger = logging.getLogger(__name__) class ShortcutsDock(QtWidgets.QDockWidget): def __init__(self, main_window, exp_manager): QtWidgets.QDockWidget.__init__(self, "Shortcuts") + self.setObjectName("Shortcuts") self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | QtWidgets.QDockWidget.DockWidgetFloatable) From 489f69f991b67fea7bfe1978dc3f9fe1f70b9fcd Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 14 Feb 2016 22:22:07 +0100 Subject: [PATCH 3/8] gui: reliable detection of dock close --- artiq/gui/applets.py | 11 +++-------- artiq/gui/experiments.py | 12 +++--------- artiq/gui/log.py | 12 +++--------- artiq/gui/tools.py | 11 ++++++++++- 4 files changed, 19 insertions(+), 27 deletions(-) diff --git a/artiq/gui/applets.py b/artiq/gui/applets.py index ddc801726..2a8732f5a 100644 --- a/artiq/gui/applets.py +++ b/artiq/gui/applets.py @@ -8,6 +8,7 @@ from quamash import QtCore, QtGui, QtWidgets from artiq.protocols.pipe_ipc import AsyncioParentComm from artiq.protocols import pyon +from artiq.gui.tools import QDockWidgetCloseDetect logger = logging.getLogger(__name__) @@ -84,11 +85,9 @@ class AppletIPCServer(AsyncioParentComm): await asyncio.wait([self.server_task]) -class AppletDock(QtWidgets.QDockWidget): - sigClosed = QtCore.pyqtSignal() - +class AppletDock(QDockWidgetCloseDetect): def __init__(self, datasets_sub, uid, name, command): - QtWidgets.QDockWidget.__init__(self, "Applet: " + name) + QDockWidgetCloseDetect.__init__(self, "Applet: " + name) self.setObjectName("applet" + str(uid)) self.datasets_sub = datasets_sub @@ -164,10 +163,6 @@ class AppletDock(QtWidgets.QDockWidget): await self.terminate() await self.start() - def closeEvent(self, event): - QtWidgets.QDockWidget.closeEvent(self, event) - self.sigClosed.emit() - _templates = [ ("Big number", "{python} -m artiq.applets.big_number " diff --git a/artiq/gui/experiments.py b/artiq/gui/experiments.py index 8b81edc92..5536c30d3 100644 --- a/artiq/gui/experiments.py +++ b/artiq/gui/experiments.py @@ -7,7 +7,7 @@ from quamash import QtGui, QtCore, QtWidgets from pyqtgraph import LayoutWidget -from artiq.gui.tools import log_level_to_name +from artiq.gui.tools import log_level_to_name, QDockWidgetCloseDetect from artiq.gui.entries import argty_to_entry @@ -133,12 +133,10 @@ class _ArgumentEditor(QtGui.QTreeWidget): pass -class _ExperimentDock(QtWidgets.QDockWidget): - sigClosed = QtCore.pyqtSignal() - +class _ExperimentDock(QDockWidgetCloseDetect): def __init__(self, manager, expurl): name = "Exp: " + expurl - QtWidgets.QDockWidget.__init__(self, name) + QDockWidgetCloseDetect.__init__(self, name) self.setObjectName(name) self.layout = QtWidgets.QGridLayout() @@ -297,10 +295,6 @@ class _ExperimentDock(QtWidgets.QDockWidget): self.argeditor = _ArgumentEditor(self.manager, self, self.expurl) self.layout.addWidget(self.argeditor, 0, 0, 1, 5) - def closeEvent(self, event): - QtWidgets.QDockWidget.closeEvent(self, event) - self.sigClosed.emit() - def save_state(self): return self.argeditor.save_state() diff --git a/artiq/gui/log.py b/artiq/gui/log.py index d853e0f1b..005fe626d 100644 --- a/artiq/gui/log.py +++ b/artiq/gui/log.py @@ -7,7 +7,7 @@ from functools import partial from quamash import QtGui, QtCore, QtWidgets from pyqtgraph import LayoutWidget -from artiq.gui.tools import log_level_to_name +from artiq.gui.tools import log_level_to_name, QDockWidgetCloseDetect def _make_wrappable(row, width=30): @@ -140,11 +140,9 @@ class _LogFilterProxyModel(QtCore.QSortFilterProxyModel): self.invalidateFilter() -class _LogDock(QtWidgets.QDockWidget): - sigClosed = QtCore.pyqtSignal() - +class _LogDock(QDockWidgetCloseDetect): def __init__(self, manager, name, log_sub): - QtWidgets.QDockWidget.__init__(self, "Log") + QDockWidgetCloseDetect.__init__(self, "Log") self.setObjectName(name) grid = LayoutWidget() @@ -254,10 +252,6 @@ class _LogDock(QtWidgets.QDockWidget): self.table_model_filter.rowsInserted.connect(self.rows_inserted_after) self.table_model_filter.rowsRemoved.connect(self.rows_removed) - def closeEvent(self, event): - QtWidgets.QDockWidget.closeEvent(self, event) - self.sigClosed.emit() - def save_state(self): return { "min_level_idx": self.filter_level.currentIndex(), diff --git a/artiq/gui/tools.py b/artiq/gui/tools.py index 5fa701d81..5de02c3a9 100644 --- a/artiq/gui/tools.py +++ b/artiq/gui/tools.py @@ -1,6 +1,6 @@ import logging -from quamash import QtCore +from PyQt5 import QtCore, QtWidgets, QtGui def log_level_to_name(level): @@ -27,3 +27,12 @@ class _WheelFilter(QtCore.QObject): def disable_scroll_wheel(widget): widget.setFocusPolicy(QtCore.Qt.StrongFocus) widget.installEventFilter(_WheelFilter(widget)) + + +class QDockWidgetCloseDetect(QtWidgets.QDockWidget): + sigClosed = QtCore.pyqtSignal() + + def event(self, event): + if isinstance(event, QtGui.QCloseEvent): + self.sigClosed.emit() + return QtWidgets.QDockWidget.event(self, event) From 579e789ad707a32d41b4ceb8c784ccb9839d8c84 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 14 Feb 2016 22:42:25 +0100 Subject: [PATCH 4/8] tools/QDockWidgetCloseDetect: simplify --- artiq/gui/tools.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/artiq/gui/tools.py b/artiq/gui/tools.py index 5de02c3a9..414cf0ef8 100644 --- a/artiq/gui/tools.py +++ b/artiq/gui/tools.py @@ -32,7 +32,6 @@ def disable_scroll_wheel(widget): class QDockWidgetCloseDetect(QtWidgets.QDockWidget): sigClosed = QtCore.pyqtSignal() - def event(self, event): - if isinstance(event, QtGui.QCloseEvent): - self.sigClosed.emit() - return QtWidgets.QDockWidget.event(self, event) + def closeEvent(self, event): + self.sigClosed.emit() + QtWidgets.QDockWidget.closeEvent(self, event) From d81ce1586939794c024447d7e28ec8628bdff0f5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 14 Feb 2016 23:04:14 +0100 Subject: [PATCH 5/8] gui: Qt wants a central widget in the main window, use explorer --- artiq/frontend/artiq_gui.py | 10 +++++----- artiq/gui/explorer.py | 11 +++-------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/artiq/frontend/artiq_gui.py b/artiq/frontend/artiq_gui.py index 7f5394f78..3772e5a5e 100755 --- a/artiq/frontend/artiq_gui.py +++ b/artiq/frontend/artiq_gui.py @@ -100,10 +100,10 @@ def main(): smgr.register(expmgr) d_shortcuts = shortcuts.ShortcutsDock(main_window, expmgr) smgr.register(d_shortcuts) - d_explorer = explorer.ExplorerDock(status_bar, expmgr, d_shortcuts, - sub_clients["explist"], - rpc_clients["schedule"], - rpc_clients["experiment_db"]) + d_explorer = explorer.Explorer(status_bar, expmgr, d_shortcuts, + sub_clients["explist"], + rpc_clients["schedule"], + rpc_clients["experiment_db"]) d_datasets = datasets.DatasetsDock(sub_clients["datasets"], rpc_clients["dataset_db"]) @@ -124,6 +124,7 @@ def main(): smgr.register(logmgr) # lay out docks + main_window.setCentralWidget(d_explorer) if os.name != "nt": main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_ttl_dds.dds_dock) main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_ttl_dds.ttl_dock) @@ -133,7 +134,6 @@ def main(): main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_applets) main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_datasets) main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d_shortcuts) - main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d_explorer) main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d_schedule) # load/initialize state diff --git a/artiq/gui/explorer.py b/artiq/gui/explorer.py index 079b1dcbe..b391b7f0e 100644 --- a/artiq/gui/explorer.py +++ b/artiq/gui/explorer.py @@ -115,18 +115,13 @@ class Model(DictSyncTreeSepModel): DictSyncTreeSepModel.__init__(self, "/", ["Experiment"], init) -class ExplorerDock(QtWidgets.QDockWidget): +class Explorer(QtWidgets.QWidget): def __init__(self, status_bar, exp_manager, d_shortcuts, explist_sub, schedule_ctl, experiment_db_ctl): - QtWidgets.QDockWidget.__init__(self, "Explorer") - self.setObjectName("Explorer") - self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | - QtWidgets.QDockWidget.DockWidgetFloatable) + QtWidgets.QWidget.__init__(self) layout = QtWidgets.QGridLayout() - top_widget = QtWidgets.QWidget() - top_widget.setLayout(layout) - self.setWidget(top_widget) + self.setLayout(layout) layout.setSpacing(5) layout.setContentsMargins(5, 5, 5, 5) From cd732718adf616cc3c4db66737f2f801470f0297 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 14 Feb 2016 23:08:14 +0100 Subject: [PATCH 6/8] gui: save/restore main window geometry --- artiq/frontend/artiq_gui.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/artiq/frontend/artiq_gui.py b/artiq/frontend/artiq_gui.py index 3772e5a5e..100b0c39c 100755 --- a/artiq/frontend/artiq_gui.py +++ b/artiq/frontend/artiq_gui.py @@ -47,10 +47,14 @@ class MainWindow(QtGui.QMainWindow): self.exit_request.set() def save_state(self): - return bytes(self.saveState()) + return { + "state": bytes(self.saveState()), + "geometry": bytes(self.saveGeometry()) + } def restore_state(self, state): - self.restoreState(QtCore.QByteArray(state)) + self.restoreGeometry(QtCore.QByteArray(state["geometry"])) + self.restoreState(QtCore.QByteArray(state["state"])) def main(): From 15515f33ef8d7321995c7ab3d38945e1be94440e Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 14 Feb 2016 23:15:18 +0100 Subject: [PATCH 7/8] gui: better default placement of docks --- artiq/frontend/artiq_gui.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/artiq/frontend/artiq_gui.py b/artiq/frontend/artiq_gui.py index 100b0c39c..6b475a0a7 100755 --- a/artiq/frontend/artiq_gui.py +++ b/artiq/frontend/artiq_gui.py @@ -131,14 +131,14 @@ def main(): main_window.setCentralWidget(d_explorer) if os.name != "nt": main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_ttl_dds.dds_dock) - main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_ttl_dds.ttl_dock) - main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_applets) - main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_datasets) + main_window.tabifyDockWidget(d_ttl_dds.dds_dock, d_ttl_dds.ttl_dock) + main_window.tabifyDockWidget(d_ttl_dds.ttl_dock, d_applets) + main_window.tabifyDockWidget(d_applets, d_datasets) else: main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_applets) - main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_datasets) - main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d_shortcuts) - main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d_schedule) + main_window.tabifyDockWidget(d_applets, d_datasets) + main_window.tabifyDockWidget(d_datasets, d_shortcuts) + main_window.addDockWidget(QtCore.Qt.BottomDockWidgetArea, d_schedule) # load/initialize state smgr.load() @@ -148,7 +148,7 @@ def main(): # create first log dock if not already in state d_log0 = logmgr.first_log_dock() if d_log0 is not None: - main_window.addDockWidget(QtCore.Qt.TopDockWidgetArea, d_log0) + main_window.tabifyDockWidget(d_shortcuts, d_log0) # run main_window.show() From 9797acc9642c050f3eec50d820025a2e5d43b0db Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 14 Feb 2016 23:27:59 +0100 Subject: [PATCH 8/8] gui/applets: prevent size from shrinking to zero when docked --- artiq/gui/applets.py | 1 + 1 file changed, 1 insertion(+) diff --git a/artiq/gui/applets.py b/artiq/gui/applets.py index 2a8732f5a..a4a29b475 100644 --- a/artiq/gui/applets.py +++ b/artiq/gui/applets.py @@ -89,6 +89,7 @@ class AppletDock(QDockWidgetCloseDetect): def __init__(self, datasets_sub, uid, name, command): QDockWidgetCloseDetect.__init__(self, "Applet: " + name) self.setObjectName("applet" + str(uid)) + self.setMinimumSize(QtCore.QSize(100, 100)) self.datasets_sub = datasets_sub self.applet_name = name