epicure.epiwidgets

Contains some utility functions to create napari widgets and customized it

  1"""
  2Contains some utility functions to create napari widgets and customized it
  3"""
  4
  5import epicure.Utils as ut
  6from qtpy.QtWidgets import QPushButton, QCheckBox, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit, QComboBox, QSpinBox, QSlider, QGroupBox, QFrame # type: ignore
  7from qtpy.QtCore import Qt # type: ignore
  8
  9def help_button( link, description="", display_settings=None ):
 10    """ Create a new Help button with given parameter """
 11    def show_doc():
 12        """ Open documentation page """
 13        ut.show_documentation_page( link )
 14
 15    help_btn = QPushButton( "help" )
 16    if description == "":
 17        help_btn.setToolTip( "Open EpiCure documentation" )
 18        help_btn.setStatusTip( "Open EpiCure documentation" )
 19    else:
 20        help_btn.setToolTip( description )
 21        help_btn.setStatusTip( description )
 22    help_btn.clicked.connect( show_doc )
 23    if display_settings is not None:
 24        if "Help button" in display_settings:
 25            color = display_settings["Help button"]
 26            help_btn.setStyleSheet( 'QPushButton {background-color: '+color+'}' )
 27    return help_btn
 28
 29def group_layout( grname ):
 30    """ Create a group box with a vertical layout """
 31    group = QGroupBox( grname )
 32    layout = QVBoxLayout()
 33    return group, layout
 34
 35def separation():
 36    """ Create horizontal line to create a separation """
 37    sep = QFrame()
 38    sep.setFrameShape(QFrame.HLine)
 39    sep.setLineWidth(2)
 40    sep.setMidLineWidth(2)
 41    sep.setMinimumSize( 10, 2 )
 42    sep.setStyleSheet('background-color: rgb(150,150,150)')  
 43    return sep
 44
 45def checkgroup_help( name, checked, descr, help_link, display_settings=None, groupnb=None ):
 46    """ Create a group that can be show/hide with checkbox and an help button """
 47    group = QGroupBox( name )
 48    chbox = QCheckBox( text=name )
 49
 50    ## set group and checkbox to the same specific color
 51    if (groupnb is not None) and (display_settings is not None):
 52        if groupnb in display_settings:
 53            color = display_settings[groupnb]
 54            group.setStyleSheet( 'QGroupBox {background-color: '+color+'}' )
 55            chbox.setStyleSheet( 'QCheckBox::indicator {background-color: '+color+'}' )
 56    
 57    def show_hide():
 58        group.setVisible( chbox.isChecked() )
 59
 60    line = QHBoxLayout()
 61    ## create checkbox
 62    chbox.setToolTip( descr )
 63    line.addWidget( chbox )
 64    chbox.stateChanged.connect( show_hide )
 65    chbox.setChecked( checked )
 66    ## create button
 67    if help_link is not None:
 68        help_btn = help_button( help_link, "", display_settings )
 69        line.addWidget( help_btn )
 70    return line, chbox, group
 71
 72def checkhelp_line( checkbox_name, checked, checkfunc, check_descr, help_link, display_settings=None, help_descr="" ):
 73    """ Create a layout line with a checkbox associated with help button """
 74    line = QHBoxLayout()
 75    ## create checkbox
 76    chbox = QCheckBox( text=checkbox_name )
 77    chbox.setToolTip( check_descr )
 78    line.addWidget( chbox )
 79    if checkfunc is not None:
 80        chbox.stateChanged.connect( checkfunc )
 81    chbox.setChecked( checked )
 82    ## create button
 83    help_btn = help_button( help_link, help_descr, display_settings )
 84    line.addWidget( help_btn )
 85    return line, chbox
 86
 87def add_check( check, checked, check_func=None, descr="" ):
 88    """ Add a checkbox with set parameters """
 89    cbox = QCheckBox( text=check )
 90    cbox.setToolTip( descr )
 91    if check_func is not None:
 92        cbox.stateChanged.connect( check_func )
 93    cbox.setChecked( checked )
 94    return cbox
 95
 96def label_line( label ):
 97    """ Returns a label line """
 98    lab = QLabel( label )
 99    return lab
100
101def hlayout():
102    """ Return a horizontal layout """
103    return QHBoxLayout()
104
105def vlayout():
106    """ Return a vertical layout """
107    return QVBoxLayout()
108
109def add_check_tolayout( layout, check, checked, check_func=None, descr="" ):
110    """ Add a checkbox with set parameters """
111    cbox = add_check( check, checked, check_func, descr )
112    layout.addWidget( cbox )
113    return cbox
114
115def double_check( checka, checkeda, funca, descra, checkb, checkedb, funcb, descrb ):
116    """ Line with two customized checkboxes """
117    line = QHBoxLayout()
118    check_a = add_check( checka, checkeda, funca, descra )
119    check_b = add_check( checkb, checkedb, funcb, descrb )
120    line.addWidget( check_a )
121    line.addWidget( check_b )
122    return line, check_a, check_b
123
124def add_button( btn, btn_func, descr="", color=None ):
125    """ Add a button connected to an action when pushed """
126    btn = QPushButton( btn )
127    if btn_func is not None:
128        btn.clicked.connect( btn_func )
129    if descr != "":
130        btn.setToolTip( descr )
131    else:
132        btn.setToolTip( "Click to perform action" )
133    if color is not None:
134        btn.setStyleSheet( 'QPushButton {background-color: '+color+'}' )
135    return btn
136
137def double_button( btna, funca, descra, btnb, funcb, descrb ):
138    """ Line with two customized buttons """
139    line = QHBoxLayout()
140    btn_a = add_button( btna, funca, descra )
141    btn_b = add_button( btnb, funcb, descrb )
142    line.addWidget( btn_a )
143    line.addWidget( btn_b )
144    return line
145
146def button_parameter_line( btn, btn_func, value, descr_btn="", descr_value="" ):
147    """ Create a layout with a button and an editable value associated """
148    line = QHBoxLayout()
149    ## Action button
150    btn = QPushButton( btn )
151    btn.clicked.connect( btn_func )
152    if descr_btn != "":
153        btn.setToolTip( descr_btn )
154    line.addWidget( btn )
155    ## Value editable
156    val = QLineEdit()
157    val.setText( value )
158    line.addWidget( val )
159    if descr_value != "":
160        val.setToolTip( descr_value )
161    return line, val
162
163def min_button_max( btn, btn_func, min_val, max_val, descr="" ):
164    """ Button inside two values (min and max) interfaces """
165    line = QHBoxLayout()
166    ## left value
167    minv = QLineEdit()
168    minv.setText( min_val )
169    line.addWidget( minv )
170    ## button
171    btn = QPushButton( btn )
172    btn.clicked.connect( btn_func )
173    if descr != "":
174        btn.setToolTip( descr )
175    line.addWidget( btn )
176    ## right value
177    maxv = QLineEdit()
178    maxv.setText( max_val )
179    line.addWidget( maxv )
180    return line, minv, maxv
181
182
183def button_check_line( btn, btn_func, check, checked=False, checkfunc=None, descr_btn="", descr_check="", leftbtn=True ):
184    """ Create a layout with a button and an assiociated checkbox """
185    line = QHBoxLayout()
186    ## Action button
187    btn = QPushButton( btn )
188    btn.clicked.connect( btn_func )
189    if descr_btn != "":
190        btn.setToolTip( descr_btn )
191    ## Value editable
192    cbox = QCheckBox( check )
193    if descr_check != "":
194        cbox.setToolTip( descr_check )
195    if checkfunc is not None:
196        cbox.stateChanged.connect( checkfunc )
197    cbox.setChecked( checked )
198    ## button first (left), then checkbox
199    if leftbtn:
200        line.addWidget( btn )
201        line.addWidget( cbox )
202    else:
203        ## or checkbox first (left), then button
204        line.addWidget( cbox )
205        line.addWidget( btn )
206    return line, cbox
207
208def value_line( label, default_value, descr="" ):
209    """ Create a layout line with a value to edit (non editable name + value part ) """
210    line = QHBoxLayout()
211    ## Value name
212    lab = QLabel()
213    lab.setText( label )
214    line.addWidget( lab )
215    if descr != "":
216        lab.setToolTip( descr )
217    ## Value editable part
218    value = QLineEdit()
219    value.setText( default_value )
220    line.addWidget( value )
221    return line, value
222
223def check_value( check, checkfunc=None, checked=False, value="0", descr="", label=None ):
224    """ Line with a checkbox and an associated editable parameter """
225    line = QHBoxLayout()
226    ## add checkbox
227    cbox = add_check( check, checked=checked, check_func=checkfunc, descr=descr )
228    line.addWidget( cbox )
229    ## add eventually a text
230    if label is not None:
231        lab = QLabel()
232        lab.setText( label )
233        line.addWidget( lab )
234    ## add the editable value
235    val = QLineEdit()
236    val.setText( value )
237    line.addWidget( val )
238    return line, cbox, val
239
240def ranged_value_line( label, minval, maxval, step, val, descr="" ):
241    """ Create a line with a label and a ranged value (limited between min and max) """
242    line = QHBoxLayout()
243    ## Add the name of the value
244    lab = QLabel()
245    lab.setText( label )
246    if descr != "":
247        lab.setToolTip( descr )
248    line.addWidget( lab )
249    ## Ranged-value widget
250    ranged_val = QSpinBox()
251    ranged_val.setMinimum( minval )
252    ranged_val.setMaximum( maxval )
253    ranged_val.setSingleStep( step ) 
254    ranged_val.setValue( val )
255    line.addWidget( ranged_val )
256    return line, ranged_val
257
258def button_list( btn, func, descr ):
259    """ Button associated with a list """
260    line = QHBoxLayout()
261    ## Button part
262    button = add_button( btn, func, descr )
263    line.addWidget( button )
264    ## list part
265    li = QComboBox()
266    line.addWidget( li )
267    return line, li
268
269def list_line( label, descr="", func=None ):
270    """ Create a layout line with a choice list to edit (non editable name + list part ) """
271    line = QHBoxLayout()
272    ## Value name
273    lab = QLabel()
274    lab.setText( label )
275    line.addWidget( lab )
276    if descr != "":
277        lab.setToolTip( descr )
278        lab.setStatusTip( descr )
279    ## Value editable part
280    value = QComboBox()
281    line.addWidget( value )
282    if func is not None:
283        value.currentIndexChanged.connect( func )
284    return line, value
285
286def listbox( func=None ):
287    """ Create a choice list to edit """
288    ## Value editable part
289    value = QComboBox()
290    if func is not None:
291        value.currentIndexChanged.connect( func )
292    return value
293
294def slider_line( name, minval, maxval, step, value, show_value=False, slidefunc=None, descr="" ):
295    """ Line with a text and a slider """
296    line = QHBoxLayout()
297    ## add name if any
298    if name is not None:
299        lab = QLabel()
300        lab.setText( name )
301        line.addWidget( lab )
302    ## add slider
303    slider =  QSlider( Qt.Horizontal )
304    slider.setMinimum( minval )
305    slider.setMaximum( maxval )
306    slider.setSingleStep( step )
307    slider.setValue( value )
308    if slidefunc is not None:
309        slider.valueChanged.connect( slidefunc )
310    if descr != "":
311        slider.setToolTip( descr )
312    if show_value:
313        lab = QLabel(""+str(value))
314        line.addWidget( lab )
315        slider.valueChanged.connect( lambda: lab.setText( ""+str(slider.value()) ) )
316    line.addWidget( slider )
317    return line, slider
def help_button(link, description='', display_settings=None):
10def help_button( link, description="", display_settings=None ):
11    """ Create a new Help button with given parameter """
12    def show_doc():
13        """ Open documentation page """
14        ut.show_documentation_page( link )
15
16    help_btn = QPushButton( "help" )
17    if description == "":
18        help_btn.setToolTip( "Open EpiCure documentation" )
19        help_btn.setStatusTip( "Open EpiCure documentation" )
20    else:
21        help_btn.setToolTip( description )
22        help_btn.setStatusTip( description )
23    help_btn.clicked.connect( show_doc )
24    if display_settings is not None:
25        if "Help button" in display_settings:
26            color = display_settings["Help button"]
27            help_btn.setStyleSheet( 'QPushButton {background-color: '+color+'}' )
28    return help_btn

Create a new Help button with given parameter

def group_layout(grname):
30def group_layout( grname ):
31    """ Create a group box with a vertical layout """
32    group = QGroupBox( grname )
33    layout = QVBoxLayout()
34    return group, layout

Create a group box with a vertical layout

def separation():
36def separation():
37    """ Create horizontal line to create a separation """
38    sep = QFrame()
39    sep.setFrameShape(QFrame.HLine)
40    sep.setLineWidth(2)
41    sep.setMidLineWidth(2)
42    sep.setMinimumSize( 10, 2 )
43    sep.setStyleSheet('background-color: rgb(150,150,150)')  
44    return sep

Create horizontal line to create a separation

def checkgroup_help(name, checked, descr, help_link, display_settings=None, groupnb=None):
46def checkgroup_help( name, checked, descr, help_link, display_settings=None, groupnb=None ):
47    """ Create a group that can be show/hide with checkbox and an help button """
48    group = QGroupBox( name )
49    chbox = QCheckBox( text=name )
50
51    ## set group and checkbox to the same specific color
52    if (groupnb is not None) and (display_settings is not None):
53        if groupnb in display_settings:
54            color = display_settings[groupnb]
55            group.setStyleSheet( 'QGroupBox {background-color: '+color+'}' )
56            chbox.setStyleSheet( 'QCheckBox::indicator {background-color: '+color+'}' )
57    
58    def show_hide():
59        group.setVisible( chbox.isChecked() )
60
61    line = QHBoxLayout()
62    ## create checkbox
63    chbox.setToolTip( descr )
64    line.addWidget( chbox )
65    chbox.stateChanged.connect( show_hide )
66    chbox.setChecked( checked )
67    ## create button
68    if help_link is not None:
69        help_btn = help_button( help_link, "", display_settings )
70        line.addWidget( help_btn )
71    return line, chbox, group

Create a group that can be show/hide with checkbox and an help button

def checkhelp_line( checkbox_name, checked, checkfunc, check_descr, help_link, display_settings=None, help_descr=''):
73def checkhelp_line( checkbox_name, checked, checkfunc, check_descr, help_link, display_settings=None, help_descr="" ):
74    """ Create a layout line with a checkbox associated with help button """
75    line = QHBoxLayout()
76    ## create checkbox
77    chbox = QCheckBox( text=checkbox_name )
78    chbox.setToolTip( check_descr )
79    line.addWidget( chbox )
80    if checkfunc is not None:
81        chbox.stateChanged.connect( checkfunc )
82    chbox.setChecked( checked )
83    ## create button
84    help_btn = help_button( help_link, help_descr, display_settings )
85    line.addWidget( help_btn )
86    return line, chbox

Create a layout line with a checkbox associated with help button

def add_check(check, checked, check_func=None, descr=''):
88def add_check( check, checked, check_func=None, descr="" ):
89    """ Add a checkbox with set parameters """
90    cbox = QCheckBox( text=check )
91    cbox.setToolTip( descr )
92    if check_func is not None:
93        cbox.stateChanged.connect( check_func )
94    cbox.setChecked( checked )
95    return cbox

Add a checkbox with set parameters

def label_line(label):
 97def label_line( label ):
 98    """ Returns a label line """
 99    lab = QLabel( label )
100    return lab

Returns a label line

def hlayout():
102def hlayout():
103    """ Return a horizontal layout """
104    return QHBoxLayout()

Return a horizontal layout

def vlayout():
106def vlayout():
107    """ Return a vertical layout """
108    return QVBoxLayout()

Return a vertical layout

def add_check_tolayout(layout, check, checked, check_func=None, descr=''):
110def add_check_tolayout( layout, check, checked, check_func=None, descr="" ):
111    """ Add a checkbox with set parameters """
112    cbox = add_check( check, checked, check_func, descr )
113    layout.addWidget( cbox )
114    return cbox

Add a checkbox with set parameters

def double_check(checka, checkeda, funca, descra, checkb, checkedb, funcb, descrb):
116def double_check( checka, checkeda, funca, descra, checkb, checkedb, funcb, descrb ):
117    """ Line with two customized checkboxes """
118    line = QHBoxLayout()
119    check_a = add_check( checka, checkeda, funca, descra )
120    check_b = add_check( checkb, checkedb, funcb, descrb )
121    line.addWidget( check_a )
122    line.addWidget( check_b )
123    return line, check_a, check_b

Line with two customized checkboxes

def add_button(btn, btn_func, descr='', color=None):
125def add_button( btn, btn_func, descr="", color=None ):
126    """ Add a button connected to an action when pushed """
127    btn = QPushButton( btn )
128    if btn_func is not None:
129        btn.clicked.connect( btn_func )
130    if descr != "":
131        btn.setToolTip( descr )
132    else:
133        btn.setToolTip( "Click to perform action" )
134    if color is not None:
135        btn.setStyleSheet( 'QPushButton {background-color: '+color+'}' )
136    return btn

Add a button connected to an action when pushed

def double_button(btna, funca, descra, btnb, funcb, descrb):
138def double_button( btna, funca, descra, btnb, funcb, descrb ):
139    """ Line with two customized buttons """
140    line = QHBoxLayout()
141    btn_a = add_button( btna, funca, descra )
142    btn_b = add_button( btnb, funcb, descrb )
143    line.addWidget( btn_a )
144    line.addWidget( btn_b )
145    return line

Line with two customized buttons

def button_parameter_line(btn, btn_func, value, descr_btn='', descr_value=''):
147def button_parameter_line( btn, btn_func, value, descr_btn="", descr_value="" ):
148    """ Create a layout with a button and an editable value associated """
149    line = QHBoxLayout()
150    ## Action button
151    btn = QPushButton( btn )
152    btn.clicked.connect( btn_func )
153    if descr_btn != "":
154        btn.setToolTip( descr_btn )
155    line.addWidget( btn )
156    ## Value editable
157    val = QLineEdit()
158    val.setText( value )
159    line.addWidget( val )
160    if descr_value != "":
161        val.setToolTip( descr_value )
162    return line, val

Create a layout with a button and an editable value associated

def min_button_max(btn, btn_func, min_val, max_val, descr=''):
164def min_button_max( btn, btn_func, min_val, max_val, descr="" ):
165    """ Button inside two values (min and max) interfaces """
166    line = QHBoxLayout()
167    ## left value
168    minv = QLineEdit()
169    minv.setText( min_val )
170    line.addWidget( minv )
171    ## button
172    btn = QPushButton( btn )
173    btn.clicked.connect( btn_func )
174    if descr != "":
175        btn.setToolTip( descr )
176    line.addWidget( btn )
177    ## right value
178    maxv = QLineEdit()
179    maxv.setText( max_val )
180    line.addWidget( maxv )
181    return line, minv, maxv

Button inside two values (min and max) interfaces

def button_check_line( btn, btn_func, check, checked=False, checkfunc=None, descr_btn='', descr_check='', leftbtn=True):
184def button_check_line( btn, btn_func, check, checked=False, checkfunc=None, descr_btn="", descr_check="", leftbtn=True ):
185    """ Create a layout with a button and an assiociated checkbox """
186    line = QHBoxLayout()
187    ## Action button
188    btn = QPushButton( btn )
189    btn.clicked.connect( btn_func )
190    if descr_btn != "":
191        btn.setToolTip( descr_btn )
192    ## Value editable
193    cbox = QCheckBox( check )
194    if descr_check != "":
195        cbox.setToolTip( descr_check )
196    if checkfunc is not None:
197        cbox.stateChanged.connect( checkfunc )
198    cbox.setChecked( checked )
199    ## button first (left), then checkbox
200    if leftbtn:
201        line.addWidget( btn )
202        line.addWidget( cbox )
203    else:
204        ## or checkbox first (left), then button
205        line.addWidget( cbox )
206        line.addWidget( btn )
207    return line, cbox

Create a layout with a button and an assiociated checkbox

def value_line(label, default_value, descr=''):
209def value_line( label, default_value, descr="" ):
210    """ Create a layout line with a value to edit (non editable name + value part ) """
211    line = QHBoxLayout()
212    ## Value name
213    lab = QLabel()
214    lab.setText( label )
215    line.addWidget( lab )
216    if descr != "":
217        lab.setToolTip( descr )
218    ## Value editable part
219    value = QLineEdit()
220    value.setText( default_value )
221    line.addWidget( value )
222    return line, value

Create a layout line with a value to edit (non editable name + value part )

def check_value( check, checkfunc=None, checked=False, value='0', descr='', label=None):
224def check_value( check, checkfunc=None, checked=False, value="0", descr="", label=None ):
225    """ Line with a checkbox and an associated editable parameter """
226    line = QHBoxLayout()
227    ## add checkbox
228    cbox = add_check( check, checked=checked, check_func=checkfunc, descr=descr )
229    line.addWidget( cbox )
230    ## add eventually a text
231    if label is not None:
232        lab = QLabel()
233        lab.setText( label )
234        line.addWidget( lab )
235    ## add the editable value
236    val = QLineEdit()
237    val.setText( value )
238    line.addWidget( val )
239    return line, cbox, val

Line with a checkbox and an associated editable parameter

def ranged_value_line(label, minval, maxval, step, val, descr=''):
241def ranged_value_line( label, minval, maxval, step, val, descr="" ):
242    """ Create a line with a label and a ranged value (limited between min and max) """
243    line = QHBoxLayout()
244    ## Add the name of the value
245    lab = QLabel()
246    lab.setText( label )
247    if descr != "":
248        lab.setToolTip( descr )
249    line.addWidget( lab )
250    ## Ranged-value widget
251    ranged_val = QSpinBox()
252    ranged_val.setMinimum( minval )
253    ranged_val.setMaximum( maxval )
254    ranged_val.setSingleStep( step ) 
255    ranged_val.setValue( val )
256    line.addWidget( ranged_val )
257    return line, ranged_val

Create a line with a label and a ranged value (limited between min and max)

def button_list(btn, func, descr):
259def button_list( btn, func, descr ):
260    """ Button associated with a list """
261    line = QHBoxLayout()
262    ## Button part
263    button = add_button( btn, func, descr )
264    line.addWidget( button )
265    ## list part
266    li = QComboBox()
267    line.addWidget( li )
268    return line, li

Button associated with a list

def list_line(label, descr='', func=None):
270def list_line( label, descr="", func=None ):
271    """ Create a layout line with a choice list to edit (non editable name + list part ) """
272    line = QHBoxLayout()
273    ## Value name
274    lab = QLabel()
275    lab.setText( label )
276    line.addWidget( lab )
277    if descr != "":
278        lab.setToolTip( descr )
279        lab.setStatusTip( descr )
280    ## Value editable part
281    value = QComboBox()
282    line.addWidget( value )
283    if func is not None:
284        value.currentIndexChanged.connect( func )
285    return line, value

Create a layout line with a choice list to edit (non editable name + list part )

def listbox(func=None):
287def listbox( func=None ):
288    """ Create a choice list to edit """
289    ## Value editable part
290    value = QComboBox()
291    if func is not None:
292        value.currentIndexChanged.connect( func )
293    return value

Create a choice list to edit

def slider_line( name, minval, maxval, step, value, show_value=False, slidefunc=None, descr=''):
295def slider_line( name, minval, maxval, step, value, show_value=False, slidefunc=None, descr="" ):
296    """ Line with a text and a slider """
297    line = QHBoxLayout()
298    ## add name if any
299    if name is not None:
300        lab = QLabel()
301        lab.setText( name )
302        line.addWidget( lab )
303    ## add slider
304    slider =  QSlider( Qt.Horizontal )
305    slider.setMinimum( minval )
306    slider.setMaximum( maxval )
307    slider.setSingleStep( step )
308    slider.setValue( value )
309    if slidefunc is not None:
310        slider.valueChanged.connect( slidefunc )
311    if descr != "":
312        slider.setToolTip( descr )
313    if show_value:
314        lab = QLabel(""+str(value))
315        line.addWidget( lab )
316        slider.valueChanged.connect( lambda: lab.setText( ""+str(slider.value()) ) )
317    line.addWidget( slider )
318    return line, slider

Line with a text and a slider