From 637c20e6d7acb79a8fea4a8647419f5ef1e99a04 Mon Sep 17 00:00:00 2001 From: TrevisanGMW Date: Tue, 5 Sep 2023 11:09:52 -0700 Subject: [PATCH 01/24] Updated patch version --- gt/tools/influences_to_python/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gt/tools/influences_to_python/__init__.py b/gt/tools/influences_to_python/__init__.py index af9a8f9c..75f763f9 100644 --- a/gt/tools/influences_to_python/__init__.py +++ b/gt/tools/influences_to_python/__init__.py @@ -25,7 +25,7 @@ # Tool Version -__version_tuple__ = (2, 0, 0) +__version_tuple__ = (2, 0, 1) __version_suffix__ = '' __version__ = '.'.join(str(n) for n in __version_tuple__) + __version_suffix__ From 8c66d2a25b8c6ac2a23a23a30341aece3959586f Mon Sep 17 00:00:00 2001 From: TrevisanGMW Date: Tue, 5 Sep 2023 11:10:43 -0700 Subject: [PATCH 02/24] Fixed no selection error --- .../influences_python_controller.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gt/tools/influences_to_python/influences_python_controller.py b/gt/tools/influences_to_python/influences_python_controller.py index abe7f9fa..ef477193 100644 --- a/gt/tools/influences_to_python/influences_python_controller.py +++ b/gt/tools/influences_to_python/influences_python_controller.py @@ -51,11 +51,13 @@ def extract_influence_python(self): """ include_bound_mesh = self.view.include_mesh_chk.isChecked() include_existing_filter = self.view.non_existent_chk.isChecked() - _code = "import maya.cmds as cmds\n\n" - _code += selected_get_python_influences_code(include_bound_mesh=include_bound_mesh, - include_existing_filter=include_existing_filter) - self.view.clear_python_output() - self.view.set_python_output_text(text=_code) + _maya_import = "import maya.cmds as cmds\n\n" + _code = selected_get_python_influences_code(include_bound_mesh=include_bound_mesh, + include_existing_filter=include_existing_filter) + if _code: + _code = _maya_import + _code + self.view.clear_python_output() + self.view.set_python_output_text(text=_code) @staticmethod def extract_influence_set(): From a7e1160e812c5bbc0d43192569fb4b9e5b9792b4 Mon Sep 17 00:00:00 2001 From: TrevisanGMW Date: Tue, 5 Sep 2023 11:11:33 -0700 Subject: [PATCH 03/24] Updated patch version --- gt/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gt/__init__.py b/gt/__init__.py index 20387936..21fd2134 100644 --- a/gt/__init__.py +++ b/gt/__init__.py @@ -1,7 +1,7 @@ import sys # Package Variables -__version_tuple__ = (3, 1, 10) +__version_tuple__ = (3, 1, 11) __version_suffix__ = '' __version__ = '.'.join(str(n) for n in __version_tuple__) + __version_suffix__ __authors__ = ['Guilherme Trevisan'] From 63864d2ec0ce618cb16800940b67d5f3b96a2c31 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 13:06:59 -0700 Subject: [PATCH 04/24] Added get_screen_dpi_scale --- gt/ui/qt_utils.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/gt/ui/qt_utils.py b/gt/ui/qt_utils.py index b97fdc77..5e98250b 100644 --- a/gt/ui/qt_utils.py +++ b/gt/ui/qt_utils.py @@ -562,6 +562,31 @@ def create_color_icon(color, width=24, height=24): return icon +def get_screen_dpi_scale(screen_number): + """ + Calculate the scale factor of the DPI for a given screen number. + + Args: + screen_number (int): The index of the screen for which to calculate DPI percentage. + + Returns: + float: The scale factor of DPI for the specified screen. + + Raises: + ValueError: If the screen number is out of range. + """ + app = QApplication.instance() + screen_list = app.screens() + + if 0 <= screen_number < len(screen_list): + target_screen = screen_list[screen_number] + dpi_scale_factor = target_screen.logicalDotsPerInch() / 96.0 + + return dpi_scale_factor + else: + raise ValueError("Invalid screen number. Please provide a valid screen number.") + + if __name__ == "__main__": with QtApplicationContext() as context: print(context) From 47c39a90b487bc49fcde98a6868e4b3acc712028 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 13:08:22 -0700 Subject: [PATCH 05/24] Fixed DPI scale description issue --- gt/tools/curve_library/__init__.py | 2 +- gt/tools/curve_library/curve_library_view.py | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/gt/tools/curve_library/__init__.py b/gt/tools/curve_library/__init__.py index 40baf653..0f36f1ed 100644 --- a/gt/tools/curve_library/__init__.py +++ b/gt/tools/curve_library/__init__.py @@ -14,7 +14,7 @@ logger.setLevel(logging.INFO) # Tool Version -__version_tuple__ = (1, 1, 2) +__version_tuple__ = (1, 1, 3) __version_suffix__ = '' __version__ = '.'.join(str(n) for n in __version_tuple__) + __version_suffix__ diff --git a/gt/tools/curve_library/curve_library_view.py b/gt/tools/curve_library/curve_library_view.py index 902ab7be..16354f55 100644 --- a/gt/tools/curve_library/curve_library_view.py +++ b/gt/tools/curve_library/curve_library_view.py @@ -51,6 +51,10 @@ def __init__(self, parent=None, controller=None, version=None): QtCore.Qt.WindowMaximizeButtonHint | QtCore.Qt.WindowMinimizeButtonHint) self.setWindowIcon(QIcon(resource_library.Icon.tool_crv_library)) + # from PySide2.QtGui import QScreen + # primary_screen = QScreen.primaryScreen() + # dpi = primary_screen.physicalDotsPerInch() + # print(dpi) stylesheet = resource_library.Stylesheet.scroll_bar_dark stylesheet += resource_library.Stylesheet.maya_basic_dialog @@ -91,7 +95,7 @@ def create_widgets(self): self.delete_custom_button.setEnabled(False) self.delete_custom_button.setIcon(QIcon(resource_library.Icon.curve_library_remove)) self.description = QLabel("") - self.description.setMaximumHeight(20) + self.description.setAlignment(Qt.AlignCenter) self.snapshot_button = QPushButton("Create Snapshot") self.snapshot_button.setEnabled(False) @@ -102,6 +106,20 @@ def create_widgets(self): # Initial Image Update self.update_preview_image() + def moveEvent(self, event): + """ + Move Event, called when the window is moved (must use this name "moveEvent") + Updates the maximum size of the description according to the scale factor of the current screen. + On windows Settings > Display > Scale and layout > Change the size of text, apps, and other items > % + """ + desktop = QDesktopWidget() + screen_number = desktop.screenNumber(self) + + from gt.ui import qt_utils + scale_factor = qt_utils.get_screen_dpi_scale(screen_number) + default_maximum_height_description = 20 + self.description.setMaximumHeight(default_maximum_height_description*scale_factor) + def create_layout(self): """Create the layout for the window.""" From ddad1fd96bd4c67417fe35b4e0cd92ae3cd8f05d Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 13:08:35 -0700 Subject: [PATCH 06/24] Fixed DPI scale issue --- gt/tools/resource_library/__init__.py | 2 +- .../resource_library/resource_library_view.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/gt/tools/resource_library/__init__.py b/gt/tools/resource_library/__init__.py index df2cd43b..0d9ffdb9 100644 --- a/gt/tools/resource_library/__init__.py +++ b/gt/tools/resource_library/__init__.py @@ -14,7 +14,7 @@ logger.setLevel(logging.INFO) # Tool Version -__version_tuple__ = (1, 0, 0) +__version_tuple__ = (1, 0, 1) __version_suffix__ = '' __version__ = '.'.join(str(n) for n in __version_tuple__) + __version_suffix__ diff --git a/gt/tools/resource_library/resource_library_view.py b/gt/tools/resource_library/resource_library_view.py index 281a8398..c75e2ce4 100644 --- a/gt/tools/resource_library/resource_library_view.py +++ b/gt/tools/resource_library/resource_library_view.py @@ -61,6 +61,22 @@ def __init__(self, parent=None, controller=None, version=None): qt_utils.center_window(self) self.resize_splitter_to_screen() + def moveEvent(self, event): + """ + Move Event, called when the window is moved (must use this name "moveEvent") + Updates the maximum size of the description/resource_path according to the scale factor of the current screen. + On windows Settings > Display > Scale and layout > Change the size of text, apps, and other items > % + """ + desktop = QDesktopWidget() + screen_number = desktop.screenNumber(self) + + from gt.ui import qt_utils + scale_factor = qt_utils.get_screen_dpi_scale(screen_number) + default_maximum_height_description = 20 + self.description.setMaximumHeight(default_maximum_height_description*scale_factor) + default_maximum_height_resource = 40 + self.resource_path.setMaximumHeight(default_maximum_height_resource*scale_factor) + def update_preview_image(self, new_image=None): """ Update the preview image displayed in the window. From 690ce24b5c84d8c1be0900840cfd20e5e6b71e32 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 13:43:05 -0700 Subject: [PATCH 07/24] Added get_window_screen_number --- gt/ui/qt_utils.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/gt/ui/qt_utils.py b/gt/ui/qt_utils.py index 5e98250b..c3535e85 100644 --- a/gt/ui/qt_utils.py +++ b/gt/ui/qt_utils.py @@ -294,7 +294,7 @@ def get_qt_color(color): logger.error(f'Unable to create QColor. Unrecognized object type received: "{type(color)}"') -def resize_to_screen(window, percentage=20, width_percentage=None, height_percentage=None): +def resize_to_screen(window, percentage=20, width_percentage=None, height_percentage=None, dpi_scale=False): """ Resizes the window to match a percentage of the screen size. @@ -302,8 +302,10 @@ def resize_to_screen(window, percentage=20, width_percentage=None, height_percen window (QDialog, any): Window to be resized. percentage (int, optional): The percentage of the screen size that the window should inherit. Must be a value between 0 and 100. Default is 20. - width_percentage (int, optional): If provided, it will overwrite general set percentage when setting width - height_percentage (int, optional): If provided, it will overwrite general set percentage when setting height + width_percentage (int, optional): If provided, it will overwrite general set percentage when setting width. + height_percentage (int, optional): If provided, it will overwrite general set percentage when setting height. + dpi_scale (bool, optional): When active, it will multiply the size of the window by the DPI scale factor. + It will limit it to the size of the window. Raises: ValueError: If the percentage is not within the range [0, 100]. @@ -318,6 +320,18 @@ def resize_to_screen(window, percentage=20, width_percentage=None, height_percen height = screen_geometry.height() * height_percentage / 100 if width_percentage: width = screen_geometry.height() * width_percentage / 100 + if dpi_scale: + dpi_scale = get_screen_dpi_scale(get_window_screen_number(window=window)) + scaled_height = height*dpi_scale + if scaled_height <= screen_geometry.height(): + height = scaled_height + else: + height = screen_geometry.height() + scaled_width = width*dpi_scale + if scaled_width <= screen_geometry.width(): + width = scaled_width + else: + width = screen_geometry.width() window.setGeometry(0, 0, width, height) @@ -336,6 +350,19 @@ def get_main_window_screen_number(): return screen_number +def get_window_screen_number(window): + """ + Determines the screen number where the provided Qt windows is located. + Args: + window (QWidget): Qt Window used to determine screen number + Returns: + int: Screen number where the window is located. + """ + desktop = QDesktopWidget() + screen_number = desktop.screenNumber(window) + return screen_number + + def center_window(window): """ Moves the given window to the center of the screen. @@ -580,8 +607,8 @@ def get_screen_dpi_scale(screen_number): if 0 <= screen_number < len(screen_list): target_screen = screen_list[screen_number] - dpi_scale_factor = target_screen.logicalDotsPerInch() / 96.0 - + standard_dpi = 96.0 + dpi_scale_factor = target_screen.logicalDotsPerInch() / standard_dpi return dpi_scale_factor else: raise ValueError("Invalid screen number. Please provide a valid screen number.") From 665623153ccf91b3031b48e4b8b4c854f3938eb1 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 13:59:18 -0700 Subject: [PATCH 08/24] Removed unnecessary imports --- gt/tools/curve_library/curve_library_view.py | 26 ++++++++-------- .../resource_library/resource_library_view.py | 30 +++++++++---------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/gt/tools/curve_library/curve_library_view.py b/gt/tools/curve_library/curve_library_view.py index 16354f55..ed84bcc9 100644 --- a/gt/tools/curve_library/curve_library_view.py +++ b/gt/tools/curve_library/curve_library_view.py @@ -106,20 +106,6 @@ def create_widgets(self): # Initial Image Update self.update_preview_image() - def moveEvent(self, event): - """ - Move Event, called when the window is moved (must use this name "moveEvent") - Updates the maximum size of the description according to the scale factor of the current screen. - On windows Settings > Display > Scale and layout > Change the size of text, apps, and other items > % - """ - desktop = QDesktopWidget() - screen_number = desktop.screenNumber(self) - - from gt.ui import qt_utils - scale_factor = qt_utils.get_screen_dpi_scale(screen_number) - default_maximum_height_description = 20 - self.description.setMaximumHeight(default_maximum_height_description*scale_factor) - def create_layout(self): """Create the layout for the window.""" @@ -252,6 +238,18 @@ def update_curve_description(self, new_title, new_description): output_color="white", overall_alignment="center") + def moveEvent(self, event): + """ + Move Event, called when the window is moved (must use this name "moveEvent") + Updates the maximum size of the description according to the scale factor of the current screen. + On windows Settings > Display > Scale and layout > Change the size of text, apps, and other items > % + """ + desktop = QDesktopWidget() + screen_number = desktop.screenNumber(self) + scale_factor = qt_utils.get_screen_dpi_scale(screen_number) + default_maximum_height_description = 20 + self.description.setMaximumHeight(default_maximum_height_description*scale_factor) + if __name__ == "__main__": with qt_utils.QtApplicationContext(): diff --git a/gt/tools/resource_library/resource_library_view.py b/gt/tools/resource_library/resource_library_view.py index c75e2ce4..eaaa661e 100644 --- a/gt/tools/resource_library/resource_library_view.py +++ b/gt/tools/resource_library/resource_library_view.py @@ -61,22 +61,6 @@ def __init__(self, parent=None, controller=None, version=None): qt_utils.center_window(self) self.resize_splitter_to_screen() - def moveEvent(self, event): - """ - Move Event, called when the window is moved (must use this name "moveEvent") - Updates the maximum size of the description/resource_path according to the scale factor of the current screen. - On windows Settings > Display > Scale and layout > Change the size of text, apps, and other items > % - """ - desktop = QDesktopWidget() - screen_number = desktop.screenNumber(self) - - from gt.ui import qt_utils - scale_factor = qt_utils.get_screen_dpi_scale(screen_number) - default_maximum_height_description = 20 - self.description.setMaximumHeight(default_maximum_height_description*scale_factor) - default_maximum_height_resource = 40 - self.resource_path.setMaximumHeight(default_maximum_height_resource*scale_factor) - def update_preview_image(self, new_image=None): """ Update the preview image displayed in the window. @@ -222,6 +206,20 @@ def update_item_description(self, new_title, new_description): output_color="white", overall_alignment="center") + def moveEvent(self, event): + """ + Move Event, called when the window is moved (must use this name "moveEvent") + Updates the maximum size of the description/resource_path according to the scale factor of the current screen. + On windows Settings > Display > Scale and layout > Change the size of text, apps, and other items > % + """ + desktop = QDesktopWidget() + screen_number = desktop.screenNumber(self) + scale_factor = qt_utils.get_screen_dpi_scale(screen_number) + default_maximum_height_description = 20 + self.description.setMaximumHeight(default_maximum_height_description*scale_factor) + default_maximum_height_resource = 40 + self.resource_path.setMaximumHeight(default_maximum_height_resource*scale_factor) + if __name__ == "__main__": with qt_utils.QtApplicationContext(): From 247a1c35916e8e2244d40c3e73ccc4ab8460bc1d Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 15:43:45 -0700 Subject: [PATCH 09/24] Added dpi_scale to resize_to_screen --- gt/ui/qt_utils.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/gt/ui/qt_utils.py b/gt/ui/qt_utils.py index c3535e85..4b7ae46b 100644 --- a/gt/ui/qt_utils.py +++ b/gt/ui/qt_utils.py @@ -294,7 +294,9 @@ def get_qt_color(color): logger.error(f'Unable to create QColor. Unrecognized object type received: "{type(color)}"') -def resize_to_screen(window, percentage=20, width_percentage=None, height_percentage=None, dpi_scale=False): +def resize_to_screen(window, percentage=20, + width_percentage=None, height_percentage=None, + dpi_scale=False, dpi_percentage=20, dpi_ignore_below_one=True): """ Resizes the window to match a percentage of the screen size. @@ -306,6 +308,11 @@ def resize_to_screen(window, percentage=20, width_percentage=None, height_percen height_percentage (int, optional): If provided, it will overwrite general set percentage when setting height. dpi_scale (bool, optional): When active, it will multiply the size of the window by the DPI scale factor. It will limit it to the size of the window. + dpi_percentage (float, int, optional): If using dpi scale, this number determines the percentage of the scale + influences the window. + For example: if "dpi_scale" is 10 and "dpi_percentage" is 50, + the used value for "dpi_scale" will become 5 (50% of 10) + dpi_ignore_below_one (bool, optional): When active, it ignores DPI calculations when the scale is 1 (100%) Raises: ValueError: If the percentage is not within the range [0, 100]. @@ -322,6 +329,9 @@ def resize_to_screen(window, percentage=20, width_percentage=None, height_percen width = screen_geometry.height() * width_percentage / 100 if dpi_scale: dpi_scale = get_screen_dpi_scale(get_window_screen_number(window=window)) + dpi_scale = dpi_scale * (dpi_percentage / 100) + if dpi_ignore_below_one and dpi_scale < 1.0: + dpi_scale = 1.0 scaled_height = height*dpi_scale if scaled_height <= screen_geometry.height(): height = scaled_height From 061e04ce7fe8d5af4f527b4229db3ab9889eaf7c Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 15:44:22 -0700 Subject: [PATCH 10/24] Used screen DPI when setting initial scale --- gt/ui/progress_bar.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gt/ui/progress_bar.py b/gt/ui/progress_bar.py index 284c9edf..1ef36dac 100644 --- a/gt/ui/progress_bar.py +++ b/gt/ui/progress_bar.py @@ -61,6 +61,8 @@ def __init__(self, parent=None, output_text=True, has_second_button=False): # Window self.setGeometry(0, 0, _min_width, _min_height) # Args X, Y, W, H self.setMinimumWidth(_min_width*.8) # 80% of the maximum width + qt_utils.resize_to_screen(window=self, height_percentage=20, width_percentage=25, + dpi_scale=True, dpi_percentage=20) qt_utils.center_window(self) # Window Details self.setWindowTitle("Progress Bar") From 6966198a2691539eabe15e42356ea3ab5024c9d2 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 15:44:39 -0700 Subject: [PATCH 11/24] Set font size to fix DPI issues --- gt/tools/curve_library/curve_library_view.py | 7 ++++++- .../resource_library/resource_library_view.py | 21 ++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/gt/tools/curve_library/curve_library_view.py b/gt/tools/curve_library/curve_library_view.py index ed84bcc9..b9364bb2 100644 --- a/gt/tools/curve_library/curve_library_view.py +++ b/gt/tools/curve_library/curve_library_view.py @@ -2,8 +2,8 @@ Curve Library View - The main GUI window class for the Curve Library tool. """ from PySide2.QtWidgets import QListWidget, QPushButton, QWidget, QSplitter, QLineEdit, QDesktopWidget, QListWidgetItem +from PySide2.QtGui import QIcon, QPixmap, QColor, QFont import gt.ui.resource_library as resource_library -from PySide2.QtGui import QIcon, QPixmap, QColor from gt.ui.squared_widget import SquaredWidget from gt.ui.qt_utils import MayaWindowMeta from PySide2 import QtWidgets, QtCore @@ -79,11 +79,15 @@ def update_preview_image(self, new_image_path=None): def create_widgets(self): """Create the widgets for the window.""" + font = QFont() + font.setPointSize(10) self.item_list = QListWidget() + self.item_list.setFont(font) self.build_button = QPushButton("Build") self.build_button.setIcon(QIcon(resource_library.Icon.curve_library_build)) self.build_button.setStyleSheet(resource_library.Stylesheet.push_button_bright) self.search_bar = QLineEdit(self) + self.search_bar.setFont(font) self.search_bar.setPlaceholderText('Search...') self.preview_image = SquaredWidget(self, center_y=False) # Buttons @@ -95,6 +99,7 @@ def create_widgets(self): self.delete_custom_button.setEnabled(False) self.delete_custom_button.setIcon(QIcon(resource_library.Icon.curve_library_remove)) self.description = QLabel("") + self.description.setFont(font) self.description.setAlignment(Qt.AlignCenter) self.snapshot_button = QPushButton("Create Snapshot") diff --git a/gt/tools/resource_library/resource_library_view.py b/gt/tools/resource_library/resource_library_view.py index eaaa661e..c1349945 100644 --- a/gt/tools/resource_library/resource_library_view.py +++ b/gt/tools/resource_library/resource_library_view.py @@ -3,9 +3,9 @@ """ from PySide2.QtWidgets import QListWidget, QPushButton, QWidget, QSplitter, QLineEdit, QDesktopWidget, QListWidgetItem from gt.ui.syntax_highlighter import PythonSyntaxHighlighter +from PySide2.QtGui import QIcon, QPixmap, QColor, QFont from PySide2.QtWidgets import QTextEdit, QComboBox import gt.ui.resource_library as resource_library -from PySide2.QtGui import QIcon, QPixmap, QColor from gt.ui.squared_widget import SquaredWidget from gt.ui.qt_utils import MayaWindowMeta from PySide2 import QtWidgets, QtCore @@ -78,26 +78,30 @@ def update_preview_image(self, new_image=None): def create_widgets(self): """Create the widgets for the window.""" + font = QFont() + font.setPointSize(10) self.item_list = QListWidget() + self.item_list.setFont(font) self.save_btn = QPushButton("Export Resource") self.save_btn.setIcon(QIcon(resource_library.Icon.curve_library_build)) self.save_btn.setStyleSheet(resource_library.Stylesheet.push_button_bright) self.search_bar = QLineEdit(self) + self.search_bar.setFont(font) self.search_bar.setPlaceholderText('Search...') self.preview_image = SquaredWidget(self, center_y=False) self.resource_path = QTextEdit() PythonSyntaxHighlighter(self.resource_path.document()) - self.resource_path.setMaximumHeight(60) + self.resource_path.setFontPointSize(10) self.source_combo_box = QComboBox() + self.source_combo_box.setFont(font) self.source_combo_box.addItem("All") self.source_combo_box.addItem("Package Resources") self.source_combo_box.addItem("Package Icons Only") self.source_combo_box.addItem("Package Colors Only") self.source_combo_box.addItem("Maya Resources") - self.description = QLabel("") - self.description.setMaximumHeight(20) + self.description.setFont(font) self.description.setAlignment(Qt.AlignCenter) # Initial Image Update self.update_preview_image() @@ -217,7 +221,7 @@ def moveEvent(self, event): scale_factor = qt_utils.get_screen_dpi_scale(screen_number) default_maximum_height_description = 20 self.description.setMaximumHeight(default_maximum_height_description*scale_factor) - default_maximum_height_resource = 40 + default_maximum_height_resource = 50 self.resource_path.setMaximumHeight(default_maximum_height_resource*scale_factor) @@ -225,8 +229,9 @@ def moveEvent(self, event): with qt_utils.QtApplicationContext(): window = ResourceLibraryView() mocked_icon = QIcon(resource_library.Icon.curve_library_base_curve) - window.add_item_view_library("item_one", icon=QIcon(resource_library.Icon.curve_library_user_curve)) - window.add_item_view_library("item_two", icon=QIcon(resource_library.Icon.curve_library_control)) + window.add_item_view_library(item_name="item_one", icon=QIcon(resource_library.Icon.curve_library_user_curve)) + window.add_item_view_library(item_name="item_two", icon=QIcon(resource_library.Icon.curve_library_control)) for index in range(1, 101): - window.add_item_view_library(f"item_with_a_very_long_name_for_testing_ui_{index}", icon=mocked_icon) + window.add_item_view_library(item_name=f"item_with_a_very_long_name_for_testing_ui_{index}", + icon=mocked_icon) window.show() From 2c65d3f6bdc278c79446025da4dc3b9b26e184e1 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 20:39:44 -0700 Subject: [PATCH 12/24] Created unittests --- gt/ui/progress_bar.py | 1 - tests/test_ui/test_progress_bar.py | 74 ++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/test_ui/test_progress_bar.py diff --git a/gt/ui/progress_bar.py b/gt/ui/progress_bar.py index 1ef36dac..11ab67e7 100644 --- a/gt/ui/progress_bar.py +++ b/gt/ui/progress_bar.py @@ -298,4 +298,3 @@ def close_parent_window(self): out = window.get_output_box_plain_text() print(out) sys.exit(app.exec_()) - diff --git a/tests/test_ui/test_progress_bar.py b/tests/test_ui/test_progress_bar.py new file mode 100644 index 00000000..da3f43a3 --- /dev/null +++ b/tests/test_ui/test_progress_bar.py @@ -0,0 +1,74 @@ +from PySide2.QtWidgets import QApplication +import unittest +import logging +import sys +import os + +# Logging Setup +logging.basicConfig() +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + +# Import Tested Script +test_utils_dir = os.path.dirname(__file__) +tests_dir = os.path.dirname(test_utils_dir) +package_root_dir = os.path.dirname(tests_dir) +for to_append in [package_root_dir, tests_dir]: + if to_append not in sys.path: + sys.path.append(to_append) +from gt.ui.progress_bar import ProgressBarWindow + + +class TestInputWindowText(unittest.TestCase): + @classmethod + def setUpClass(cls): + app = QApplication.instance() + if not app: + cls.app = QApplication(sys.argv) + + def setUp(self): + self.window = ProgressBarWindow() + + def test_set_progress_bar_value(self): + window = ProgressBarWindow() + window.show() + + # Test setting the progress bar value + window.set_progress_bar_value(50) + self.assertEqual(window.progress_bar.value(), 50) + + def test_add_text_to_output_box(self): + window = ProgressBarWindow() + + # Test adding text to the output box + text_to_add = "This is a test message." + window.add_text_to_output_box(text_to_add) + output_text = window.get_output_box_plain_text() + self.assertIn(text_to_add, output_text) + + def test_change_line_color(self): + window = ProgressBarWindow() + + # Test changing the color of a specific line + text_to_add = "This is a test message." + window.add_text_to_output_box(text_to_add) + window.change_line_color(line_number=1, color="red") + + # Get the formatted text and check if it contains the color tag + output_text = window.get_output_box_plain_text() + self.assertIn(text_to_add, output_text) + + def test_change_last_line_color(self): + window = ProgressBarWindow() + + # Test changing the color of the last line + text_to_add1 = "This is line 1." + text_to_add2 = "This is line 2." + window.add_text_to_output_box(text_to_add1) + window.add_text_to_output_box(text_to_add2) + window.change_last_line_color("blue") + + # Get the formatted text and check if the last line contains the color tag + output_text = window.get_output_box_plain_text() + self.assertIn(text_to_add1, output_text) + self.assertIn(text_to_add2, output_text) From 150ace6b4a6d0f46d4b489cee120e4669ccb908b Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 20:39:59 -0700 Subject: [PATCH 13/24] Created unittests --- tests/__init__.py | 9 +++- tests/test_ui/__init__.py | 4 ++ tests/test_ui/test_input_window_text.py | 55 +++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 tests/test_ui/test_input_window_text.py diff --git a/tests/__init__.py b/tests/__init__.py index 081bc06c..1366d0ca 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -28,10 +28,17 @@ # Modules to Test modules_to_test = [ + # Ui + test_ui.test_input_window_text, + test_ui.test_line_text_widget, + test_ui.test_maya_menu, + test_ui.test_progress_bar, + test_ui.test_resource_library, + # Tools test_curve_library.test_curve_library_model, test_package_updater.test_package_updater_model, test_sample_tool.test_sample_tool_model, - test_ui.test_resource_library, + # Utils test_utils.test_alembic_utils, test_utils.test_anim_utils, test_utils.test_attr_utils, diff --git a/tests/test_ui/__init__.py b/tests/test_ui/__init__.py index cfb2f03b..078bb0a6 100644 --- a/tests/test_ui/__init__.py +++ b/tests/test_ui/__init__.py @@ -1 +1,5 @@ +from . import test_input_window_text +from . import test_line_text_widget +from . import test_maya_menu +from . import test_progress_bar from . import test_resource_library diff --git a/tests/test_ui/test_input_window_text.py b/tests/test_ui/test_input_window_text.py new file mode 100644 index 00000000..00c39671 --- /dev/null +++ b/tests/test_ui/test_input_window_text.py @@ -0,0 +1,55 @@ +from PySide2.QtWidgets import QApplication +import unittest +import logging +import sys +import os + +# Logging Setup +logging.basicConfig() +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + +# Import Tested Script +test_utils_dir = os.path.dirname(__file__) +tests_dir = os.path.dirname(test_utils_dir) +package_root_dir = os.path.dirname(tests_dir) +for to_append in [package_root_dir, tests_dir]: + if to_append not in sys.path: + sys.path.append(to_append) +from gt.ui.input_window_text import InputWindowText + + +class TestInputWindowText(unittest.TestCase): + @classmethod + def setUpClass(cls): + app = QApplication.instance() + if not app: + cls.app = QApplication(sys.argv) + + def setUp(self): + self.window = InputWindowText() + + def test_window_title(self): + expected_title = "New Window Title" + self.window.set_window_title(expected_title) + self.assertEqual(self.window.windowTitle(), expected_title) + + def test_text_field_text(self): + expected_text = "Sample Text" + self.window.set_text_field_text(expected_text) + self.assertEqual(self.window.get_text_field_text(), expected_text) + + def test_text_field_placeholder(self): + expected_placeholder = "Enter text here" + self.window.set_text_field_placeholder(expected_placeholder) + self.assertEqual(self.window.text_field.placeholderText(), expected_placeholder) + + def test_confirm_button_text(self): + expected_button_text = "OK" + self.window.set_confirm_button_text(expected_button_text) + self.assertEqual(self.window.confirm_button.text(), expected_button_text) + + def test_message_label(self): + expected_message = "This is a test message" + self.window.set_message(expected_message) + self.assertEqual(self.window.description_label.text(), expected_message) From c51d80db0690ffdd6ba7b0721a4713306183e933 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 20:40:05 -0700 Subject: [PATCH 14/24] Created unittests --- tests/test_ui/test_line_text_widget.py | 47 ++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/test_ui/test_line_text_widget.py diff --git a/tests/test_ui/test_line_text_widget.py b/tests/test_ui/test_line_text_widget.py new file mode 100644 index 00000000..90955f09 --- /dev/null +++ b/tests/test_ui/test_line_text_widget.py @@ -0,0 +1,47 @@ +from PySide2.QtWidgets import QApplication, QDialog, QVBoxLayout +from PySide2.QtGui import QColor +import unittest +import logging +import sys +import os + +# Logging Setup +logging.basicConfig() +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + +# Import Tested Script +test_utils_dir = os.path.dirname(__file__) +tests_dir = os.path.dirname(test_utils_dir) +package_root_dir = os.path.dirname(tests_dir) +for to_append in [package_root_dir, tests_dir]: + if to_append not in sys.path: + sys.path.append(to_append) +from gt.ui.line_text_widget import LineTextWidget + + +class TestLineTextWidget(unittest.TestCase): + @classmethod + def setUpClass(cls): + app = QApplication.instance() + if not app: + cls.app = QApplication(sys.argv) + + def test_line_number_color(self): + line_text_widget = LineTextWidget() + line_text_widget.set_line_number_color(color=QColor(255, 0, 0)) # Set a red color + self.assertEqual(line_text_widget.number_bar.number_color, QColor(255, 0, 0)) + + def test_line_number_bold_color(self): + line_text_widget = LineTextWidget() + line_text_widget.line_number_bold_color(color=QColor(0, 255, 0)) # Set a green color + self.assertEqual(line_text_widget.number_bar.number_bold_color, QColor(0, 255, 0)) + + def test_dialog_with_syntax_highlighter(self): + from gt.ui.syntax_highlighter import PythonSyntaxHighlighter + dialog = QDialog() + layout = QVBoxLayout(dialog) + line_text_widget = LineTextWidget() + dialog.setLayout(layout) + layout.addWidget(line_text_widget) + PythonSyntaxHighlighter(line_text_widget.get_text_edit().document()) From 6ad9b9d2bb72017e530f0fbf5dad552c756e8e05 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 20:40:07 -0700 Subject: [PATCH 15/24] Created unittests --- tests/test_ui/test_maya_menu.py | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 tests/test_ui/test_maya_menu.py diff --git a/tests/test_ui/test_maya_menu.py b/tests/test_ui/test_maya_menu.py new file mode 100644 index 00000000..0f765a7b --- /dev/null +++ b/tests/test_ui/test_maya_menu.py @@ -0,0 +1,89 @@ +from PySide2.QtWidgets import QApplication +import unittest +import logging +import sys +import os + +# Logging Setup +logging.basicConfig() +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + +# Import Tested Script +test_utils_dir = os.path.dirname(__file__) +tests_dir = os.path.dirname(test_utils_dir) +package_root_dir = os.path.dirname(tests_dir) +for to_append in [package_root_dir, tests_dir]: + if to_append not in sys.path: + sys.path.append(to_append) +from gt.ui.maya_menu import MayaMenu, MenuItem +from tests import maya_test_tools + + +class TestMayaMenu(unittest.TestCase): + @classmethod + def setUpClass(cls): + app = QApplication.instance() + if not app: + cls.app = QApplication(sys.argv) + + def setUp(self): + # Create a MayaMenu object for testing + self.menu = MayaMenu(name="TestMenu", parent=None) + maya_test_tools.import_maya_standalone(initialize=True) + + def tearDown(self): + # Delete the menu after each test + self.menu.delete_menu() + + def test_create_menu(self): + # Test if the menu is created successfully + self.menu.create_menu() + self.assertTrue(self.menu.initialized) + + def test_add_menu_item(self): + # Add a menu item and check if it exists in the menu items list + label = "TestMenuItem" + self.menu.add_menu_item(label) + self.assertTrue(any(item.label == label for item in self.menu.menu_items)) + + def test_add_sub_menu(self): + # Add a sub-menu and check if it exists in the sub_menus list + label = "TestSubMenu" + self.menu.add_sub_menu(label) + self.assertTrue(label in self.menu.sub_menus) + + def test_add_divider(self): + # Add a divider and check if it exists in the menu items list + label = "TestDivider" + self.menu.add_divider(label) + self.assertTrue(any(item.label == label for item in self.menu.menu_items)) + + def test_get_item_parameters(self): + # Test the get_item_parameters method + item = MenuItem(label="label", + command='command', + tooltip='tooltip', + icon='icon', + enable=True, + parent="parent", + divider=True, + divider_label="divider_label", + sub_menu=False, + tear_off=False, + enable_command_repeat=False, + option_box=False, + option_box_icon='') + params = self.menu.get_item_parameters(item) + self.assertEqual(params["label"], "label") + self.assertEqual(params["command"], "command") + self.assertEqual(params["annotation"], "tooltip") + self.assertEqual(params["image"], "icon") + self.assertEqual(params["enable"], True) + self.assertEqual(params["parent"], "parent") + self.assertEqual(params["divider"], True) + self.assertEqual(params["dividerLabel"], "divider_label") + self.assertEqual(params["subMenu"], False) + self.assertEqual(params.get("tearOff"), None) + self.assertEqual(params["enableCommandRepeat"], False) + self.assertEqual(params.get("optionBox"), None) From fae097928cbc60a06306382f861b6ed01d5668d5 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 20:45:45 -0700 Subject: [PATCH 16/24] Created unittests --- tests/__init__.py | 1 + tests/test_ui/__init__.py | 1 + tests/test_ui/test_python_output_view.py | 54 ++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/test_ui/test_python_output_view.py diff --git a/tests/__init__.py b/tests/__init__.py index 1366d0ca..0f0ebb1a 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -33,6 +33,7 @@ test_ui.test_line_text_widget, test_ui.test_maya_menu, test_ui.test_progress_bar, + test_ui.test_python_output_view, test_ui.test_resource_library, # Tools test_curve_library.test_curve_library_model, diff --git a/tests/test_ui/__init__.py b/tests/test_ui/__init__.py index 078bb0a6..8ae56d91 100644 --- a/tests/test_ui/__init__.py +++ b/tests/test_ui/__init__.py @@ -2,4 +2,5 @@ from . import test_line_text_widget from . import test_maya_menu from . import test_progress_bar +from . import test_python_output_view from . import test_resource_library diff --git a/tests/test_ui/test_python_output_view.py b/tests/test_ui/test_python_output_view.py new file mode 100644 index 00000000..3921925d --- /dev/null +++ b/tests/test_ui/test_python_output_view.py @@ -0,0 +1,54 @@ +from PySide2.QtWidgets import QApplication +from unittest.mock import MagicMock +import unittest +import logging +import sys +import os + +# Logging Setup +logging.basicConfig() +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + +# Import Tested Script +test_utils_dir = os.path.dirname(__file__) +tests_dir = os.path.dirname(test_utils_dir) +package_root_dir = os.path.dirname(tests_dir) +for to_append in [package_root_dir, tests_dir]: + if to_append not in sys.path: + sys.path.append(to_append) +from gt.ui.python_output_view import PythonOutputView + + +class TestPythonOutputView(unittest.TestCase): + @classmethod + def setUpClass(cls): + app = QApplication.instance() + if not app: + cls.app = QApplication(sys.argv) + + def setUp(self): + # Create an instance of PythonOutputView + self.python_output_view = PythonOutputView() + + def test_clear_python_output(self): + # Test clearing Python output + self.python_output_view.output_python_box.get_text_edit().setPlainText("Sample text") + self.python_output_view.clear_python_output() + result = self.python_output_view.get_python_output_text() + expected = "" + self.assertEqual(result, expected) + + def test_set_python_output_text(self): + # Test setting Python output text + self.python_output_view.set_python_output_text("Sample text") + result = self.python_output_view.get_python_output_text() + expected = "Sample text" + self.assertEqual(result, expected) + + def test_get_python_output_text(self): + # Test getting Python output text + self.python_output_view.output_python_box.get_text_edit().setPlainText("Sample text") + result = self.python_output_view.get_python_output_text() + expected = "Sample text" + self.assertEqual(result, expected) From 0ee7ef7cde1e22a1e083dbe26f7d4a7f489ea19e Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 20:45:56 -0700 Subject: [PATCH 17/24] Fixed test class name --- tests/test_ui/test_progress_bar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_ui/test_progress_bar.py b/tests/test_ui/test_progress_bar.py index da3f43a3..cb1e4776 100644 --- a/tests/test_ui/test_progress_bar.py +++ b/tests/test_ui/test_progress_bar.py @@ -19,7 +19,7 @@ from gt.ui.progress_bar import ProgressBarWindow -class TestInputWindowText(unittest.TestCase): +class TestProgressBar(unittest.TestCase): @classmethod def setUpClass(cls): app = QApplication.instance() From ff07e6dcbebf6d0eb97bedec0bcc38e66b15026f Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 22:57:08 -0700 Subject: [PATCH 18/24] Created initial qt_utils unittests --- tests/__init__.py | 1 + tests/test_ui/__init__.py | 1 + tests/test_ui/test_qt_utils.py | 115 +++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 tests/test_ui/test_qt_utils.py diff --git a/tests/__init__.py b/tests/__init__.py index 0f0ebb1a..c0471b65 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -34,6 +34,7 @@ test_ui.test_maya_menu, test_ui.test_progress_bar, test_ui.test_python_output_view, + test_ui.test_qt_utils, test_ui.test_resource_library, # Tools test_curve_library.test_curve_library_model, diff --git a/tests/test_ui/__init__.py b/tests/test_ui/__init__.py index 8ae56d91..f8e93355 100644 --- a/tests/test_ui/__init__.py +++ b/tests/test_ui/__init__.py @@ -3,4 +3,5 @@ from . import test_maya_menu from . import test_progress_bar from . import test_python_output_view +from . import test_qt_utils from . import test_resource_library diff --git a/tests/test_ui/test_qt_utils.py b/tests/test_ui/test_qt_utils.py new file mode 100644 index 00000000..2c29f3af --- /dev/null +++ b/tests/test_ui/test_qt_utils.py @@ -0,0 +1,115 @@ +from PySide2.QtCore import QPoint +from PySide2.QtWidgets import QApplication, QDialog +from unittest.mock import patch, MagicMock, Mock +from PySide2 import QtGui, QtCore +import unittest +import logging +import sys +import os + +# Logging Setup +logging.basicConfig() +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + +# Import Tested Script +test_utils_dir = os.path.dirname(__file__) +tests_dir = os.path.dirname(test_utils_dir) +package_root_dir = os.path.dirname(tests_dir) +for to_append in [package_root_dir, tests_dir]: + if to_append not in sys.path: + sys.path.append(to_append) +from gt.ui.qt_utils import MayaWindowMeta +from gt.ui import qt_utils + + +class TestQtUtilities(unittest.TestCase): + @classmethod + def setUpClass(cls): + app = QApplication.instance() + if not app: + cls.app = QApplication(sys.argv) + + @patch('gt.ui.qt_utils.is_script_in_interactive_maya', MagicMock(return_value=True)) + def test_base_inheritance_default(self): + """ + Test that MayaWindowMeta sets 'base_inheritance' to QDialog by default. + """ + new_class = MayaWindowMeta('TestBaseInheritanceDefault', (object,), {}) + from maya.app.general.mayaMixin import MayaQWidgetDockableMixin + self.assertEqual(new_class.__bases__, (MayaQWidgetDockableMixin, QDialog)) + + @patch('gt.ui.qt_utils.is_script_in_interactive_maya', MagicMock(return_value=True)) + @patch('gt.ui.qt_utils.is_system_macos', MagicMock(return_value=False)) + def test_base_inheritance_non_macos(self): + new_class = MayaWindowMeta(name='TestBaseInheritanceNonMacOS', bases=(object,), attrs={}) + from maya.app.general.mayaMixin import MayaQWidgetDockableMixin + self.assertEqual(new_class.__bases__, (MayaQWidgetDockableMixin, QDialog)) + + @patch('gt.ui.qt_utils.is_script_in_interactive_maya', MagicMock(return_value=True)) + def test_base_inheritance_widget(self): + from PySide2.QtWidgets import QWidget + new_class = MayaWindowMeta(name='TestBaseInheritance', bases=(object,), attrs={}, base_inheritance=(QWidget,)) + from maya.app.general.mayaMixin import MayaQWidgetDockableMixin + self.assertEqual(new_class.__bases__, (MayaQWidgetDockableMixin, QWidget)) + + @patch('gt.utils.system_utils.import_from_path') + @patch('gt.ui.qt_utils.get_maya_main_window') + def test_with_valid_class_type(self, mock_get_maya_main_window, mock_import_from_path): + mock_maya_window = MagicMock() + mock_maya_window.findChildren.return_value = ["child_one", "child_two"] + mock_import_from_path.return_value = Mock() + mock_get_maya_main_window.return_value = mock_maya_window + + # Call the function + result = qt_utils.get_maya_main_window_qt_elements(Mock()) + + # Expected result + expected = ["child_one", "child_two"] + + # Assert the result + self.assertEqual(result, expected) + + def test_close_ui_elements_success(self): + # Create mock UI elements + ui_element1 = Mock() + ui_element2 = Mock() + + # Call the function with the mock elements + obj_list = [ui_element1, ui_element2] + qt_utils.close_ui_elements(obj_list) + + # Assert that close() and deleteLater() methods were called for each UI element + ui_element1.close.assert_called_once() + ui_element1.deleteLater.assert_called_once() + ui_element2.close.assert_called_once() + ui_element2.deleteLater.assert_called_once() + + @patch.object(QtGui.QCursor, 'pos', return_value=QtCore.QPoint(100, 200)) + def test_get_cursor_position_no_offset(self, mock_cursor): + expected = QtCore.QPoint(100, 200) + result = qt_utils.get_cursor_position() + self.assertEqual(expected, result) + + @patch.object(QtGui.QCursor, 'pos', return_value=QtCore.QPoint(100, 200)) + def test_get_cursor_position_with_offset(self, mock_cursor): + offset_x = 10 + offset_y = 20 + expected = QtCore.QPoint(110, 220) + result = qt_utils.get_cursor_position(offset_x, offset_y) + self.assertEqual(expected, result) + + @patch('gt.ui.qt_utils.get_main_window_screen_number', return_value=0) + @patch.object(QApplication, 'screens') + def test_get_screen_center(self, mock_screens, mock_get_main_window_screen_number): + expected = QPoint(100, 200) + mocked_xy = MagicMock() + mocked_xy.x.return_value = 100 + mocked_xy.y.return_value = 200 + mocked_center = MagicMock() + mocked_center.center.return_value = mocked_xy + mocked_geometry = MagicMock() + mocked_geometry.geometry.return_value = mocked_center + mock_screens.return_value = [mocked_geometry] + result = qt_utils.get_screen_center() + self.assertEqual(expected, result) From 5c8b3b948042b972a2a9a86ab43f6dd3917af556 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Wed, 6 Sep 2023 22:57:22 -0700 Subject: [PATCH 19/24] Removed show function from test --- tests/test_ui/test_progress_bar.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_ui/test_progress_bar.py b/tests/test_ui/test_progress_bar.py index cb1e4776..baa19981 100644 --- a/tests/test_ui/test_progress_bar.py +++ b/tests/test_ui/test_progress_bar.py @@ -31,7 +31,6 @@ def setUp(self): def test_set_progress_bar_value(self): window = ProgressBarWindow() - window.show() # Test setting the progress bar value window.set_progress_bar_value(50) From ff3af87ba968f31142421fb7460f692aa6c90bd7 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Thu, 7 Sep 2023 13:16:27 -0700 Subject: [PATCH 20/24] Created more unittests --- tests/test_ui/test_qt_utils.py | 119 ++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 1 deletion(-) diff --git a/tests/test_ui/test_qt_utils.py b/tests/test_ui/test_qt_utils.py index 2c29f3af..0ba98276 100644 --- a/tests/test_ui/test_qt_utils.py +++ b/tests/test_ui/test_qt_utils.py @@ -1,5 +1,6 @@ from PySide2.QtCore import QPoint -from PySide2.QtWidgets import QApplication, QDialog +from PySide2.QtGui import QFont, QColor +from PySide2.QtWidgets import QApplication, QDialog, QWidget from unittest.mock import patch, MagicMock, Mock from PySide2 import QtGui, QtCore import unittest @@ -113,3 +114,119 @@ def test_get_screen_center(self, mock_screens, mock_get_main_window_screen_numbe mock_screens.return_value = [mocked_geometry] result = qt_utils.get_screen_center() self.assertEqual(expected, result) + + @patch('gt.ui.qt_utils.QtGui.QFont', return_value="mocked_font") + @patch('gt.ui.qt_utils.QApplication.instance', return_value=MagicMock()) + @patch('gt.ui.qt_utils.QtGui.QFontDatabase.addApplicationFontFromData', return_value=0) + @patch('gt.ui.qt_utils.QtGui.QFontDatabase.applicationFontFamilies', return_value=['CustomFont']) + def test_load_custom_font_success(self, mock_font_from_data, mock_app_font_families, mock_app, mock_font): + custom_font = qt_utils.load_custom_font('custom_font.ttf', + point_size=12, weight=QFont.Bold, italic=True) + expected_font = "mocked_font" + self.assertEqual(expected_font, custom_font) + + def test_font_available(self): + # Test if a font that should be available returns True + font_name = "Arial" + expected_result = True + result = qt_utils.is_font_available(font_name) + self.assertEqual(result, expected_result) + + def test_font_not_available(self): + # Test if a font that should not be available returns False + font_name = "NonExistentFont123" + expected_result = False + result = qt_utils.is_font_available(font_name) + self.assertEqual(result, expected_result) + + @patch('gt.ui.qt_utils.is_font_available', return_value=True) + @patch('gt.ui.qt_utils.QApplication.instance') + def test_get_font_with_font_name(self, mock_instance, mock_is_font_available): + mock_instance.return_value = MagicMock() + + font_name = 'Arial' + font = qt_utils.get_font(font_name) + + expected_font = QtGui.QFont(font_name) + + self.assertEqual(font, expected_font) + + @patch('gt.ui.qt_utils.is_font_available', return_value=False) + @patch('gt.ui.qt_utils.load_custom_font', return_value=QtGui.QFont('CustomFont')) + @patch('gt.ui.qt_utils.QApplication.instance') + def test_get_font_with_font_path(self, mock_instance, mock_load_custom_font, mock_is_font_available): + mock_instance.return_value = MagicMock() + from gt.ui import resource_library + result = qt_utils.get_font(resource_library.Font.roboto) + expected_font = QtGui.QFont('CustomFont') + self.assertEqual(expected_font, result) + + @patch('gt.ui.qt_utils.QApplication.instance') + def test_get_font_invalid_font(self, mock_instance): + mock_instance.return_value = MagicMock() + + invalid_font = 123 # Invalid input type + font = qt_utils.get_font(invalid_font) + + expected_font = QtGui.QFont() # Default font + + self.assertEqual(font, expected_font) + + def test_get_qt_color_valid_hex_color(self): + # Test with a valid hex color + expected = QColor("#FF0000") + result = qt_utils.get_qt_color("#FF0000") + self.assertEqual(expected, result) + + def test_get_qt_color_valid_color_name(self): + # Test with a valid color name + expected = QColor("red") + result = qt_utils.get_qt_color("red") + self.assertEqual(expected, result) + + def test_get_qt_color_invalid_color_input(self): + # Test with an invalid color input + expected = None + result = qt_utils.get_qt_color("invalid_color") + self.assertEqual(expected, result) + + def test_get_qt_color_color_object_input(self): + # Test with a QColor object as input + input_color = QColor("#00FF00") + expected = input_color + result = qt_utils.get_qt_color(input_color) + self.assertEqual(expected, result) + + def test_get_qt_color_none_input(self): + # Test with None as input + expected = None + result = qt_utils.get_qt_color(None) + self.assertEqual(expected, result) + + def test_get_qt_color_library(self): + # Test with None as input + from gt.ui import resource_library + expected = QColor(resource_library.Color.RGB.red) + result = qt_utils.get_qt_color(resource_library.Color.RGB.red) + self.assertEqual(expected, result) + + @patch('gt.ui.qt_utils.QDesktopWidget') + def test_resize_to_screen_valid_percentage(self, mock_desktop_widget): + mock_screen = MagicMock() + mock_screen.width.return_value = 100 + mock_screen.height.return_value = 200 + mock_geo = MagicMock() + mock_geo.availableGeometry.return_value = mock_screen + mock_desktop_widget.return_value = mock_geo + window = MagicMock() + qt_utils.resize_to_screen(window, percentage=50) + expected_width = 50 + expected_height = 100 + self.assertEqual(window.setGeometry.call_args[0][2], expected_width) + self.assertEqual(window.setGeometry.call_args[0][3], expected_height) + + def test_resize_to_screen_invalid_percentage(self): + window = Mock() + with self.assertRaises(ValueError): + qt_utils.resize_to_screen(window, percentage=110) + \ No newline at end of file From 7679cb19c6afdc38484aa60b9f2edfd032b8c97a Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Thu, 7 Sep 2023 14:18:35 -0700 Subject: [PATCH 21/24] Created a few more unittests --- tests/test_ui/test_qt_utils.py | 54 ++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/tests/test_ui/test_qt_utils.py b/tests/test_ui/test_qt_utils.py index 0ba98276..7b59f754 100644 --- a/tests/test_ui/test_qt_utils.py +++ b/tests/test_ui/test_qt_utils.py @@ -1,6 +1,6 @@ from PySide2.QtCore import QPoint from PySide2.QtGui import QFont, QColor -from PySide2.QtWidgets import QApplication, QDialog, QWidget +from PySide2.QtWidgets import QApplication, QDialog, QWidget, QLabel from unittest.mock import patch, MagicMock, Mock from PySide2 import QtGui, QtCore import unittest @@ -229,4 +229,54 @@ def test_resize_to_screen_invalid_percentage(self): window = Mock() with self.assertRaises(ValueError): qt_utils.resize_to_screen(window, percentage=110) - \ No newline at end of file + + @patch('gt.ui.qt_utils.QApplication') + def test_get_main_window_screen_number(self, mock_instance): + mock_screen_number = MagicMock() + mock_screen_number.screenNumber.return_value = 10 + mock_instance.instance.return_value = MagicMock() + mock_instance.desktop.return_value = mock_screen_number + result = qt_utils.get_main_window_screen_number() + expected = 10 + self.assertEqual(expected, result) + + @patch('gt.ui.qt_utils.QDesktopWidget') + def test_get_window_screen_number(self, mock_desktop): + mock_screen_number = MagicMock() + mock_screen_number.screenNumber.return_value = 10 + mock_desktop.return_value = mock_screen_number + result = qt_utils.get_window_screen_number(MagicMock()) + expected = 10 + self.assertEqual(expected, result) + + def test_center_window(self): + mock_window = MagicMock() + qt_utils.center_window(mock_window) + mock_window.move.assert_called() + + def test_update_formatted_label_default_format(self): + mock_label = QLabel() + expected_html = "
Text
" + qt_utils.update_formatted_label(mock_label, "Text") + result_html = mock_label.text() + self.assertEqual(expected_html, result_html) + + def test_update_formatted_label_custom_format(self): + mock_label = QLabel() + expected_html = ("
TextOutput
") + qt_utils.update_formatted_label( + mock_label, + "Text", + text_size=16, + text_color="blue", + text_bg_color="yellow", + text_is_bold=True, + output_text="Output", + output_size=14, + output_color="red", + text_output_is_bold=True, + overall_alignment="left" + ) + result_html = mock_label.text() + self.assertEqual(expected_html, result_html) \ No newline at end of file From 0e60571feacf149bb380b9428425301873a5f1b0 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Thu, 7 Sep 2023 14:27:50 -0700 Subject: [PATCH 22/24] Fixed exact width issue with "load_and_scale_pixmap" --- gt/ui/qt_utils.py | 6 ++-- tests/test_ui/test_qt_utils.py | 56 +++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/gt/ui/qt_utils.py b/gt/ui/qt_utils.py index 4b7ae46b..63f5d69c 100644 --- a/gt/ui/qt_utils.py +++ b/gt/ui/qt_utils.py @@ -449,14 +449,14 @@ def update_formatted_label(target_label, target_label.setText(_html) -def load_and_scale_pixmap(image_path, scale_percentage, exact_height=None, exact_width=None): +def load_and_scale_pixmap(image_path, scale_percentage=100, exact_height=None, exact_width=None): """ Load an image from the given path, and scale it by the specified percentage, then return the scaled QPixmap. Args: image_path (str): Path to the image file. - scale_percentage (float): Percentage to scale the image by. + scale_percentage (float): Percentage to scale the image by. (Default is 100%, which is the original resolution) 100 = Same resolution. 50 = half the resolution. 200 = double the resolution. exact_height (int, optional): If provided, it will overwrite scale percentage and use this height instead. exact_width (int, optional): If provided, it will overwrite scale percentage and use this width instead. @@ -474,7 +474,7 @@ def load_and_scale_pixmap(image_path, scale_percentage, exact_height=None, exact if exact_height and isinstance(exact_height, int): scaled_height = exact_height if exact_width and isinstance(exact_width, int): - scaled_height = exact_width + scaled_width = exact_width scaled_pixmap = pixmap.scaled(scaled_width, scaled_height, mode=QtCore.Qt.SmoothTransformation) return scaled_pixmap diff --git a/tests/test_ui/test_qt_utils.py b/tests/test_ui/test_qt_utils.py index 7b59f754..e2726a78 100644 --- a/tests/test_ui/test_qt_utils.py +++ b/tests/test_ui/test_qt_utils.py @@ -279,4 +279,58 @@ def test_update_formatted_label_custom_format(self): overall_alignment="left" ) result_html = mock_label.text() - self.assertEqual(expected_html, result_html) \ No newline at end of file + self.assertEqual(expected_html, result_html) + + def test_load_and_scale_pixmap_scale_by_percentage(self): + # Test scaling by percentage + from gt.ui import resource_library + input_path = resource_library.Icon.dev_code + + scale_percentage = 50 + scaled_pixmap = qt_utils.load_and_scale_pixmap(image_path=input_path, + scale_percentage=scale_percentage) + + expected_width = 256 # 50% of the original width + expected_height = 256 # 50% of the original height + + self.assertEqual(scaled_pixmap.width(), expected_width) + self.assertEqual(scaled_pixmap.height(), expected_height) + + def test_load_and_scale_pixmap_scale_by_exact_height(self): + # Test scaling by exact height + from gt.ui import resource_library + input_path = resource_library.Icon.dev_code + exact_height = 200 + scaled_pixmap = qt_utils.load_and_scale_pixmap(image_path=input_path, scale_percentage=100, + exact_height=exact_height) + + expected_height = 200 # Exact height specified + + self.assertEqual(scaled_pixmap.height(), expected_height) + + def test_load_and_scale_pixmap_scale_by_exact_width(self): + # Test scaling by exact width + from gt.ui import resource_library + input_path = resource_library.Icon.dev_code + exact_width = 300 + scaled_pixmap = qt_utils.load_and_scale_pixmap(image_path=input_path, scale_percentage=100, + exact_width=exact_width) + + expected_width = 300 # Exact width specified + + self.assertEqual(scaled_pixmap.width(), expected_width) + + def test_load_and_scale_pixmap_scale_with_both_exact_dimensions(self): + # Test scaling with both exact dimensions specified + from gt.ui import resource_library + input_path = resource_library.Icon.dev_code + exact_width = 300 + exact_height = 200 + scaled_pixmap = qt_utils.load_and_scale_pixmap(image_path=input_path, scale_percentage=100, + exact_height=exact_height, exact_width=exact_width) + + expected_width = 300 # Exact width specified + expected_height = 200 # Exact height specified + + self.assertEqual(scaled_pixmap.width(), expected_width) + self.assertEqual(scaled_pixmap.height(), expected_height) From 66b5ea861e3cb433cee2a7e72c462583d064a236 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Thu, 7 Sep 2023 17:08:17 -0700 Subject: [PATCH 23/24] Created more unittests --- tests/test_ui/test_qt_utils.py | 62 +++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/tests/test_ui/test_qt_utils.py b/tests/test_ui/test_qt_utils.py index e2726a78..2e4bddde 100644 --- a/tests/test_ui/test_qt_utils.py +++ b/tests/test_ui/test_qt_utils.py @@ -1,5 +1,5 @@ from PySide2.QtCore import QPoint -from PySide2.QtGui import QFont, QColor +from PySide2.QtGui import QFont, QColor, QPixmap, QIcon from PySide2.QtWidgets import QApplication, QDialog, QWidget, QLabel from unittest.mock import patch, MagicMock, Mock from PySide2 import QtGui, QtCore @@ -334,3 +334,63 @@ def test_load_and_scale_pixmap_scale_with_both_exact_dimensions(self): self.assertEqual(scaled_pixmap.width(), expected_width) self.assertEqual(scaled_pixmap.height(), expected_height) + + def test_create_color_pixmap_valid_color(self): + expected_width_height = 24 + result = qt_utils.create_color_pixmap(color=QColor(255, 0, 0), + width=expected_width_height, + height=expected_width_height) + self.assertEqual(QPixmap, type(result)) + self.assertEqual(expected_width_height, result.height()) + self.assertEqual(expected_width_height, result.width()) + + def test_create_color_pixmap_invalid_color(self): + # Test with an invalid color (not a QColor) + result = qt_utils.create_color_pixmap("invalid_color") + self.assertIsNone(result) + + def test_create_color_icon_valid_color(self): + result = qt_utils.create_color_icon(color=QColor(255, 0, 0)) + self.assertEqual(QIcon, type(result)) + + def test_create_color_icon_invalid_color(self): + # Test with an invalid color (not a QColor) + result = qt_utils.create_color_icon("invalid_color") + self.assertIsNone(result) + + @patch('gt.ui.qt_utils.QApplication') + def test_get_screen_dpi_scale_valid_screen_number(self, mock_qapp): + # Create a mock QApplication instance with mock screens + app = MagicMock() + screen1 = MagicMock() + screen2 = MagicMock() + screen1.logicalDotsPerInch.return_value = 120.0 + screen2.logicalDotsPerInch.return_value = 96.0 + app.screens.return_value = [screen1, screen2] + + # Replace the QApplication instance with the mock + mock_qapp.instance.return_value = app + + expected_result = 1 + result = qt_utils.get_screen_dpi_scale(screen_number=1) + self.assertEqual(expected_result, result) + expected_result = 1.25 + result = qt_utils.get_screen_dpi_scale(screen_number=0) + self.assertEqual(expected_result, result) + + @patch('gt.ui.qt_utils.QApplication') + def test_get_screen_dpi_scale_negative_screen_number(self, mock_app): + # Create a mock QApplication instance with mock screens + app = MagicMock() + screen1 = MagicMock() + screen2 = MagicMock() + screen1.logicalDotsPerInch.return_value = 120.0 + screen2.logicalDotsPerInch.return_value = 96.0 + app.screens.return_value = [screen1, screen2] + + # Replace the QApplication instance with the mock + mock_app.instance.return_value = app + + # Test with a negative screen number (screen_number = -1) + with self.assertRaises(ValueError): + qt_utils.get_screen_dpi_scale(-1) From ffa4661356e6fcc99b9cae5b1a41d23b2a345328 Mon Sep 17 00:00:00 2001 From: Guilherme Trevisan Date: Thu, 7 Sep 2023 17:08:33 -0700 Subject: [PATCH 24/24] Added instance check to Qt context --- gt/ui/qt_utils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gt/ui/qt_utils.py b/gt/ui/qt_utils.py index 63f5d69c..05ca7e8a 100644 --- a/gt/ui/qt_utils.py +++ b/gt/ui/qt_utils.py @@ -526,7 +526,11 @@ def __enter__(self): self.parent = get_maya_main_window() else: logger.debug('Running Qt outside Maya. Initializing QApplication.') - self.app = QtWidgets.QApplication(sys.argv) + _app_instance = QApplication.instance() + if not _app_instance: + self.app = QApplication(sys.argv) + else: + self.app = _app_instance return self def __exit__(self, exc_type, exc_value, traceback):