Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Bliss
bliss
Commits
0fe68852
Commit
0fe68852
authored
May 28, 2021
by
Valentin Valls
Browse files
Create a table to manage stored scans
parent
5713ec6f
Changes
3
Hide whitespace changes
Inline
Side-by-side
bliss/flint/widgets/curve_plot.py
View file @
0fe68852
...
...
@@ -119,9 +119,13 @@ class CurvePlotWidget(plot_helper.PlotWidget):
plotItemSelected
=
qt
.
Signal
(
object
)
"""Emitted when a flint plot item was selected by the plot"""
scanListUpdated
=
qt
.
Signal
(
object
)
"""Emitted when the list of scans is changed"""
def
__init__
(
self
,
parent
=
None
):
super
(
CurvePlotWidget
,
self
).
__init__
(
parent
=
parent
)
self
.
__scan
:
Optional
[
scan_model
.
Scan
]
=
None
self
.
__scans
:
List
[
scan_model
.
Scan
]
=
[]
self
.
__maxScans
=
3
self
.
__flintModel
:
Optional
[
flint_model
.
FlintState
]
=
None
self
.
__plotModel
:
plot_model
.
Plot
=
None
...
...
@@ -369,6 +373,7 @@ class CurvePlotWidget(plot_helper.PlotWidget):
self
.
__aggregator
.
callbackTo
(
self
.
__transactionFinished
)
)
self
.
__plotModel
=
plotModel
self
.
__syncStyleStrategy
()
if
self
.
__plotModel
is
not
None
:
self
.
__plotModel
.
structureChanged
.
connect
(
self
.
__aggregator
.
callbackTo
(
self
.
__structureChanged
)
...
...
@@ -535,6 +540,27 @@ class CurvePlotWidget(plot_helper.PlotWidget):
self
.
__boundingY2
.
setRange
(
xMin
,
xMax
)
self
.
__boundingY2
.
setVisible
(
True
)
def
scanList
(
self
):
return
self
.
__scans
def
removeScan
(
self
,
scan
):
if
scan
is
None
:
return
if
scan
is
self
.
__scan
:
_logger
.
warning
(
"Removing the current scan is not available"
)
return
self
.
__scans
.
remove
(
scan
)
self
.
__syncStyleStrategy
()
self
.
scanListUpdated
.
emit
(
self
.
__scans
)
self
.
__redrawAllScans
()
@
property
def
__scan
(
self
):
if
len
(
self
.
__scans
)
==
0
:
return
None
else
:
return
self
.
__scans
[
0
]
def
scan
(
self
)
->
Optional
[
scan_model
.
Scan
]:
return
self
.
__scan
...
...
@@ -551,7 +577,12 @@ class CurvePlotWidget(plot_helper.PlotWidget):
self
.
__scan
.
scanFinished
.
disconnect
(
self
.
__aggregator
.
callbackTo
(
self
.
__scanFinished
)
)
self
.
__scan
=
scan
if
scan
is
not
None
:
self
.
__scans
.
insert
(
0
,
scan
)
while
len
(
self
.
__scans
)
>
self
.
__maxScans
:
del
self
.
__scans
[
-
1
]
self
.
__syncStyleStrategy
()
self
.
scanListUpdated
.
emit
(
self
.
__scans
)
if
self
.
__scan
is
not
None
:
self
.
__scan
.
scanDataUpdated
[
object
].
connect
(
self
.
__aggregator
.
callbackTo
(
self
.
__scanDataUpdated
)
...
...
@@ -569,6 +600,12 @@ class CurvePlotWidget(plot_helper.PlotWidget):
self
.
__redrawAllScans
()
self
.
__syncAxisTitle
.
trigger
()
def
__syncStyleStrategy
(
self
):
if
self
.
__plotModel
is
not
None
:
styleStrategy
=
self
.
__plotModel
.
styleStrategy
()
if
styleStrategy
is
not
None
:
styleStrategy
.
setScans
(
self
.
__scans
)
def
__cleanScanIfNeeded
(
self
,
scan
):
plotModel
=
self
.
__plotModel
if
plotModel
is
None
:
...
...
@@ -648,9 +685,10 @@ class CurvePlotWidget(plot_helper.PlotWidget):
for
scan
in
scanItems
:
self
.
__redrawScan
(
scan
.
scan
())
else
:
currentScan
=
self
.
__scan
if
currentScan
is
not
None
:
self
.
__redrawScan
(
currentScan
)
for
s
in
self
.
__scans
:
if
s
is
None
:
continue
self
.
__redrawScan
(
s
)
def
__cleanScan
(
self
,
scan
:
scan_model
.
Scan
):
items
=
self
.
__items
.
pop
(
scan
,
{})
...
...
@@ -714,10 +752,10 @@ class CurvePlotWidget(plot_helper.PlotWidget):
for
scan
in
scanItems
:
self
.
__updatePlotItem
(
item
,
scan
.
scan
())
else
:
currentScan
=
self
.
__scan
if
currentScan
is
None
:
return
self
.
__updatePlotItem
(
item
,
currentScan
)
for
s
in
self
.
__scan
s
:
if
s
is
None
:
continue
self
.
__updatePlotItem
(
item
,
s
)
if
reselect
is
not
None
:
self
.
selectPlotItem
(
reselect
)
...
...
bliss/flint/widgets/curve_plot_property.py
View file @
0fe68852
...
...
@@ -10,6 +10,7 @@ from typing import Union
from
typing
import
List
from
typing
import
Dict
from
typing
import
Optional
from
typing
import
NamedTuple
import
logging
import
functools
...
...
@@ -29,6 +30,7 @@ from bliss.flint.helper.style_helper import DefaultStyleStrategy
from
bliss.flint.utils
import
qmodelutils
from
bliss.flint.widgets.select_channel_dialog
import
SelectChannelDialog
from
.
import
delegates
from
.
import
data_views
from
.
import
_property_tree_helper
...
...
@@ -637,6 +639,60 @@ class _DataItem(_property_tree_helper.ScanRowItem):
self
.
updateError
()
class
ScanItem
(
NamedTuple
):
scan
:
scan_model
.
Scan
plotModel
:
plot_model
.
Plot
curveWidget
:
qt
.
QWidget
class
ScanTableView
(
data_views
.
VDataTableView
):
ScanNbColumn
=
0
ScanTitleColumn
=
1
ScanStartTimeColumn
=
2
ScanStyleColumn
=
3
ScanRemoveColumn
=
4
def
initLayout
(
self
):
"""Called after the model was set"""
self
.
setColumn
(
self
.
ScanNbColumn
,
title
=
"Nb"
,
delegate
=
delegates
.
ScanNumberDelegate
,
resizeMode
=
qt
.
QHeaderView
.
ResizeToContents
,
)
self
.
setColumn
(
self
.
ScanTitleColumn
,
title
=
"Title"
,
delegate
=
delegates
.
ScanTitleDelegate
,
resizeMode
=
qt
.
QHeaderView
.
Stretch
,
)
self
.
setColumn
(
self
.
ScanStartTimeColumn
,
title
=
"Time"
,
delegate
=
delegates
.
ScanStartTimeDelegate
,
resizeMode
=
qt
.
QHeaderView
.
ResizeToContents
,
)
self
.
setColumn
(
self
.
ScanStyleColumn
,
title
=
"Style"
,
delegate
=
delegates
.
StyleScanDelegate
,
resizeMode
=
qt
.
QHeaderView
.
ResizeToContents
,
)
self
.
setColumn
(
self
.
ScanRemoveColumn
,
title
=
"Remove"
,
delegate
=
delegates
.
RemoveScanDelegate
,
resizeMode
=
qt
.
QHeaderView
.
ResizeToContents
,
)
self
.
setShowGrid
(
False
)
self
.
verticalHeader
().
setVisible
(
False
)
vheader
=
self
.
verticalHeader
()
vheader
.
setDefaultSectionSize
(
30
)
vheader
.
sectionResizeMode
(
qt
.
QHeaderView
.
Fixed
)
class
CurvePlotPropertyWidget
(
qt
.
QWidget
):
NameColumn
=
0
...
...
@@ -680,12 +736,18 @@ class CurvePlotPropertyWidget(qt.QWidget):
line
.
setFrameShape
(
qt
.
QFrame
.
HLine
)
line
.
setFrameShadow
(
qt
.
QFrame
.
Sunken
)
self
.
__scanListView
=
ScanTableView
(
self
)
self
.
__scanListModel
=
data_views
.
ObjectListModel
(
self
)
self
.
__scanListView
.
setModel
(
self
.
__scanListModel
)
self
.
__scanListView
.
initLayout
()
layout
=
qt
.
QVBoxLayout
(
self
)
layout
.
setContentsMargins
(
0
,
0
,
0
,
0
)
layout
.
setSpacing
(
0
)
layout
.
addWidget
(
toolBar
)
layout
.
addWidget
(
line
)
layout
.
addWidget
(
self
.
__tree
)
layout
.
addWidget
(
self
.
__scanListView
)
def
__removeAllItems
(
self
):
if
self
.
__plotModel
is
None
:
...
...
@@ -892,21 +954,26 @@ class CurvePlotPropertyWidget(qt.QWidget):
widget
.
plotModelUpdated
.
disconnect
(
self
.
__plotModelUpdated
)
widget
.
plotItemSelected
.
disconnect
(
self
.
__selectionChangedFromPlot
)
widget
.
scanModelUpdated
.
disconnect
(
self
.
__currentScanChanged
)
widget
.
scanListUpdated
.
disconnect
(
self
.
__currentScanListChanged
)
self
.
__focusWidget
=
widget
if
self
.
__focusWidget
is
not
None
:
widget
.
plotModelUpdated
.
connect
(
self
.
__plotModelUpdated
)
widget
.
plotItemSelected
.
connect
(
self
.
__selectionChangedFromPlot
)
widget
.
scanModelUpdated
.
connect
(
self
.
__currentScanChanged
)
widget
.
scanListUpdated
.
connect
(
self
.
__currentScanListChanged
)
plotModel
=
widget
.
plotModel
()
scanModel
=
widget
.
scan
()
else
:
plotModel
=
None
scanModel
=
None
self
.
__currentScanChanged
(
scanModel
)
self
.
__currentScanListChanged
(
widget
.
scanList
())
self
.
__plotModelUpdated
(
plotModel
)
self
.
__syncScanModel
()
def
__plotModelUpdated
(
self
,
plotModel
):
self
.
setPlotModel
(
plotModel
)
self
.
__syncScanModel
()
def
setPlotModel
(
self
,
plotModel
:
plot_model
.
Plot
):
if
self
.
__plotModel
is
not
None
:
...
...
@@ -923,6 +990,20 @@ class CurvePlotPropertyWidget(qt.QWidget):
def
__currentScanChanged
(
self
,
scanModel
):
self
.
__setScan
(
scanModel
)
def
__currentScanListChanged
(
self
,
scanList
):
self
.
__syncScanModel
()
def
__syncScanModel
(
self
):
widget
=
self
.
__focusWidget
if
widget
is
None
:
return
plotModel
=
self
.
__plotModel
if
plotModel
is
None
:
return
scans
=
widget
.
scanList
()
scanList
=
[
ScanItem
(
s
,
plotModel
,
widget
)
for
s
in
scans
]
self
.
__scanListModel
.
setObjectList
(
scanList
)
def
__structureChanged
(
self
):
if
self
.
__plotModel
.
isInTransaction
():
self
.
__structureInvalidated
=
True
...
...
bliss/flint/widgets/delegates.py
View file @
0fe68852
...
...
@@ -181,6 +181,86 @@ class StyleItemDelegate(qt.QStyledItemDelegate):
editor
.
move
(
pos
)
class
RemovePropertyItemDelegate
(
qt
.
QStyledItemDelegate
):
def
__init__
(
self
,
parent
):
qt
.
QStyledItemDelegate
.
__init__
(
self
,
parent
=
parent
)
def
createEditor
(
self
,
parent
,
option
,
index
):
if
not
index
.
isValid
():
return
super
(
RemovePropertyItemDelegate
,
self
).
createEditor
(
parent
,
option
,
index
)
editor
=
RemovePlotItemButton
(
parent
=
parent
)
plotItem
=
self
.
getPlotItem
(
index
)
editor
.
setVisible
(
plotItem
is
not
None
)
return
editor
def
getPlotItem
(
self
,
index
)
->
Union
[
None
,
plot_model
.
Item
]:
plotItem
=
index
.
data
(
PlotItemRole
)
if
not
isinstance
(
plotItem
,
plot_model
.
Item
):
return
None
return
plotItem
def
setEditorData
(
self
,
editor
,
index
):
plotItem
=
self
.
getPlotItem
(
index
)
editor
.
setVisible
(
plotItem
is
not
None
)
editor
.
setPlotItem
(
plotItem
)
def
setModelData
(
self
,
editor
,
model
,
index
):
pass
class
StyleScanDelegate
(
qt
.
QStyledItemDelegate
):
"""Style delegate to display scan style.
"""
def
__init__
(
self
,
parent
=
None
,
editable
=
False
):
qt
.
QStyledItemDelegate
.
__init__
(
self
,
parent
=
parent
)
self
.
__editable
=
editable
def
createEditor
(
self
,
parent
,
option
,
index
):
if
not
index
.
isValid
():
return
super
(
StyleScanDelegate
,
self
).
createEditor
(
parent
,
option
,
index
)
editor
=
StylePropertyWidget
(
parent
)
editor
.
setEditable
(
self
.
__editable
)
editor
.
setMinimumSize
(
editor
.
sizeHint
())
self
.
__updateEditor
(
editor
,
index
)
return
editor
def
__getFirstItem
(
self
,
plotModel
:
plot_model
.
Plot
):
if
plotModel
is
None
:
return
None
for
item
in
plotModel
.
items
():
if
isinstance
(
item
,
plot_item_model
.
ScanItem
):
pass
elif
isinstance
(
item
,
plot_model
.
ComputableMixIn
):
pass
else
:
return
item
return
None
def
__updateEditor
(
self
,
editor
:
qt
.
QWidget
,
index
:
qt
.
QModelIndex
):
scanItem
=
index
.
data
(
ObjectRole
)
plotItem
=
self
.
__getFirstItem
(
scanItem
.
plotModel
)
editor
.
setScan
(
scanItem
.
scan
)
editor
.
setPlotItem
(
plotItem
)
def
setEditorData
(
self
,
editor
,
index
):
self
.
__updateEditor
(
editor
,
index
)
def
setModelData
(
self
,
editor
,
model
,
index
):
pass
def
updateEditorGeometry
(
self
,
editor
,
option
,
index
):
# Center the widget to the cell
size
=
editor
.
sizeHint
()
half
=
size
/
2
halfPoint
=
qt
.
QPoint
(
half
.
width
(),
half
.
height
()
-
1
)
pos
=
option
.
rect
.
center
()
-
halfPoint
editor
.
move
(
pos
)
class
RemovePlotItemButton
(
qt
.
QToolButton
):
def
__init__
(
self
,
parent
:
qt
.
QWidget
=
None
):
super
(
RemovePlotItemButton
,
self
).
__init__
(
parent
=
parent
)
...
...
@@ -202,30 +282,112 @@ class RemovePlotItemButton(qt.QToolButton):
self
.
__plotItem
=
plotItem
class
RemovePropertyItemDelegate
(
qt
.
QStyledItemDelegate
):
def
__init__
(
self
,
parent
):
qt
.
QStyledItemDelegate
.
__init__
(
self
,
parent
=
parent
)
class
RemoveScanButton
(
qt
.
QToolButton
):
def
__init__
(
self
,
parent
:
qt
.
QWidget
=
None
):
super
(
RemoveScanButton
,
self
).
__init__
(
parent
=
parent
)
self
.
__scan
:
Optional
[
scan_model
.
Scan
]
=
None
self
.
__plotWidget
:
Optional
[
qt
.
QWidget
]
=
None
self
.
clicked
.
connect
(
self
.
__requestRemoveScan
)
icon
=
icons
.
getQIcon
(
"flint:icons/remove-item"
)
self
.
setIcon
(
icon
)
self
.
setAutoRaise
(
True
)
def
__requestRemoveScan
(
self
):
widget
=
self
.
__plotWidget
widget
.
removeScan
(
self
.
__scan
)
def
setScan
(
self
,
scan
:
scan_model
.
Scan
):
self
.
__scan
=
scan
def
setPlotWidget
(
self
,
plotWidget
:
qt
.
QWidget
):
self
.
__plotWidget
=
plotWidget
class
RemoveScanDelegate
(
qt
.
QStyledItemDelegate
):
def
createEditor
(
self
,
parent
,
option
,
index
):
if
not
index
.
isValid
():
return
super
(
RemovePropertyItemDelegate
,
self
).
createEditor
(
parent
,
option
,
index
)
editor
=
RemovePlotItemButton
(
parent
=
parent
)
plotItem
=
self
.
getPlotItem
(
index
)
editor
.
setVisible
(
plotItem
is
not
None
)
return
super
(
RemoveScanDelegate
,
self
).
createEditor
(
parent
,
option
,
index
)
editor
=
RemoveScanButton
(
parent
=
parent
)
self
.
setEditorData
(
editor
,
index
)
return
editor
def
getPlotItem
(
self
,
index
)
->
Union
[
None
,
plot_model
.
Item
]:
plotItem
=
index
.
data
(
PlotItemRole
)
if
not
isinstance
(
plotItem
,
plot_model
.
Item
):
return
None
return
plotItem
def
setEditorData
(
self
,
editor
,
index
):
scanItem
=
index
.
data
(
ObjectRole
)
editor
.
setScan
(
scanItem
.
scan
)
editor
.
setPlotWidget
(
scanItem
.
curveWidget
)
isRemovable
=
True
if
scanItem
.
scan
is
None
or
scanItem
.
curveWidget
is
None
:
isRemovable
=
False
else
:
if
scanItem
.
scan
is
scanItem
.
curveWidget
.
scan
():
isRemovable
=
False
editor
.
setToolTip
(
"The active scan can't be removed"
)
editor
.
setEnabled
(
isRemovable
)
def
setModelData
(
self
,
editor
,
model
,
index
):
pass
class
ScanNumberDelegate
(
qt
.
QStyledItemDelegate
):
def
createEditor
(
self
,
parent
,
option
,
index
):
if
not
index
.
isValid
():
return
super
().
createEditor
(
parent
,
option
,
index
)
editor
=
qt
.
QLabel
(
parent
=
parent
)
return
editor
def
setEditorData
(
self
,
editor
,
index
):
plotItem
=
self
.
getPlotItem
(
index
)
editor
.
setVisible
(
plotItem
is
not
None
)
editor
.
setPlotItem
(
plotItem
)
scanItem
=
index
.
data
(
ObjectRole
)
scanInfo
=
scanItem
.
scan
.
scanInfo
()
scanNb
=
scanInfo
.
get
(
"scan_nb"
,
None
)
if
scanNb
is
None
:
scanNb
=
""
else
:
scanNb
=
f
"#
{
scanNb
}
"
editor
.
setText
(
scanNb
)
def
setModelData
(
self
,
editor
,
model
,
index
):
pass
class
ScanTitleDelegate
(
qt
.
QStyledItemDelegate
):
def
createEditor
(
self
,
parent
,
option
,
index
):
if
not
index
.
isValid
():
return
super
().
createEditor
(
parent
,
option
,
index
)
editor
=
qt
.
QLabel
(
parent
=
parent
)
return
editor
def
setEditorData
(
self
,
editor
,
index
):
scanItem
=
index
.
data
(
ObjectRole
)
scanInfo
=
scanItem
.
scan
.
scanInfo
()
scanTitle
=
scanInfo
.
get
(
"title"
,
None
)
if
scanTitle
is
None
:
scanTitle
=
scanInfo
.
get
(
"type"
,
None
)
if
scanTitle
is
None
:
scanTitle
=
""
editor
.
setText
(
scanTitle
)
def
setModelData
(
self
,
editor
,
model
,
index
):
pass
class
ScanStartTimeDelegate
(
qt
.
QStyledItemDelegate
):
def
createEditor
(
self
,
parent
,
option
,
index
):
if
not
index
.
isValid
():
return
super
().
createEditor
(
parent
,
option
,
index
)
editor
=
qt
.
QLabel
(
parent
=
parent
)
return
editor
def
__toStartTimeText
(
self
,
scan
:
scan_model
.
Scan
)
->
str
:
scanInfo
=
scan
.
scanInfo
()
value
=
scanInfo
.
get
(
"start_time"
,
None
)
if
value
is
None
:
return
""
return
value
.
strftime
(
"%H:%M"
)
def
setEditorData
(
self
,
editor
,
index
):
scanItem
=
index
.
data
(
ObjectRole
)
text
=
self
.
__toStartTimeText
(
scanItem
.
scan
)
editor
.
setText
(
text
)
def
setModelData
(
self
,
editor
,
model
,
index
):
pass
...
...
@@ -365,6 +527,10 @@ class StylePropertyWidget(qt.QWidget):
def
__currentScanChanged
(
self
):
self
.
__setScan
(
self
.
__flintModel
.
currentScan
())
def
setScan
(
self
,
scan
:
Union
[
None
,
scan_model
.
Scan
]):
self
.
__scan
=
scan
self
.
__update
()
def
__setScan
(
self
,
scan
:
Union
[
None
,
scan_model
.
Scan
]):
self
.
__scan
=
scan
self
.
__update
()
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment