mirror of https://github.com/m-labs/artiq.git
dashboard: Allow moving/hiding of Schedule view columns
This is very handy to make good use of screen real estate, as e.g. file path and Git revision are often not as important to judge the state of the system at a glance – particularly, as the schedule entries can then fit on a single line each.
This commit is contained in:
parent
4e654011c3
commit
6a7926ddeb
|
@ -6,6 +6,7 @@ import logging
|
|||
from PyQt6 import QtCore, QtWidgets, QtGui
|
||||
|
||||
from artiq.gui.models import DictSyncModel
|
||||
from artiq.gui.tools import SelectableColumnTableView
|
||||
from artiq.tools import elide
|
||||
|
||||
|
||||
|
@ -66,7 +67,7 @@ class ScheduleDock(QtWidgets.QDockWidget):
|
|||
|
||||
self.schedule_ctl = schedule_ctl
|
||||
|
||||
self.table = QtWidgets.QTableView()
|
||||
self.table = SelectableColumnTableView()
|
||||
self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows)
|
||||
self.table.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.SingleSelection)
|
||||
self.table.verticalHeader().setSectionResizeMode(
|
||||
|
@ -104,6 +105,9 @@ class ScheduleDock(QtWidgets.QDockWidget):
|
|||
h.resizeSection(6, 20 * cw)
|
||||
h.resizeSection(7, 20 * cw)
|
||||
|
||||
# Allow user to reorder or disable columns.
|
||||
h.setSectionsMovable(True)
|
||||
|
||||
def set_model(self, model):
|
||||
self.table_model = model
|
||||
self.table.setModel(self.table_model)
|
||||
|
@ -154,4 +158,9 @@ class ScheduleDock(QtWidgets.QDockWidget):
|
|||
return bytes(self.table.horizontalHeader().saveState())
|
||||
|
||||
def restore_state(self, state):
|
||||
self.table.horizontalHeader().restoreState(QtCore.QByteArray(state))
|
||||
h = self.table.horizontalHeader()
|
||||
h.restoreState(QtCore.QByteArray(state))
|
||||
|
||||
# The state includes the sectionsMovable property, so set it again to be able to
|
||||
# deal with pre-existing save files from when we used not to enable it.
|
||||
h.setSectionsMovable(True)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import asyncio
|
||||
import logging
|
||||
|
||||
from PyQt6 import QtCore, QtWidgets
|
||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class DoubleClickLineEdit(QtWidgets.QLineEdit):
|
||||
|
@ -88,6 +88,51 @@ class LayoutWidget(QtWidgets.QWidget):
|
|||
self.layout.addWidget(item, row, col, rowspan, colspan)
|
||||
|
||||
|
||||
class SelectableColumnTableView(QtWidgets.QTableView):
|
||||
"""A QTableView packaged up with a header row context menu that allows users to
|
||||
show/hide columns using checkable entries.
|
||||
|
||||
By default, all columns are shown. If only one shown column remains, the entry is
|
||||
disabled to prevent a situation where no columns are shown, which might be confusing
|
||||
to the user.
|
||||
|
||||
Qt considers whether columns are shown to be part of the header state, i.e. it is
|
||||
included in saveState()/restoreState().
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.horizontalHeader().setContextMenuPolicy(
|
||||
QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
|
||||
self.horizontalHeader().customContextMenuRequested.connect(
|
||||
self.show_header_context_menu)
|
||||
|
||||
def show_header_context_menu(self, pos):
|
||||
menu = QtWidgets.QMenu(self)
|
||||
|
||||
num_columns_total = self.model().columnCount()
|
||||
num_columns_shown = sum(
|
||||
(not self.isColumnHidden(i)) for i in range(num_columns_total))
|
||||
for i in range(num_columns_total):
|
||||
name = self.model().headerData(i, QtCore.Qt.Orientation.Horizontal)
|
||||
action = QtGui.QAction(name, self)
|
||||
action.setCheckable(True)
|
||||
|
||||
is_currently_hidden = self.isColumnHidden(i)
|
||||
action.setChecked(not is_currently_hidden)
|
||||
if not is_currently_hidden:
|
||||
if num_columns_shown == 1:
|
||||
# Don't allow hiding of the last visible column.
|
||||
action.setEnabled(False)
|
||||
|
||||
action.triggered.connect(
|
||||
lambda checked, i=i: self.setColumnHidden(i, not checked))
|
||||
menu.addAction(action)
|
||||
|
||||
menu.exec(self.horizontalHeader().mapToGlobal(pos))
|
||||
|
||||
|
||||
async def get_open_file_name(parent, caption, dir, filter):
|
||||
"""like QtWidgets.QFileDialog.getOpenFileName(), but a coroutine"""
|
||||
dialog = QtWidgets.QFileDialog(parent, caption, dir, filter)
|
||||
|
|
Loading…
Reference in New Issue