import os
import time
from pathlib import PureWindowsPath
from fortrace.core.qemu_monitor import QEMUMonitorSession
from fortrace.utility.applications.application import (
ApplicationEvent,
ApplicationType,
GenericApplication,
ParentNotifier,
)
from fortrace.utility.applications.file_manager.file_manager import GenericFileManager
from fortrace.utility.exceptions import DesktopEnvironmentException
from fortrace.utility.image_processing.image_similarity import nrmse
from fortrace.utility.image_processing.text_detection import text_line_contains
[docs]
class Explorer(GenericFileManager):
"""Representation of a Windows Explorer application window.
Notes:
Please use 'File Explorer' when creating this class, since Windows yields Edge
when entering 'Explorer'.
When using paths, make sure to use PureWindowsPath in this class
"""
def __init__(self, qs: QEMUMonitorSession, parent_notifier: ParentNotifier):
super().__init__("File Explorer", qs, parent_notifier)
[docs]
def focus_on_item(self, name: str):
self._qs.send_key_combination("ctrl-f") # start search
time.sleep(2) # wait for search field to become active
self._qs.send_text(name, True)
for _ in range(5):
search_0 = self.take_screenshot()
time.sleep(2)
search_1 = self.take_screenshot()
if nrmse(search_0, search_1) < 0.01:
break
time.sleep(5)
else:
raise DesktopEnvironmentException(
"The search to focus the item takes far too long."
)
text = self.extract_text()[1]
if text_line_contains(text, "No items match your search", "jaro"):
raise ValueError(f"Cannot find {name} with Windows Explorer search")
self._qs.send_key_combination("down") # focus results window
self._qs.send_key_combination("ctrl-a") # select all items in results window
[docs]
def open_file(
self, path: os.PathLike, app_type: ApplicationType, app_name: str
) -> GenericApplication:
# if only file name is supplied, we don't have to change directory
path = PureWindowsPath(path)
if path.is_absolute():
self.browse_to_directory(path.parent)
self.focus_on_item(path.name)
self._qs.send_key_combination("ret")
# pylint: disable-next=import-outside-toplevel
from fortrace.utility.applications.application_factory import get_application
new_app = get_application(app_type, app_name, self._qs, self._parent_notifier)
self._parent_notifier(
ApplicationEvent.NEW_APPLICATION_OPENED, application_reference=new_app
)
return new_app
[docs]
def bookmark_current_location(self):
raise NotImplementedError()
[docs]
def empty_trash(self):
raise NotImplementedError()
[docs]
def move_file(
self,
source: os.PathLike,
destination: os.PathLike,
overwrite: bool = False,
ignore_suffix: bool = True,
):
source = PureWindowsPath(source)
destination = PureWindowsPath(destination)
self._move_file(source, destination, overwrite, ignore_suffix)
[docs]
def search(self, query: str):
self._qs.send_key_combination("ctrl-f")
self._qs.send_text(query)
self._qs.send_key_combination("ctrl-tab")
[docs]
def toggle_show_hidden(self):
self._qs.send_key_combination("alt-v") # show "View" tab
self._qs.send_text("hh")
self._show_hidden = ~self._show_hidden
[docs]
def browse_to_directory(self, path: os.PathLike):
"""Browse the given path to a directory.
Args:
path: Windows path to be browsed to
Notes:
When specifying only a drive letter, make sure to include the double colon,
or else this is not recognized as a Windows path
"""
super().browse_to_directory(path)