replace gtk2/PyGTK and Python 2 idioms in DamarisGUI.py

- raise "RuntimeError" -> raise RuntimeError(...)
- gobject.timeout_add/idle_add/PRIORITY_* -> GLib equivalents
  (PyGIDeprecationWarning)
- remove no-op gobject.type_register(GtkSource.View)
- gtk.HBox -> gtk.Box(orientation=HORIZONTAL) (deprecated since 3.2)
- menu.popup(6-arg) -> menu.popup_at_pointer (deprecated since 3.22)
- Thread.getName() -> Thread.name (deprecated since 3.10)
- rename gtksourceview2 alias to gtksourceview
- rename bare iter locals/params to treeiter to avoid shadowing
  the builtin

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
markusro committed 2026-10-18 16:24:59 +02:00
1 parent 6d46e8ca1a
commit f18bbdf48c
1 file changed
+65 -65
+65 -65
View File
@@ -24,6 +24,7 @@ from gi.repository import GObject as gobject
import sqlite3
import uuid
from gi.repository import GLib as glib
from gi.repository import Gtk as gtk
gtk_version_missmatch = gtk.check_version( 3, 0, 0 )
@@ -32,8 +33,7 @@ if gtk_version_missmatch:
from gi.repository import Gdk as gdk
from gi.repository import GtkSource as gtksourceview2
gobject.type_register(gtksourceview2.View)
from gi.repository import GtkSource as gtksourceview
from gi.repository import Pango as pango
@@ -208,7 +208,7 @@ class DamarisGUI:
if exp_script and res_script:
self.start_immediately = start_immediately
else:
raise "RuntimeError"
raise RuntimeError("start_immediately requires both experiment and result script")
else:
self.start_immediately = False
self.statusbar_init( )
@@ -740,7 +740,7 @@ class DamarisGUI:
if actual_config[ "data_pool_name" ] != "":
self.dump_states( init=True, logtext=self.log.snapshot_since_last_dump( ) )
gobject.timeout_add( 200, self.observe_running_experiment )
glib.timeout_add( 200, self.observe_running_experiment )
def observe_running_experiment( self ):
"""
@@ -875,7 +875,7 @@ class DamarisGUI:
self.toolbar_pause_button.set_sensitive( False )
self.toolbar_stop_button.set_sensitive( False )
if len( still_running ) != 0:
logger.warning("Subprocess(es) still running: %s", ', '.join( [s.getName( ) for s in still_running] ))
logger.warning("Subprocess(es) still running: %s", ', '.join( [s.name for s in still_running] ))
return True
else:
if self.save_thread is not None:
@@ -1323,7 +1323,7 @@ class LogWindow:
"""Manages the application log window.
Provides a timestamped, scrollable text view for application messages.
Messages are dispatched via ``gobject.idle_add`` to keep the GTK main
Messages are dispatched via ``glib.idle_add`` to keep the GTK main
loop responsive.
Args:
@@ -1353,7 +1353,7 @@ class LogWindow:
def __call__( self, message ):
timetag = time.time( )
gobject.idle_add( self.add_message_callback, timetag, message, priority=gobject.PRIORITY_LOW )
glib.idle_add( self.add_message_callback, timetag, message, priority=glib.PRIORITY_LOW )
def add_message_callback( self, timetag, message ):
date_tag = ""
@@ -1418,9 +1418,9 @@ class ScriptWidgets:
experiment script file.
res_script_filename (str or None): Path to the currently loaded
result script file.
experiment_script_textview (:class:`gtksourceview2.View`): Text view
experiment_script_textview (:class:`gtksourceview.View`): Text view
for the experiment script.
data_handling_textview (:class:`gtksourceview2.View`): Text view for
data_handling_textview (:class:`gtksourceview.View`): Text view for
the result script.
Public Methods:
@@ -1441,7 +1441,7 @@ class ScriptWidgets:
def __init__( self, xml_gui, outer_space ):
"""Initialize text widgets with syntax highlighting and completion.
Sets up two :class:`gtksourceview2.View` instances with Python
Sets up two :class:`gtksourceview.View` instances with Python
syntax highlighting, keyword auto-completion, line numbers, and
smart indentation. Connects text buffer signals to toolbar and
status bar update handlers.
@@ -1468,10 +1468,10 @@ class ScriptWidgets:
self.data_handling_textview = self.xml_gui.get_object( "data_handling_textview" )
# create and set syntax-highlighting text-buffers as textview backends
self.experiment_script_textbuffer = gtksourceview2.Buffer()
self.data_handling_textbuffer = gtksourceview2.Buffer()
self.experiment_script_textbuffer = gtksourceview.Buffer()
self.data_handling_textbuffer = gtksourceview.Buffer()
lm = gtksourceview2.LanguageManager()
lm = gtksourceview.LanguageManager()
langpython = lm.get_language("python")
self.experiment_script_textbuffer.set_language(langpython)
@@ -1505,7 +1505,7 @@ set_pfg set_dac set_phase set_pts_local get_length set_title get_title add_linep
add_errorplotdata get_number_of_channels get_style set_style get_xlabel set_xlabel
get_ylabel set_ylabel"""
self.keywordsbuffer = gtksourceview2.Buffer()
self.keywordsbuffer = gtksourceview.Buffer()
self.keywordsbuffer.set_text(keywords)
compexp = self.experiment_script_textview.get_completion()
@@ -1514,15 +1514,15 @@ get_ylabel set_ylabel"""
compexp.set_property("show-headers", True)
compres.set_property("show-headers", True)
self.compwgen = gtksourceview2.CompletionWords.new("Keywords", None)
self.compwgen = gtksourceview.CompletionWords.new("Keywords", None)
self.compwgen.register(self.keywordsbuffer)
self.compwgen.set_property("minimum-word-size", 2)
self.compwexp = gtksourceview2.CompletionWords.new("Words", None)
self.compwexp = gtksourceview.CompletionWords.new("Words", None)
self.compwexp.register(self.experiment_script_textbuffer)
self.compwexp.set_property("minimum-word-size", 2)
self.compwres = gtksourceview2.CompletionWords.new("Words", None)
self.compwres = gtksourceview.CompletionWords.new("Words", None)
self.compwres.register(self.data_handling_textbuffer)
self.compwres.set_property("minimum-word-size", 2)
@@ -1754,7 +1754,7 @@ get_ylabel set_ylabel"""
def textviews_modified( self, widget = None, event=None ):
# mix into toolbar affairs
if type(widget) is gtksourceview2.View:
if type(widget) is gtksourceview.View:
return self.textviews_moved( widget )
else:
return False
@@ -2395,7 +2395,7 @@ class ConfigTab:
self.config_data_pool_write_interval_entry.connect("key-press-event", self.config_keypress)
# ADC bit depth setting
self.config_adc_bit_depth_hbox = gtk.HBox(homogeneous=False, spacing=6)
self.config_adc_bit_depth_hbox = gtk.Box(orientation=gtk.Orientation.HORIZONTAL, spacing=6)
self.config_adc_bit_depth_label = gtk.Label(label="ADC bit depth:")
self.config_adc_bit_depth_spinbutton = gtk.SpinButton.new_with_range(8, 32, 1)
self.config_adc_bit_depth_spinbutton.set_value(ADC_Result.default_bit_depth)
@@ -2410,7 +2410,7 @@ class ConfigTab:
self.config_adc_bit_depth_hbox.show_all()
# Temperature monitoring settings - single line layout
self.config_temp_hbox = gtk.HBox(homogeneous=False, spacing=6)
self.config_temp_hbox = gtk.Box(orientation=gtk.Orientation.HORIZONTAL, spacing=6)
# Controller type selector
self.config_temp_controller_type_label = gtk.Label(label="Controller:")
@@ -2421,7 +2421,7 @@ class ConfigTab:
self.config_temp_controller_type_combobox.set_tooltip_text("Select temperature controller type")
self.config_temp_controller_type_combobox.connect("changed", self.on_temp_controller_type_changed)
self.config_temp_controller_type_hbox = gtk.HBox(homogeneous=False, spacing=0)
self.config_temp_controller_type_hbox = gtk.Box(orientation=gtk.Orientation.HORIZONTAL, spacing=0)
self.config_temp_controller_type_hbox.pack_start(self.config_temp_controller_type_label, False, False, 0)
self.config_temp_controller_type_hbox.pack_start(self.config_temp_controller_type_combobox, False, False, 0)
self.config_temp_hbox.pack_start(self.config_temp_controller_type_hbox, False, False, 0)
@@ -2440,7 +2440,7 @@ class ConfigTab:
self.config_temp_device_button.set_tooltip_text("Browse for temperature controller device")
self.config_temp_device_button.connect("clicked", self.on_temp_device_browse_clicked)
self.config_temp_device_hbox = gtk.HBox(homogeneous=False, spacing=0)
self.config_temp_device_hbox = gtk.Box(orientation=gtk.Orientation.HORIZONTAL, spacing=0)
self.config_temp_device_hbox.pack_start(self.config_temp_device_entry, True, True, 0)
self.config_temp_device_hbox.pack_start(self.config_temp_device_button, False, False, 0)
self.config_temp_hbox.pack_start(self.config_temp_device_hbox, True, True, 0)
@@ -2452,7 +2452,7 @@ class ConfigTab:
self.config_temp_interval_spinbutton.set_tooltip_text("Time between temperature readings in seconds")
self.config_temp_interval_spinbutton.connect("key-press-event", self.config_keypress)
self.config_temp_interval_hbox = gtk.HBox(homogeneous=False, spacing=6)
self.config_temp_interval_hbox = gtk.Box(orientation=gtk.Orientation.HORIZONTAL, spacing=6)
self.config_temp_interval_hbox.pack_start(self.config_temp_interval_label, False, False, 0)
self.config_temp_interval_hbox.pack_start(self.config_temp_interval_spinbutton, False, False, 0)
self.config_temp_hbox.pack_start(self.config_temp_interval_hbox, False, False, 0)
@@ -2466,7 +2466,7 @@ class ConfigTab:
self.config_temp_baudrate_combobox.append_text("115200")
self.config_temp_baudrate_combobox.set_active(0)
self.config_temp_baudrate_combobox.set_tooltip_text("Serial baud rate for temperature controller")
self.config_temp_baudrate_hbox = gtk.HBox(homogeneous=False, spacing=6)
self.config_temp_baudrate_hbox = gtk.Box(orientation=gtk.Orientation.HORIZONTAL, spacing=6)
self.config_temp_baudrate_hbox.pack_start(self.config_temp_baudrate_combobox, False, False, 0)
self.config_temp_hbox.pack_start(self.config_temp_baudrate_hbox, False, False, 0)
# Note: baud rate is shown for eurotherm, hidden for simulated
@@ -2675,14 +2675,14 @@ pygobject version %(pygobject)s
if "data_pool_complib" in config:
# find combo-box entry and make it active...
model = self.config_data_pool_complib.get_model( )
iter = model.get_iter_first( )
while iter is not None:
if model.get( iter, 0 )[ 0 ] == config[ "data_pool_complib" ]:
self.config_data_pool_complib.set_active_iter( iter )
treeiter = model.get_iter_first( )
while treeiter is not None:
if model.get( treeiter, 0 )[ 0 ] == config[ "data_pool_complib" ]:
self.config_data_pool_complib.set_active_iter( treeiter )
break
iter = model.iter_next( iter )
treeiter = model.iter_next( treeiter )
# if this compression method is not supported, warn and do nothing
if iter is None:
if treeiter is None:
logger.warning("Compression method %s is not supported", config[ "data_pool_complib" ])
def on_adc_bit_depth_changed(self, widget):
@@ -2759,8 +2759,8 @@ pygobject version %(pygobject)s
if model is None:
return
for i in range(model.iter_n_children(None)):
iter = model.iter_nth_child(None, i)
if iter and model.get(iter, 0)[0] == text:
treeiter = model.iter_nth_child(None, i)
if treeiter and model.get(treeiter, 0)[0] == text:
combobox.set_active(i)
return
@@ -3113,13 +3113,13 @@ class MonitorWidgets:
if none_iter is not None:
self.display_source_combobox.set_active_iter( none_iter )
def source_list_find_one( self, model, iter, what ):
def source_list_find_one( self, model, treeiter, what ):
"""find node in subcategory"""
while iter is not None:
if str( model.get( iter, 0 )[ 0 ] ) == what:
return iter
iter = model.iter_next( iter )
return iter
while treeiter is not None:
if str( model.get( treeiter, 0 )[ 0 ] ) == what:
return treeiter
treeiter = model.iter_next( treeiter )
return treeiter
def source_list_find( self, namelist ):
"""
@@ -3146,35 +3146,35 @@ class MonitorWidgets:
del namelist[:i]
# Continue search from here
retval = found_iter
iter = self.display_source_treestore.iter_children( retval )
while iter is not None and len( namelist ) > 0:
treeiter = self.display_source_treestore.iter_children( retval )
while treeiter is not None and len( namelist ) > 0:
name = namelist[ 0 ]
iter = self.source_list_find_one( self.display_source_treestore, iter, name )
if iter is not None:
retval = iter
treeiter = self.source_list_find_one( self.display_source_treestore, treeiter, name )
if treeiter is not None:
retval = treeiter
namelist.pop( 0 )
# Update cache
partial_path += "/" + name
self.source_list_cache[partial_path] = retval
iter = self.display_source_treestore.iter_children( retval )
treeiter = self.display_source_treestore.iter_children( retval )
return retval
else:
del self.source_list_cache[partial_path]
model = self.display_source_treestore
retval = None
#iter = model.get_iter_root( )
iter = model.get_iter_first( )
#treeiter = model.get_iter_root( )
treeiter = model.get_iter_first( )
current_path = []
while iter is not None and len( namelist ) > 0:
while treeiter is not None and len( namelist ) > 0:
name = namelist[ 0 ]
iter = self.source_list_find_one( model, iter, name )
if iter is not None:
retval = iter
treeiter = self.source_list_find_one( model, treeiter, name )
if treeiter is not None:
retval = treeiter
namelist.pop( 0 )
current_path.append(name)
self.source_list_cache["/".join(current_path)] = retval
iter = model.iter_children( retval )
treeiter = model.iter_children( retval )
return retval
def source_list_add( self, source_name, parent=None ):
@@ -3201,17 +3201,17 @@ class MonitorWidgets:
def source_list_remove( self, source_name ):
namelist = source_name.split( "/" )
pwd = namelist[ : ]
iter = self.source_list_find( namelist )
if iter is None or len( namelist ) > 0:
treeiter = self.source_list_find( namelist )
if treeiter is None or len( namelist ) > 0:
logger.warning("source_list_remove: Not found")
return
model = self.display_source_treestore
if model.iter_has_child( iter ):
if model.iter_has_child( treeiter ):
logger.warning("source_list_remove: Request to delete a tree")
return
while True:
parent = model.iter_parent( iter )
model.remove( iter )
parent = model.iter_parent( treeiter )
model.remove( treeiter )
pwd.pop( )
# We now test, if we want to remove parent too
if parent is None:
@@ -3222,7 +3222,7 @@ class MonitorWidgets:
if "/".join( pwd ) in self.data_pool:
# The parent has data connected to it
break
iter = parent
treeiter = parent
def source_list_current( self ):
ai = self.display_source_combobox.get_active_iter( )
@@ -3304,7 +3304,7 @@ class MonitorWidgets:
self.update_counter_lock.acquire( )
self.update_counter += 1
self.update_counter_lock.release( )
gobject.idle_add( self.datapool_idle_listener, event, priority=gobject.PRIORITY_DEFAULT_IDLE )
glib.idle_add(self.datapool_idle_listener, event, priority=glib.PRIORITY_DEFAULT_IDLE )
else:
if event.what == DataPool.Event.updated_value and \
(
@@ -3313,13 +3313,13 @@ class MonitorWidgets:
self.update_counter_lock.acquire()
self.update_counter += 1
self.update_counter_lock.release()
gobject.idle_add( self.update_display_idle_event, self.displayed_data[ 0 ][ : ],
priority=gobject.PRIORITY_DEFAULT_IDLE )
glib.idle_add(self.update_display_idle_event, self.displayed_data[ 0 ][ : ],
priority=glib.PRIORITY_DEFAULT_IDLE )
else:
self.update_counter_lock.acquire( )
self.update_counter += 1
self.update_counter_lock.release( )
gobject.idle_add( self.datapool_idle_listener, event, priority=gobject.PRIORITY_DEFAULT_IDLE )
glib.idle_add(self.datapool_idle_listener, event, priority=glib.PRIORITY_DEFAULT_IDLE )
if event.what in [ DataPool.Event.updated_value, DataPool.Event.new_key ]:
#print "Update hdf5 file ..."
@@ -3346,8 +3346,8 @@ class MonitorWidgets:
self.update_counter_lock.acquire( )
self.update_counter += 1
self.update_counter_lock.release( )
gobject.idle_add( self.update_display_idle_event, self.displayed_data[ 0 ][ : ],
priority=gobject.PRIORITY_DEFAULT_IDLE )
glib.idle_add(self.update_display_idle_event, self.displayed_data[ 0 ][ : ],
priority=glib.PRIORITY_DEFAULT_IDLE )
################### consume idle events
@@ -3457,7 +3457,7 @@ class MonitorWidgets:
self.update_counter += 1
self.update_counter_lock.release( )
event = DataPool.Event( DataPool.Event.updated_value, new_data_name )
gobject.idle_add( self.datapool_idle_listener, event, priority=gobject.PRIORITY_DEFAULT_IDLE )
glib.idle_add(self.datapool_idle_listener, event, priority=glib.PRIORITY_DEFAULT_IDLE )
def display_autoscaling_toggled( self, widget, data=None ):
self.matplot_axes.set_autoscale_on( self.display_autoscaling_checkbutton.get_active( ) )
@@ -3600,7 +3600,7 @@ class MonitorWidgets:
menu.append(item_copy_svg)
menu.show_all()
menu.popup(None, None, None, None, event.button, event.time)
menu.popup_at_pointer(event)
def copy_canvas_as_png(self, widget):
"""Copy canvas to clipboard as PNG"""