From f8cdc9b32f22eaba665069a70f3eda83af1b1365 Mon Sep 17 00:00:00 2001 From: Jesica Date: Fri, 30 Jun 2023 12:49:41 +0700 Subject: [PATCH 01/14] return top_window of the active app --- openadapt/window/_windows.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index f56b1605a..ca6189fea 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -95,7 +95,7 @@ def get_active_window(depth=10, max_width=10, filename=None) -> Desktop: Desktop: The active window object. """ app = pywinauto.application.Application(backend="uia").connect(active_only=True) - window = app.active() + window = app.top_window() return window From 422ea1850c01cb79497a476abebab5e33e3df2ab Mon Sep 17 00:00:00 2001 From: Jesica Date: Fri, 30 Jun 2023 12:53:16 +0700 Subject: [PATCH 02/14] remove runtime exception --- openadapt/window/_windows.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index ca6189fea..fb0994ba7 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -25,11 +25,8 @@ def get_active_window_state() -> dict: - "window_id": ID of the active window. """ # catch specific exceptions, when except happens do log.warning - try: - active_window = get_active_window() - except RuntimeError as e: - logger.warning(e) - return {} + active_window = get_active_window() + meta = get_active_window_meta(active_window) rectangle_dict = dictify_rect(meta["rectangle"]) data = get_element_properties(active_window) From 84e0295a206b6f008feafc0811df55bd8c6bfc93 Mon Sep 17 00:00:00 2001 From: Jesica Date: Tue, 4 Jul 2023 07:08:04 +0700 Subject: [PATCH 03/14] handle runtime error --- openadapt/window/_windows.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index fb0994ba7..89b041a74 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -25,8 +25,10 @@ def get_active_window_state() -> dict: - "window_id": ID of the active window. """ # catch specific exceptions, when except happens do log.warning - active_window = get_active_window() - + try: + active_window = get_active_window() + except RuntimeError as e: + return {} meta = get_active_window_meta(active_window) rectangle_dict = dictify_rect(meta["rectangle"]) data = get_element_properties(active_window) From a40bdb8bb5cf35e3c122ac32a3e40d79f458b760 Mon Sep 17 00:00:00 2001 From: Jesica Date: Wed, 5 Jul 2023 22:57:15 +0700 Subject: [PATCH 04/14] handle COMerror --- openadapt/window/_windows.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index 89b041a74..3e17de835 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -6,7 +6,7 @@ import time from pprint import pprint import pickle - +import comtypes def get_active_window_state() -> dict: """ @@ -120,7 +120,11 @@ def get_element_properties(element): 'children': []}]} """ - properties = element.get_properties() + try: + properties = element.get_properties() + except comtypes.COMError: + logger.warning(f"COMError occurred: {com_err}") + return {} children = element.children() if children: From dafbd7068ad722f5acaefe5b67dea9960b4525a1 Mon Sep 17 00:00:00 2001 From: Jesica Date: Mon, 10 Jul 2023 09:05:34 -0400 Subject: [PATCH 05/14] add logger.warning --- openadapt/tools/printer.py | 58 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 openadapt/tools/printer.py diff --git a/openadapt/tools/printer.py b/openadapt/tools/printer.py new file mode 100644 index 000000000..f8bcf3ec8 --- /dev/null +++ b/openadapt/tools/printer.py @@ -0,0 +1,58 @@ +import sys +from PySide6.QtCore import QCoreApplication, Qt +from PySide6.QtWidgets import QApplication +from PySide6.QtPrintSupport import QPrinter, QPrintDialog, QPrinterInfo +from PySide6.QtGui import QPainter + +class PrinterIntegration: + def __init__(self): + self.app = QApplication(sys.argv) + + def get_available_printers(self): + printer_info_list = QPrinterInfo.availablePrinters() + printer_names = [printer.printerName() for printer in printer_info_list] + return printer_names + + def print_document(self, document_path, printer_name): + printer_info = QPrinterInfo.printerInfo(printer_name) + if printer_info is not None: + printer = QPrinter(printer_info) + printer.setOutputFormat(QPrinter.NativeFormat) + printer.setOutputFileName(document_path) + + print_dialog = QPrintDialog(printer) + print_dialog.setWindowTitle("Print Document") + print_dialog.setOptions(QPrintDialog.PrintToFile | QPrintDialog.PrintPageRange) + + if print_dialog.exec() == QPrintDialog.Accepted: + painter = QPainter(printer) + painter.begin(printer) + + # Draw your content on the painter + self.draw_content(painter) # Add your content drawing logic here + + painter.end() + + sys.exit(self.app.exec()) + + def draw_content(self, painter): + # Add your specific drawing logic here + # This is where you can draw the court record, revocation order, and warrant packet + + # Example: + painter.drawText(100, 100, "Court Record") + painter.drawText(200, 200, "Revocation Order") + painter.drawText(300, 300, "Warrant Packet") + +if __name__ == "__main__": + printer_integration = PrinterIntegration() + printer_names = printer_integration.get_available_printers() + if printer_names: + # Select the desired printer from the available options + selected_printer = printer_names[0] # Change this according to your requirements + + # Define the document path + document_path = "path/to/your/document.pdf" # Change this according to your requirements + + # Call the print_document method + printer_integration.print_document(document_path, selected_printer) From 5bbc2f3fea8bf243c36d31d5259aa02a74a06327 Mon Sep 17 00:00:00 2001 From: Jesica Date: Mon, 10 Jul 2023 09:06:00 -0400 Subject: [PATCH 06/14] add logger.warning --- openadapt/tools/printer.py | 58 ------------------------------------ openadapt/window/_windows.py | 3 +- 2 files changed, 2 insertions(+), 59 deletions(-) delete mode 100644 openadapt/tools/printer.py diff --git a/openadapt/tools/printer.py b/openadapt/tools/printer.py deleted file mode 100644 index f8bcf3ec8..000000000 --- a/openadapt/tools/printer.py +++ /dev/null @@ -1,58 +0,0 @@ -import sys -from PySide6.QtCore import QCoreApplication, Qt -from PySide6.QtWidgets import QApplication -from PySide6.QtPrintSupport import QPrinter, QPrintDialog, QPrinterInfo -from PySide6.QtGui import QPainter - -class PrinterIntegration: - def __init__(self): - self.app = QApplication(sys.argv) - - def get_available_printers(self): - printer_info_list = QPrinterInfo.availablePrinters() - printer_names = [printer.printerName() for printer in printer_info_list] - return printer_names - - def print_document(self, document_path, printer_name): - printer_info = QPrinterInfo.printerInfo(printer_name) - if printer_info is not None: - printer = QPrinter(printer_info) - printer.setOutputFormat(QPrinter.NativeFormat) - printer.setOutputFileName(document_path) - - print_dialog = QPrintDialog(printer) - print_dialog.setWindowTitle("Print Document") - print_dialog.setOptions(QPrintDialog.PrintToFile | QPrintDialog.PrintPageRange) - - if print_dialog.exec() == QPrintDialog.Accepted: - painter = QPainter(printer) - painter.begin(printer) - - # Draw your content on the painter - self.draw_content(painter) # Add your content drawing logic here - - painter.end() - - sys.exit(self.app.exec()) - - def draw_content(self, painter): - # Add your specific drawing logic here - # This is where you can draw the court record, revocation order, and warrant packet - - # Example: - painter.drawText(100, 100, "Court Record") - painter.drawText(200, 200, "Revocation Order") - painter.drawText(300, 300, "Warrant Packet") - -if __name__ == "__main__": - printer_integration = PrinterIntegration() - printer_names = printer_integration.get_available_printers() - if printer_names: - # Select the desired printer from the available options - selected_printer = printer_names[0] # Change this according to your requirements - - # Define the document path - document_path = "path/to/your/document.pdf" # Change this according to your requirements - - # Call the print_document method - printer_integration.print_document(document_path, selected_printer) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index 3e17de835..9df16d424 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -28,6 +28,7 @@ def get_active_window_state() -> dict: try: active_window = get_active_window() except RuntimeError as e: + logger.warning(e) return {} meta = get_active_window_meta(active_window) rectangle_dict = dictify_rect(meta["rectangle"]) @@ -122,7 +123,7 @@ def get_element_properties(element): try: properties = element.get_properties() - except comtypes.COMError: + except comtypes.COMError as com_err: logger.warning(f"COMError occurred: {com_err}") return {} children = element.children() From 3dc81e5c9eb058b748e6febb6f60510e03abdd0e Mon Sep 17 00:00:00 2001 From: Jesica Date: Tue, 11 Jul 2023 09:51:45 -0400 Subject: [PATCH 07/14] add get_properties --- openadapt/window/_windows.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index 9df16d424..4427b9aea 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -120,12 +120,7 @@ def get_element_properties(element): 'children': [{'prop1': 'child_value1', 'prop2': 'child_value2', 'children': []}]} """ - - try: - properties = element.get_properties() - except comtypes.COMError as com_err: - logger.warning(f"COMError occurred: {com_err}") - return {} + properties = get_properties(element) children = element.children() if children: @@ -164,6 +159,20 @@ def main(): ipdb.set_trace() +def get_properties(element): + """Return the properties of the control as a dictionary.""" + #import ipdb; ipdb.set_trace() + props = {} + + # for each of the properties that can be written out + for propname in element.writable_props: + # set the item in the props dictionary keyed on the propname + try : + props[propname] = getattr(element, propname)() + except : + continue + + return props if __name__ == "__main__": main() From 2769166efbd72aa4a5fedcbc7b891ca700c84969 Mon Sep 17 00:00:00 2001 From: Jesica Date: Tue, 11 Jul 2023 22:19:21 -0400 Subject: [PATCH 08/14] remove unnecessary imports --- openadapt/window/_windows.py | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index 4427b9aea..cbd0f3aab 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -1,12 +1,8 @@ -import collections -import sys from loguru import logger import pywinauto -from pywinauto import Desktop -import time from pprint import pprint import pickle -import comtypes + def get_active_window_state() -> dict: """ @@ -87,7 +83,7 @@ def get_active_element_state(x: int, y: int): return properties -def get_active_window(depth=10, max_width=10, filename=None) -> Desktop: +def get_active_window() -> Desktop: """ Get the active window object. @@ -159,20 +155,22 @@ def main(): ipdb.set_trace() + def get_properties(element): - """Return the properties of the control as a dictionary.""" - #import ipdb; ipdb.set_trace() - props = {} - - # for each of the properties that can be written out - for propname in element.writable_props: - # set the item in the props dictionary keyed on the propname - try : - props[propname] = getattr(element, propname)() - except : - continue - - return props + """Return the properties of the control as a dictionary.""" + # import ipdb; ipdb.set_trace() + props = {} + + # for each of the properties that can be written out + for propname in element.writable_props: + # set the item in the props dictionary keyed on the propname + try: + props[propname] = getattr(element, propname)() + except: + continue + + return props + if __name__ == "__main__": main() From faa3ec8d00878420b50513550a53f5a6835d00ad Mon Sep 17 00:00:00 2001 From: Jesica Date: Wed, 12 Jul 2023 06:23:44 -0400 Subject: [PATCH 09/14] remove -> Desktop --- openadapt/window/_windows.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index cbd0f3aab..a7bffdbca 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -83,7 +83,7 @@ def get_active_element_state(x: int, y: int): return properties -def get_active_window() -> Desktop: +def get_active_window(): """ Get the active window object. @@ -167,6 +167,7 @@ def get_properties(element): try: props[propname] = getattr(element, propname)() except: + import ipdb; ipdb.set_trace() continue return props From 58900120049bebf916a187423ddd18d14c5c008d Mon Sep 17 00:00:00 2001 From: Jesica Date: Wed, 12 Jul 2023 13:51:52 -0400 Subject: [PATCH 10/14] monkey patching --- openadapt/window/_windows.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index a7bffdbca..b64a62cbb 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -157,6 +157,12 @@ def main(): def get_properties(element): + #monkey patching + _get_properties = element.get_properties + element.get_properties = pywinauto.base_wrapper.BaseWrapper.get_properties + properties = element.get_properties() + element.get_properties = _get_properties + return properties """Return the properties of the control as a dictionary.""" # import ipdb; ipdb.set_trace() props = {} From 29e749bf7db61e22a8c2a75fca5467fd1cdf3038 Mon Sep 17 00:00:00 2001 From: Jesica Date: Thu, 13 Jul 2023 10:49:09 -0400 Subject: [PATCH 11/14] fix get_properties --- openadapt/window/_windows.py | 63 ++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index b64a62cbb..60bf7bc34 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -78,7 +78,7 @@ def get_active_element_state(x: int, y: int): """ active_window = get_active_window() active_element = active_window.from_point(x, y) - properties = active_element.get_properties() + properties = get_properties(active_element) properties["rectangle"] = dictify_rect(properties["rectangle"]) return properties @@ -138,6 +138,44 @@ def dictify_rect(rect): return rect_dict +def get_properties(element): + """ + Retrieves specific writable properties of an element. + + This function is used to obtain a dictionary of writable properties for + a given element. + The reason we are using this function instead of directly using the + `get_properties()` function is because the writable properties vary + for each element and we only want the default properties. + + Args: + element: The element for which to retrieve writable properties. + + Returns: + A dictionary containing the writable properties of the element, + with property names as keys and their corresponding values. + + """ + writable_props = [ + "class_name", + "friendly_class_name", + "texts", + "control_id", + "rectangle", + "is_visible", + "is_enabled", + "control_count", + ] + props = {} + + # for each of the properties that can be written out + for propname in writable_props: + # set the item in the props dictionary keyed on the propname + props[propname] = getattr(element, propname)() + + return props + + def main(): """ Test function for retrieving and inspecting the state of the active window. @@ -156,28 +194,5 @@ def main(): ipdb.set_trace() -def get_properties(element): - #monkey patching - _get_properties = element.get_properties - element.get_properties = pywinauto.base_wrapper.BaseWrapper.get_properties - properties = element.get_properties() - element.get_properties = _get_properties - return properties - """Return the properties of the control as a dictionary.""" - # import ipdb; ipdb.set_trace() - props = {} - - # for each of the properties that can be written out - for propname in element.writable_props: - # set the item in the props dictionary keyed on the propname - try: - props[propname] = getattr(element, propname)() - except: - import ipdb; ipdb.set_trace() - continue - - return props - - if __name__ == "__main__": main() From 02e2373d29a699df3c0eee9f5cd038ede0831912 Mon Sep 17 00:00:00 2001 From: Jesica Date: Thu, 13 Jul 2023 13:57:33 -0400 Subject: [PATCH 12/14] monkey patch __class__ --- openadapt/window/_windows.py | 37 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index 60bf7bc34..cb5d4d2c1 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -92,7 +92,7 @@ def get_active_window(): """ app = pywinauto.application.Application(backend="uia").connect(active_only=True) window = app.top_window() - return window + return window.wrapper_object() def get_element_properties(element): @@ -142,38 +142,25 @@ def get_properties(element): """ Retrieves specific writable properties of an element. - This function is used to obtain a dictionary of writable properties for - a given element. - The reason we are using this function instead of directly using the - `get_properties()` function is because the writable properties vary - for each element and we only want the default properties. + This function retrieves a dictionary of writable properties for a given element. + It achieves this by temporarily modifying the class of the element object using + monkey patching.This approach is necessary because in some cases, the original + class of the element may have a `get_properties()` function that raises errors. Args: element: The element for which to retrieve writable properties. Returns: A dictionary containing the writable properties of the element, - with property names as keys and their corresponding values. + with property names as keys and their corres + ponding values. """ - writable_props = [ - "class_name", - "friendly_class_name", - "texts", - "control_id", - "rectangle", - "is_visible", - "is_enabled", - "control_count", - ] - props = {} - - # for each of the properties that can be written out - for propname in writable_props: - # set the item in the props dictionary keyed on the propname - props[propname] = getattr(element, propname)() - - return props + _element_class = element.__class__ + element.__class__ = pywinauto.base_wrapper.BaseWrapper + properties = element.get_properties() + element.__class__ = _element_class + return properties def main(): From cc0eb4b6db99fa8c4150bb0d3ae81c6a10159730 Mon Sep 17 00:00:00 2001 From: Jesica Date: Thu, 13 Jul 2023 15:31:55 -0400 Subject: [PATCH 13/14] fix monkey patching --- openadapt/window/_windows.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index cb5d4d2c1..4f1784670 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -157,12 +157,18 @@ class of the element may have a `get_properties()` function that raises errors. """ _element_class = element.__class__ - element.__class__ = pywinauto.base_wrapper.BaseWrapper + class TempElement(element.__class__): + writable_props = pywinauto.base_wrapper.BaseWrapper.writable_props + + # Instantiate the subclass + element.__class__ = TempElement + # Retrieve properties using get_properties() properties = element.get_properties() element.__class__ = _element_class return properties + def main(): """ Test function for retrieving and inspecting the state of the active window. From 6685c3695ad5d69a6379f537a55bb7a93b631d39 Mon Sep 17 00:00:00 2001 From: Jesica Date: Fri, 14 Jul 2023 14:18:24 -0400 Subject: [PATCH 14/14] format with black --- openadapt/window/_windows.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openadapt/window/_windows.py b/openadapt/window/_windows.py index 4f1784670..40b74250b 100644 --- a/openadapt/window/_windows.py +++ b/openadapt/window/_windows.py @@ -144,21 +144,22 @@ def get_properties(element): This function retrieves a dictionary of writable properties for a given element. It achieves this by temporarily modifying the class of the element object using - monkey patching.This approach is necessary because in some cases, the original + monkey patching.This approach is necessary because in some cases, the original class of the element may have a `get_properties()` function that raises errors. Args: element: The element for which to retrieve writable properties. Returns: - A dictionary containing the writable properties of the element, + A dictionary containing the writable properties of the element, with property names as keys and their corres ponding values. """ _element_class = element.__class__ + class TempElement(element.__class__): - writable_props = pywinauto.base_wrapper.BaseWrapper.writable_props + writable_props = pywinauto.base_wrapper.BaseWrapper.writable_props # Instantiate the subclass element.__class__ = TempElement @@ -168,7 +169,6 @@ class TempElement(element.__class__): return properties - def main(): """ Test function for retrieving and inspecting the state of the active window.