Skip to content

Commit 30fcd43

Browse files
committed
Allow index support and partial text matching and case insensitivity
1 parent d17632a commit 30fcd43

2 files changed

Lines changed: 50 additions & 19 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,5 @@ custom_profiles/
6262
Apps/Windows/inspector.exe
6363
Apps/Windows/Element.xml
6464
Framework/settings.conf.lock
65-
Framework/Built_In_Automation/Desktop/Linux/latest_app.txt
65+
Framework/Built_In_Automation/Desktop/Linux/latest_app.txt
66+
**/linux_screen.png

Framework/Built_In_Automation/Desktop/Linux/BuiltInFunctions.py

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,20 @@ def capture_screenshot(file_path: str, app_name: str | None = None) -> bool:
246246

247247
def 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

468491
def 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

Comments
 (0)