epicure.epiwidgets

Creation of customized widgets for the user interface

Contains some utility functions to create napari widgets and customized it

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

Create a new Help button with given parameter

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

Create a group box with a vertical layout

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

Create horizontal line to create a separation

def checkgroup_help(name, checked, descr, help_link, display_settings=None, groupnb=None):
48def checkgroup_help( name, checked, descr, help_link, display_settings=None, groupnb=None ):
49    """ Create a group that can be show/hide with checkbox and an help button """
50    group = QGroupBox( name )
51    chbox = QCheckBox( text=name )
52
53    ## set group and checkbox to the same specific color
54    if (groupnb is not None) and (display_settings is not None):
55        if groupnb in display_settings:
56            color = display_settings[groupnb]
57            group.setStyleSheet( 'QGroupBox {background-color: '+color+'}' )
58            chbox.setStyleSheet( 'QCheckBox::indicator {background-color: '+color+'}' )
59    
60    def show_hide():
61        group.setVisible( chbox.isChecked() )
62
63    line = QHBoxLayout()
64    ## create checkbox
65    chbox.setToolTip( descr )
66    line.addWidget( chbox )
67    chbox.stateChanged.connect( show_hide )
68    chbox.setChecked( checked )
69    ## create button
70    if help_link is not None:
71        help_btn = help_button( help_link, "", display_settings )
72        line.addWidget( help_btn )
73    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=''):
75def checkhelp_line( checkbox_name, checked, checkfunc, check_descr, help_link, display_settings=None, help_descr="" ):
76    """ Create a layout line with a checkbox associated with help button """
77    line = QHBoxLayout()
78    ## create checkbox
79    chbox = QCheckBox( text=checkbox_name )
80    chbox.setToolTip( check_descr )
81    line.addWidget( chbox )
82    if checkfunc is not None:
83        chbox.stateChanged.connect( checkfunc )
84    chbox.setChecked( checked )
85    ## create button
86    help_btn = help_button( help_link, help_descr, display_settings )
87    line.addWidget( help_btn )
88    return line, chbox

Create a layout line with a checkbox associated with help button

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

Add a checkbox with set parameters

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

Returns a label line

def hlayout():
104def hlayout():
105    """ Return a horizontal layout """
106    return QHBoxLayout()

Return a horizontal layout

def vlayout():
108def vlayout():
109    """ Return a vertical layout """
110    return QVBoxLayout()

Return a vertical layout

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

Add a checkbox with set parameters

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

Line with two customized checkboxes

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

Add a button connected to an action when pushed

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

Line with two customized buttons

def button_parameter_line(btn, btn_func, value, descr_btn='', descr_value=''):
149def button_parameter_line( btn, btn_func, value, descr_btn="", descr_value="" ):
150    """ Create a layout with a button and an editable value associated """
151    line = QHBoxLayout()
152    ## Action button
153    btn = QPushButton( btn )
154    btn.clicked.connect( btn_func )
155    if descr_btn != "":
156        btn.setToolTip( descr_btn )
157    line.addWidget( btn )
158    ## Value editable
159    val = QLineEdit()
160    val.setText( value )
161    line.addWidget( val )
162    if descr_value != "":
163        val.setToolTip( descr_value )
164    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=''):
166def min_button_max( btn, btn_func, min_val, max_val, descr="" ):
167    """ Button inside two values (min and max) interfaces """
168    line = QHBoxLayout()
169    ## left value
170    minv = QLineEdit()
171    minv.setText( min_val )
172    line.addWidget( minv )
173    ## button
174    btn = QPushButton( btn )
175    btn.clicked.connect( btn_func )
176    if descr != "":
177        btn.setToolTip( descr )
178    line.addWidget( btn )
179    ## right value
180    maxv = QLineEdit()
181    maxv.setText( max_val )
182    line.addWidget( maxv )
183    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):
186def button_check_line( btn, btn_func, check, checked=False, checkfunc=None, descr_btn="", descr_check="", leftbtn=True ):
187    """ Create a layout with a button and an assiociated checkbox """
188    line = QHBoxLayout()
189    ## Action button
190    btn = QPushButton( btn )
191    btn.clicked.connect( btn_func )
192    if descr_btn != "":
193        btn.setToolTip( descr_btn )
194    ## Value editable
195    cbox = QCheckBox( check )
196    if descr_check != "":
197        cbox.setToolTip( descr_check )
198    if checkfunc is not None:
199        cbox.stateChanged.connect( checkfunc )
200    cbox.setChecked( checked )
201    ## button first (left), then checkbox
202    if leftbtn:
203        line.addWidget( btn )
204        line.addWidget( cbox )
205    else:
206        ## or checkbox first (left), then button
207        line.addWidget( cbox )
208        line.addWidget( btn )
209    return line, cbox

Create a layout with a button and an assiociated checkbox

def value_line(label, default_value, descr=''):
211def value_line( label, default_value, descr="" ):
212    """ Create a layout line with a value to edit (non editable name + value part ) """
213    line = QHBoxLayout()
214    ## Value name
215    lab = QLabel()
216    lab.setText( label )
217    line.addWidget( lab )
218    if descr != "":
219        lab.setToolTip( descr )
220    ## Value editable part
221    value = QLineEdit()
222    value.setText( default_value )
223    line.addWidget( value )
224    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):
226def check_value( check, checkfunc=None, checked=False, value="0", descr="", label=None ):
227    """ Line with a checkbox and an associated editable parameter """
228    line = QHBoxLayout()
229    ## add checkbox
230    cbox = add_check( check, checked=checked, check_func=checkfunc, descr=descr )
231    line.addWidget( cbox )
232    ## add eventually a text
233    if label is not None:
234        lab = QLabel()
235        lab.setText( label )
236        line.addWidget( lab )
237    ## add the editable value
238    val = QLineEdit()
239    val.setText( value )
240    line.addWidget( val )
241    return line, cbox, val

Line with a checkbox and an associated editable parameter

def ranged_value_line(label, minval, maxval, step, val, descr=''):
243def ranged_value_line( label, minval, maxval, step, val, descr="" ):
244    """ Create a line with a label and a ranged value (limited between min and max) """
245    line = QHBoxLayout()
246    ## Add the name of the value
247    lab = QLabel()
248    lab.setText( label )
249    if descr != "":
250        lab.setToolTip( descr )
251    line.addWidget( lab )
252    ## Ranged-value widget
253    ranged_val = QSpinBox()
254    ranged_val.setMinimum( minval )
255    ranged_val.setMaximum( maxval )
256    ranged_val.setSingleStep( step ) 
257    ranged_val.setValue( val )
258    line.addWidget( ranged_val )
259    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):
261def button_list( btn, func, descr ):
262    """ Button associated with a list """
263    line = QHBoxLayout()
264    ## Button part
265    button = add_button( btn, func, descr )
266    line.addWidget( button )
267    ## list part
268    li = QComboBox()
269    line.addWidget( li )
270    return line, li

Button associated with a list

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

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

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

Create a choice list to edit

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

Line with a text and a slider