From d4390b067b6a8f6ed25cea866694d7f60f09fd77 Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Mon, 27 Mar 2023 19:58:07 +0200 Subject: [PATCH 01/10] feat: add a `Browse` button, not visible by default --- cuesubmit/cuesubmit/ui/Widgets.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cuesubmit/cuesubmit/ui/Widgets.py b/cuesubmit/cuesubmit/ui/Widgets.py index 1bcf9b951..c3724fc46 100644 --- a/cuesubmit/cuesubmit/ui/Widgets.py +++ b/cuesubmit/cuesubmit/ui/Widgets.py @@ -53,6 +53,7 @@ def __init__(self, labelText=None, defaultText='', tooltip=None, validators=None self.label.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) self.lineEdit = CueLineEdit(defaultText, completerStrings=completers) self.lineEdit.setToolTip(tooltip) + self.browseButton = QtWidgets.QPushButton(text='Browse') self.horizontalLine = CueHLine() self.validators = validators or [] self.setupUi() @@ -64,6 +65,7 @@ def setupUi(self): self.setLayout(self.mainLayout) self.mainLayout.addWidget(self.label, 0, 0, 1, 1) self.mainLayout.addWidget(self.lineEdit, 1, 0, 1, 4) + self.browseButton.setVisible(False) self.mainLayout.addWidget(self.horizontalLine, 2, 0, 1, 4) self.label.setStyleSheet(Style.LABEL_TEXT) From 1094b1961d79de4fa8fd4cf9afb2749aaebb094b Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Mon, 27 Mar 2023 20:00:12 +0200 Subject: [PATCH 02/10] feat: add 2 functions `getFolder` and `getFile` (with optional file filter) --- cuesubmit/cuesubmit/ui/Widgets.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cuesubmit/cuesubmit/ui/Widgets.py b/cuesubmit/cuesubmit/ui/Widgets.py index c3724fc46..967b37f74 100644 --- a/cuesubmit/cuesubmit/ui/Widgets.py +++ b/cuesubmit/cuesubmit/ui/Widgets.py @@ -450,6 +450,23 @@ def separatorLine(): line.setStyleSheet(Style.SEPARATOR_LINE) return line +def getFile(fileFilter=None): + """ Opens a file browser and returns the result + :param fileFilter: optional filters (ex: "Maya Ascii File (*.ma);;Maya Binary File (*.mb);;Maya Files (*.ma *.mb)") + :type fileFilter: str + :returns: Name of the file + :rtype: str + """ + filename, _ = QtWidgets.QFileDialog.getOpenFileName(caption='Select file', dir='.', filter=fileFilter) + return filename + +def getFolder(): + """ Opens a folder browser and returns the result + :returns: Name of the folder + :rtype: str + """ + folder = QtWidgets.QFileDialog.getExistingDirectory(caption='Select folder', dir='.', filter='') + return folder class CueMessageBox(QtWidgets.QMessageBox): """A QMessageBox with message and OK button.""" From 2c78cb04b682e72925aade17268ad2113645206e Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Mon, 27 Mar 2023 20:02:05 +0200 Subject: [PATCH 03/10] feat: add wrappers to `getFile` and `getFolder` to set the returned result on the calling widget --- cuesubmit/cuesubmit/ui/Widgets.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cuesubmit/cuesubmit/ui/Widgets.py b/cuesubmit/cuesubmit/ui/Widgets.py index 967b37f74..cb8672bed 100644 --- a/cuesubmit/cuesubmit/ui/Widgets.py +++ b/cuesubmit/cuesubmit/ui/Widgets.py @@ -468,6 +468,24 @@ def getFolder(): folder = QtWidgets.QFileDialog.getExistingDirectory(caption='Select folder', dir='.', filter='') return folder +def _setBrowseFileText(widget_setter, fileFilter, *args, **kwargs): + """ wrapper function to open a fileBrowser and set its result back in the widget + :param widget_setter: widget's function to set its text + :type widget_setter: function + :param fileFilter: optional filters (ex: "Maya Ascii File (*.ma);;Maya Binary File (*.mb);;Maya Files (*.ma *.mb)") + :type fileFilter: str + """ + result = getFile(fileFilter) + widget_setter(result) + +def _setBrowseFolderText(widget_setter, *args, **kwargs): + """ wrapper function to open a folderBrowser and set its result back in the widget + :param widget_setter: widget's function to set its text + :type widget_setter: function + """ + result = getFolder() + widget_setter(result) + class CueMessageBox(QtWidgets.QMessageBox): """A QMessageBox with message and OK button.""" From 9b93f726553cbda6a2a4a1419bf30a2a67d23683 Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Mon, 27 Mar 2023 20:09:25 +0200 Subject: [PATCH 04/10] feat: add functions to display the browse button and attach wrappers that feeds the lineEdit widget with browse result. --- cuesubmit/cuesubmit/ui/Widgets.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/cuesubmit/cuesubmit/ui/Widgets.py b/cuesubmit/cuesubmit/ui/Widgets.py index cb8672bed..8f0b10fb6 100644 --- a/cuesubmit/cuesubmit/ui/Widgets.py +++ b/cuesubmit/cuesubmit/ui/Widgets.py @@ -21,6 +21,7 @@ from __future__ import absolute_import from builtins import object +from functools import partial from PySide2 import QtCore, QtGui, QtWidgets from cuesubmit import Constants @@ -76,6 +77,32 @@ def setupConnections(self): self.lineEdit.focusChange.connect(self.textFocusChange) # pylint: enable=no-member + def setFileBrowsable(self, fileFilter=None): + """ Displays the Browse button and hook it to a fileBrowser with optional file filters + + :param fileFilter: single or multiple file filters (ex: 'Maya Ascii File (*.ma)') + :type fileFilter: str or list + """ + self._showBrowseButton() + if isinstance(fileFilter, (list, tuple)): + fileFilter = ';;'.join(fileFilter) + self.browseButton.clicked.connect(partial(_setBrowseFileText, + widget_setter=self.setter, + fileFilter=fileFilter)) + + def setFolderBrowsable(self): + """ Displays the Browse button and hook it to a folderBrowser """ + self._showBrowseButton() + self.browseButton.clicked.connect(partial(_setBrowseFolderText, + widget_setter=self.setter)) + + def _showBrowseButton(self): + """ Re-layout lineEdit and browse button and display it """ + self.mainLayout.removeWidget(self.lineEdit) + self.mainLayout.addWidget(self.lineEdit, 1, 0, 1, 3) + self.mainLayout.addWidget(self.browseButton, 1, 3, 1, 1) + self.browseButton.setVisible(True) + def setText(self, text): """Set the text to the given value. @type text: str From ac4ef690f65c03470d1166fda22a07d1124f0add Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Mon, 27 Mar 2023 20:44:56 +0200 Subject: [PATCH 05/10] feat: Make `BaseMayaSettings` and `InMayaSettings` browsable with file filter --- cuesubmit/cuesubmit/ui/SettingsWidgets.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cuesubmit/cuesubmit/ui/SettingsWidgets.py b/cuesubmit/cuesubmit/ui/SettingsWidgets.py index 01601265a..b1d06c388 100644 --- a/cuesubmit/cuesubmit/ui/SettingsWidgets.py +++ b/cuesubmit/cuesubmit/ui/SettingsWidgets.py @@ -54,16 +54,24 @@ class InMayaSettings(BaseSettingsWidget): def __init__(self, cameras=None, filename=None, parent=None, *args, **kwargs): super(InMayaSettings, self).__init__(parent=parent) self.mayaFileInput = Widgets.CueLabelLineEdit('Maya File:', filename) + self.fileFilters = ['Maya Ascii file (*.ma)', + 'Maya Binary file (*.mb)', + 'Maya file (*.ma *.mb)'] self.cameraSelector = Widgets.CueSelectPulldown('Render Cameras', options=cameras) self.selectorLayout = QtWidgets.QHBoxLayout() self.setupUi() + self.setupConnections() def setupUi(self): """Creates the Maya-specific widget layout.""" self.mainLayout.addWidget(self.mayaFileInput) self.selectorLayout.addWidget(self.cameraSelector) self.selectorLayout.addSpacerItem(Widgets.CueSpacerItem(Widgets.SpacerTypes.HORIZONTAL)) - self.mainLayout.addLayout(self.selectorLayout) + + def setupConnections(self): + """Sets up widget signals.""" + self.mayaFileInput.lineEdit.textChanged.connect(self.dataChanged.emit) # pylint: disable=no-member + self.mayaFileInput.setFileBrowsable(fileFilter=self.fileFilters) def setCommandData(self, commandData): self.mayaFileInput.setText(commandData.get('mayaFile', '')) @@ -83,6 +91,9 @@ class BaseMayaSettings(BaseSettingsWidget): def __init__(self, parent=None, *args, **kwargs): super(BaseMayaSettings, self).__init__(parent=parent) self.mayaFileInput = Widgets.CueLabelLineEdit('Maya File:') + self.fileFilters = ['Maya Ascii file (*.ma)', + 'Maya Binary file (*.mb)', + 'Maya file (*.ma *.mb)'] self.setupUi() self.setupConnections() @@ -93,6 +104,7 @@ def setupUi(self): def setupConnections(self): """Sets up widget signals.""" self.mayaFileInput.lineEdit.textChanged.connect(self.dataChanged.emit) # pylint: disable=no-member + self.mayaFileInput.setFileBrowsable(fileFilter=self.fileFilters) def setCommandData(self, commandData): self.mayaFileInput.setText(commandData.get('mayaFile', '')) From ca2fa7de70bfd7ce682352c5481404ee0e4ef6b2 Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Mon, 27 Mar 2023 20:46:04 +0200 Subject: [PATCH 06/10] feat: Make `BaseNukeSettings` and `InNukeSettings` browsable with file filter --- cuesubmit/cuesubmit/ui/SettingsWidgets.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cuesubmit/cuesubmit/ui/SettingsWidgets.py b/cuesubmit/cuesubmit/ui/SettingsWidgets.py index b1d06c388..3167e5bb1 100644 --- a/cuesubmit/cuesubmit/ui/SettingsWidgets.py +++ b/cuesubmit/cuesubmit/ui/SettingsWidgets.py @@ -122,17 +122,23 @@ class InNukeSettings(BaseSettingsWidget): def __init__(self, writeNodes=None, filename=None, parent=None, *args, **kwargs): super(InNukeSettings, self).__init__(parent=parent) self.fileInput = Widgets.CueLabelLineEdit('Nuke File:', filename) + self.fileFilters = ['Nuke script file (*.nk)'] self.writeNodeSelector = Widgets.CueSelectPulldown('Write Nodes:', emptyText='[All]', options=writeNodes) self.selectorLayout = QtWidgets.QHBoxLayout() self.setupUi() + self.setupConnections() def setupUi(self): """Creates the Nuke-specific widget layout.""" self.mainLayout.addWidget(self.fileInput) self.selectorLayout.addWidget(self.writeNodeSelector) self.selectorLayout.addSpacerItem(Widgets.CueSpacerItem(Widgets.SpacerTypes.HORIZONTAL)) - self.mainLayout.addLayout(self.selectorLayout) + + def setupConnections(self): + """Sets up widget signals.""" + self.fileInput.lineEdit.textChanged.connect(self.dataChanged.emit) # pylint: disable=no-member + self.fileInput.setFileBrowsable(fileFilter=self.fileFilters) def setCommandData(self, commandData): self.fileInput.setText(commandData.get('nukeFile', '')) @@ -152,6 +158,7 @@ class BaseNukeSettings(BaseSettingsWidget): def __init__(self, parent=None, *args, **kwargs): super(BaseNukeSettings, self).__init__(parent=parent) self.fileInput = Widgets.CueLabelLineEdit('Nuke File:') + self.fileFilters = ['Nuke script file (*.nk)'] self.setupUi() self.setupConnections() @@ -162,6 +169,7 @@ def setupUi(self): def setupConnections(self): """Sets up widget signals.""" self.fileInput.lineEdit.textChanged.connect(self.dataChanged.emit) # pylint: disable=no-member + self.fileInput.setFileBrowsable(fileFilter=self.fileFilters) def setCommandData(self, commandData): self.fileInput.setText(commandData.get('nukeFile', '')) From 9ffd3a61de211f682035a924407043be95cca8fc Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Mon, 27 Mar 2023 20:47:11 +0200 Subject: [PATCH 07/10] feat: Make `BaseBlenderSettings` browsable with file filter --- cuesubmit/cuesubmit/ui/SettingsWidgets.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cuesubmit/cuesubmit/ui/SettingsWidgets.py b/cuesubmit/cuesubmit/ui/SettingsWidgets.py index 3167e5bb1..5b811b08f 100644 --- a/cuesubmit/cuesubmit/ui/SettingsWidgets.py +++ b/cuesubmit/cuesubmit/ui/SettingsWidgets.py @@ -213,6 +213,7 @@ class BaseBlenderSettings(BaseSettingsWidget): # pylint: disable=keyword-arg-before-vararg,unused-argument def __init__(self, parent=None, *args, **kwargs): super(BaseBlenderSettings, self).__init__(parent=parent) + self.fileFilters = ['Blender file (*.blend)'] self.fileInput = Widgets.CueLabelLineEdit('Blender File:') self.outputPath = Widgets.CueLabelLineEdit( 'Output Path (Optional):', @@ -237,6 +238,7 @@ def setupConnections(self): # pylint: disable=no-member self.fileInput.lineEdit.textChanged.connect(self.dataChanged.emit) self.outputPath.lineEdit.textChanged.connect(self.dataChanged.emit) + self.fileInput.setFileBrowsable(fileFilter=self.fileFilters) # pylint: enable=no-member def setCommandData(self, commandData): From 59093efe29ed929b75a3bbc551b48f8a2c0b435f Mon Sep 17 00:00:00 2001 From: Kern Attila Germain <5556461+KernAttila@users.noreply.github.com> Date: Fri, 31 Mar 2023 19:33:09 +0200 Subject: [PATCH 08/10] fix: revert 2 deleted lines --- cuesubmit/cuesubmit/ui/SettingsWidgets.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cuesubmit/cuesubmit/ui/SettingsWidgets.py b/cuesubmit/cuesubmit/ui/SettingsWidgets.py index 5b811b08f..ce4d3197f 100644 --- a/cuesubmit/cuesubmit/ui/SettingsWidgets.py +++ b/cuesubmit/cuesubmit/ui/SettingsWidgets.py @@ -67,6 +67,7 @@ def setupUi(self): self.mainLayout.addWidget(self.mayaFileInput) self.selectorLayout.addWidget(self.cameraSelector) self.selectorLayout.addSpacerItem(Widgets.CueSpacerItem(Widgets.SpacerTypes.HORIZONTAL)) + self.mainLayout.addLayout(self.selectorLayout) def setupConnections(self): """Sets up widget signals.""" @@ -134,6 +135,7 @@ def setupUi(self): self.mainLayout.addWidget(self.fileInput) self.selectorLayout.addWidget(self.writeNodeSelector) self.selectorLayout.addSpacerItem(Widgets.CueSpacerItem(Widgets.SpacerTypes.HORIZONTAL)) + self.mainLayout.addLayout(self.selectorLayout) def setupConnections(self): """Sets up widget signals.""" From 2c9757d72f88e78be4bd1bfba310bcbf7d3700c9 Mon Sep 17 00:00:00 2001 From: Kern Attila GERMAIN <5556461+KernAttila@users.noreply.github.com> Date: Tue, 25 Apr 2023 00:57:51 +0200 Subject: [PATCH 09/10] feat: add Constants `MAYA_FILE_FILTERS`, `NUKE_FILE_FILTERS`, `BLENDER_FILE_FILTERS` --- cuesubmit/cuesubmit/Constants.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cuesubmit/cuesubmit/Constants.py b/cuesubmit/cuesubmit/Constants.py index 123f32723..2ceae70fb 100644 --- a/cuesubmit/cuesubmit/Constants.py +++ b/cuesubmit/cuesubmit/Constants.py @@ -39,6 +39,15 @@ BLENDER_RENDER_CMD = config.get('BLENDER_RENDER_CMD', 'blender') FRAME_TOKEN = config.get('FRAME_TOKEN', '#IFRAME#') +MAYA_FILE_FILTERS = [ + 'Maya Ascii file (*.ma)', + 'Maya Binary file (*.mb)', + 'Maya file (*.ma *.mb)' +] +NUKE_FILE_FILTERS = ['Nuke script file (*.nk)'] +BLENDER_FILE_FILTERS = ['Blender file (*.blend)'] + + BLENDER_FORMATS = ['', 'AVIJPEG', 'AVIRAW', 'BMP', 'CINEON', 'DPX', 'EXR', 'HDR', 'IRIS', 'IRIZ', 'JP2', 'JPEG', 'MPEG', 'MULTILAYER', 'PNG', 'RAWTGA', 'TGA', 'TIFF'] BLENDER_OUTPUT_OPTIONS_URL = \ From c30b14685d73d0270485da13c08be6b80b5b81d8 Mon Sep 17 00:00:00 2001 From: Kern Attila GERMAIN <5556461+KernAttila@users.noreply.github.com> Date: Tue, 25 Apr 2023 00:58:12 +0200 Subject: [PATCH 10/10] fix: use Constants `MAYA_FILE_FILTERS`, `NUKE_FILE_FILTERS`, `BLENDER_FILE_FILTERS` --- cuesubmit/cuesubmit/ui/SettingsWidgets.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/cuesubmit/cuesubmit/ui/SettingsWidgets.py b/cuesubmit/cuesubmit/ui/SettingsWidgets.py index ce4d3197f..a0be3dd27 100644 --- a/cuesubmit/cuesubmit/ui/SettingsWidgets.py +++ b/cuesubmit/cuesubmit/ui/SettingsWidgets.py @@ -54,9 +54,7 @@ class InMayaSettings(BaseSettingsWidget): def __init__(self, cameras=None, filename=None, parent=None, *args, **kwargs): super(InMayaSettings, self).__init__(parent=parent) self.mayaFileInput = Widgets.CueLabelLineEdit('Maya File:', filename) - self.fileFilters = ['Maya Ascii file (*.ma)', - 'Maya Binary file (*.mb)', - 'Maya file (*.ma *.mb)'] + self.fileFilters = Constants.MAYA_FILE_FILTERS self.cameraSelector = Widgets.CueSelectPulldown('Render Cameras', options=cameras) self.selectorLayout = QtWidgets.QHBoxLayout() self.setupUi() @@ -92,9 +90,7 @@ class BaseMayaSettings(BaseSettingsWidget): def __init__(self, parent=None, *args, **kwargs): super(BaseMayaSettings, self).__init__(parent=parent) self.mayaFileInput = Widgets.CueLabelLineEdit('Maya File:') - self.fileFilters = ['Maya Ascii file (*.ma)', - 'Maya Binary file (*.mb)', - 'Maya file (*.ma *.mb)'] + self.fileFilters = Constants.MAYA_FILE_FILTERS self.setupUi() self.setupConnections() @@ -123,7 +119,7 @@ class InNukeSettings(BaseSettingsWidget): def __init__(self, writeNodes=None, filename=None, parent=None, *args, **kwargs): super(InNukeSettings, self).__init__(parent=parent) self.fileInput = Widgets.CueLabelLineEdit('Nuke File:', filename) - self.fileFilters = ['Nuke script file (*.nk)'] + self.fileFilters = Constants.NUKE_FILE_FILTERS self.writeNodeSelector = Widgets.CueSelectPulldown('Write Nodes:', emptyText='[All]', options=writeNodes) self.selectorLayout = QtWidgets.QHBoxLayout() @@ -160,7 +156,7 @@ class BaseNukeSettings(BaseSettingsWidget): def __init__(self, parent=None, *args, **kwargs): super(BaseNukeSettings, self).__init__(parent=parent) self.fileInput = Widgets.CueLabelLineEdit('Nuke File:') - self.fileFilters = ['Nuke script file (*.nk)'] + self.fileFilters = Constants.NUKE_FILE_FILTERS self.setupUi() self.setupConnections() @@ -215,7 +211,7 @@ class BaseBlenderSettings(BaseSettingsWidget): # pylint: disable=keyword-arg-before-vararg,unused-argument def __init__(self, parent=None, *args, **kwargs): super(BaseBlenderSettings, self).__init__(parent=parent) - self.fileFilters = ['Blender file (*.blend)'] + self.fileFilters = Constants.BLENDER_FILE_FILTERS self.fileInput = Widgets.CueLabelLineEdit('Blender File:') self.outputPath = Widgets.CueLabelLineEdit( 'Output Path (Optional):',