@@ -246,11 +246,20 @@ def capture_screenshot(file_path: str, app_name: str | None = None) -> bool:
246246
247247def convert_data_set_to_dict (data_set : DataSet ) -> dict [str , str ]:
248248 """ Convert data set to dictionary for easier access """
249+ # ToDo: handle * and ** properly
249250 data_dict = {}
250251 for item in data_set :
251252 if len (item ) == 3 :
252253 key , _ , value = item
253- data_dict [key .strip ()] = value
254+ if key .startswith ('**' ):
255+ data_dict [key [2 :].strip ()] = value
256+ data_dict ['exact_' + key [2 :].strip ()] = 'false'
257+ data_dict ['case_sensitive_' + key [2 :].strip ()] = 'false'
258+ elif key .startswith ('*' ):
259+ data_dict [key [1 :].strip ()] = value
260+ data_dict ['exact_' + key [1 :].strip ()] = 'false'
261+ else :
262+ data_dict [key .strip ()] = value
254263 else :
255264 CommonUtil .ExecLog (MODULE_NAME , f"Invalid item in data set: { item } " , 3 )
256265 return data_dict
@@ -444,25 +453,39 @@ def get_paths_by_text(xml_content: str, search_text: str, exact_match=True, case
444453 if path and path not in paths :
445454 paths .append (path )
446455
447- return paths
456+ return sorted ( paths )
448457
449458
450- def get_parent_path_from_paths (paths : list [str ]) -> str | None :
459+ def get_parent_path_from_paths (paths : list [str ]) -> list [ str ] :
451460 """
452461 Sometimes multiple paths are returned for the same element.
453- They may have parent child relation. It is good idea to use
454- the parent. Parents path is always shorter and it is prefix
455- of child's path If they are not related, then return None.
462+ They may have parent-child relations. This function identifies
463+ all parent paths by removing children whose parent exists in the list.
464+
465+ Returns a list of parent paths (paths that are not prefixes of any other path).
456466 """
457467 if not paths :
458- return None
468+ return []
459469
460- paths .sort (key = lambda x : len (x ))
461- parent_path = paths [0 ]
462- for path in paths [1 :]:
463- if not path .startswith (parent_path ):
464- return None
465- return parent_path
470+ # Sort by length to process shorter (potential parent) paths first
471+ sorted_paths = sorted (set (paths ), key = lambda x : len (x ))
472+ parents = []
473+
474+ for i , path in enumerate (sorted_paths ):
475+ # Check if this path is a parent of any other path
476+ is_parent = False
477+ for j in range (i + 1 , len (sorted_paths )):
478+ # Check if sorted_paths[j] starts with path followed by a dot
479+ # This ensures "0.0.0" doesn't match "0.0.0.1" incorrectly
480+ if sorted_paths [j ].startswith (path + "." ):
481+ is_parent = True
482+ break
483+
484+ # If this path is not a parent of any remaining path, it's a leaf or standalone parent
485+ if not is_parent :
486+ parents .append (path )
487+
488+ return parents
466489
467490
468491def get_path_appname_from_dataset (
@@ -471,16 +494,23 @@ def get_path_appname_from_dataset(
471494 ) -> tuple [str | None , str | None ]:
472495 path , app_name = data_dict .get ("path" ), data_dict .get ("app_name" )
473496 wait_time = float (data_dict .get ("wait" , wait_time ) or str (wait_time or 10 ))
497+ index = data_dict .get ("index" ) or "0"
498+ if index .isdigit ():
499+ index = int (index )
500+ else :
501+ raise ValueError ("Index must be an integer." )
474502 text = data_dict .get ("text" , "" ).strip ()
503+ exact_text_match = data_dict .get ("exact_text" , "true" ).lower () == "true"
504+ text_case_sensitive = data_dict .get ("case_sensitive_text" , "true" ).lower () == "true"
475505 start_time = time .time ()
476506 if not path and text :
477507 while True :
478508 ui_tree = get_ui_tree (app_name )
479509 if not ui_tree :
480510 CommonUtil .ExecLog ("" , "UI tree not found for app_name: %s" % app_name , 3 )
481511 return None , app_name
482- paths = get_paths_by_text (ui_tree , text )
483- CommonUtil . ExecLog ( "" , "Found paths: %s" % paths , 1 )
512+ paths = get_paths_by_text (ui_tree , text , exact_match = exact_text_match , case_sensitive = text_case_sensitive )
513+
484514 if len (paths ) == 0 :
485515 if time .time () < start_time + wait_time :
486516 time .sleep (0.5 )
@@ -491,8 +521,9 @@ def get_path_appname_from_dataset(
491521 if len (paths ) == 1 :
492522 return paths [0 ], app_name
493523 else :
494- path = get_parent_path_from_paths (paths )
495- return path , app_name
524+ parent_paths = get_parent_path_from_paths (paths )
525+ CommonUtil .ExecLog ("" , "Found paths: %s" % parent_paths , 1 )
526+ return parent_paths [index ] if parent_paths else None , app_name
496527 return path , app_name
497528
498529
@@ -864,7 +895,6 @@ def find_best_app_match(user_input: str) -> Optional[Tuple[str, str, str]]:
864895 desktop_files = glob .glob ("/usr/share/applications/*.desktop" )
865896 for desktop_file in desktop_files :
866897 name , exec_cmd = parse_desktop_file (desktop_file )
867- print (f"Found desktop file: { desktop_file } , Name: { name } , Exec: { exec_cmd } " )
868898 if name and exec_cmd :
869899 # Use the desktop file basename as the key for matching
870900 key = os .path .basename (desktop_file ).replace ('.desktop' , '' )
0 commit comments