Beispiel #1
0
    def execPushButton(self):
        """ Execute the function associated with a button.
			***NOT YET IMPLEMENTED***
		"""
        verbose.print_(
            "%s %s" %
            (self.sender().objectName(), self.sender().property('exec')))
Beispiel #2
0
def createDir(path):
    """ Create a directory with the specified path.
	"""
    path = os.path.normpath(path)

    if os.path.isdir(path):
        verbose.print_("Directory already exists: %s" % path)
        pass

    else:
        try:
            os.makedirs(path)

            # Hide the folder if its name starts with a dot, as these files
            # are not automatically hidden on Windows
            if os.environ['IC_RUNNING_OS'] == "Windows":
                if os.path.basename(path).startswith('.'):
                    setHidden(path)

            verbose.print_(
                'mkdir "%s"' %
                path)  # This causes an error if user config dir doesn't exist
            return path

        except:
            verbose.error("Cannot create directory: %s" % path)
            return False
Beispiel #3
0
    def storeValue(self, category, attr, value=""):
        """ Store value in data.
		"""
        currentAttrStr = "%20s %s.%s" % (type(value), category, attr)
        if currentAttrStr == self.currentAttrStr:
            verbose.print_("%s=%s" % (currentAttrStr, value), inline=True)
        else:
            verbose.print_("%s=%s" % (currentAttrStr, value))

        self.prefs.set_attr(category, attr, value)  # str(value)

        self.currentAttrStr = currentAttrStr
Beispiel #4
0
    def storeWindow(self):
        """ Store window geometry and state.
			(Save state may cause issues with PyQt5)
		"""
        if self.store_window_geometry:
            try:
                self.settings.setValue("geometry", self.saveGeometry())
                verbose.print_("Storing window geometry for '%s'." %
                               self.objectName())
            except:
                verbose.warning("Could not store window geometry for '%s'." %
                                self.objectName())
Beispiel #5
0
def copyDirContents(source, destination, umask='000'):
    """ Copy the contents of a folder recursively.
		Could rewrite using shutil.copy / copytree?
	"""
    src = os.path.normpath(os.path.join(source, "*"))
    dst = os.path.normpath(destination)

    if os.environ['IC_RUNNING_OS'] == "Windows":
        cmdStr = 'copy /Y "%s" "%s"' % (src, dst)
    elif os.environ['IC_RUNNING_OS'] == "Linux":  # Quick bodge
        cmdStr = 'cp -rf %s %s' % (src, dst)
    else:
        cmdStr = 'cp -rf "%s" "%s"' % (src, dst)

    verbose.print_(cmdStr)
    os.system(cmdStr)
Beispiel #6
0
    def calcAspectRatio(self):
        """ Calculate aspect ratio.
		"""
        # # fullWidth = self.frame.fullWidth_spinBox.value()
        # # fullHeight = self.frame.fullHeight_spinBox.value()
        # fullWidth = int(self.parent.prefs.get_attr('resolution', 'fullWidth'))
        # fullHeight = int(self.parent.prefs.get_attr('resolution', 'fullHeight'))
        fullWidth = self.getInt('fullWidth')
        fullHeight = self.getInt('fullHeight')
        ar = Fraction(fullWidth, fullHeight)
        self.parent.aspectRatio = float(fullWidth) / float(fullHeight)

        verbose.print_("Aspect ratio: %f" % self.parent.aspectRatio, 4)
        self.frame.preserveAR_checkBox.setText(
            "Lock aspect ratio to %d:%d (%.3f)" %
            (ar.numerator, ar.denominator, self.parent.aspectRatio))
Beispiel #7
0
def move(source, destination, quiet=False):
    """ Move a file or folder.
	"""
    src = os.path.normpath(source)
    dst = os.path.normpath(destination)

    if not quiet:
        verbose.print_('move "%s" -> "%s"' % (src, dst))
    try:
        shutil.move(src, dst)
        return True
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        msg = traceback.format_exception_only(exc_type, exc_value)[0]
        if not quiet:
            verbose.error(msg)
        return False
Beispiel #8
0
def execute(args):
    """ Wrapper to execute a command using subprocess.check_output().
	"""
    verbose.print_(" ".join(arg for arg in args))

    try:
        if os.environ['IC_RUNNING_OS'] == "Windows":
            output = subprocess.check_output(args,
                                             creationflags=CREATE_NO_WINDOW)
        else:
            output = subprocess.check_output(args)
        return True, output.decode()

    except subprocess.CalledProcessError as e:
        error_msg = e.output.decode()
        # verbose.error(error_msg)
        # raise RuntimeError(error_msg)
        return False, error_msg
Beispiel #9
0
    def openProperties(self, category, storeProperties=True):
        """ Open properties panel for selected settings category. Loads UI
			file and sets up widgets.
		"""
        self.currentCategory = category

        # Show panel & load values into form widgets
        if self.loadPanel(category):
            if (self.inherit is not None) \
            and self.ui.settings_frame.property('inheritable'):
                verbose.print_("Category: %s (values inheritable)" % category)
                self.setupWidgets(self.ui.settings_frame,
                                  forceCategory=category,
                                  inherit=self.prefs_inherited,
                                  storeProperties=False)
            else:
                verbose.print_("Category: %s" % category)
                self.setupWidgets(self.ui.settings_frame,
                                  forceCategory=category,
                                  storeProperties=storeProperties)
Beispiel #10
0
def hardLink(source, destination, umask='000', verify=True):
    """ Creates hard links.
	"""
    src = os.path.normpath(source)
    dst = os.path.normpath(destination)

    if os.environ['IC_RUNNING_OS'] == "Windows":
        # If destination is a folder, append the filename from the source
        if os.path.isdir(dst):
            filename = os.path.basename(src)
            dst = os.path.join(dst, filename)

        # Delete the destination file if it already exists - this is to mimic
        # the Unix behaviour and force creation of the hard link
        if os.path.isfile(dst):
            os.system('del "%s" /f /q' % dst)

        # Create the hardlink
        #cmdStr = 'mklink /H "%s" "%s"' %(dst, src)  # This only works with local NTFS volumes
        cmdStr = 'fsutil hardlink create "%s" "%s" >nul' % (
            dst, src
        )  # Works over SMB network shares; suppressing output to null
    else:
        #cmdStr = '%s; ln -f %s %s' %(setUmask(umask), src, dst)
        cmdStr = 'ln -f %s %s' % (src, dst)

    verbose.print_(cmdStr)
    os.system(cmdStr)

    # Make sure source and destination files match
    if verify:
        if verify_hardlink(src, dst):
            return dst
        else:
            verbose.warning(
                "Failed to create hardlink. Attempting to copy file instead.")
            copy(src, dst)
    else:
        return dst
Beispiel #11
0
def submit_job(**kwargs):
    """ Submit job to Deadline.
	"""
    cmd_output = ""
    result_msg = ""

    # if kwargs is not None:
    # 	for key, value in kwargs.items():
    # 		print("%24s = %s" %(key, value))

    try:
        if kwargs['renderLayers']:  # Batch submission -----------------------
            # Generate submission info files
            num_jobs = 0
            job_info_file_list = []
            plugin_info_file_list = []
            for render_layer in re.split(
                    r',\s*',
                    kwargs['renderLayers']):  # may be better to pass as list
                kwargs['renderLayer'] = render_layer
                # kwargs['isMovie'] = False
                job_info_file = generate_job_info_file(**kwargs)
                job_info_file_list.append(job_info_file)
                plugin_info_file = generate_plugin_info_file(**kwargs)
                plugin_info_file_list.append(plugin_info_file)
                num_jobs += 1

            # Generate batch file
            batch_submission_file = generate_batch_file(
                kwargs['scene'], job_info_file_list, plugin_info_file_list)

            # Execute deadlinecommand
            cmd_result, cmd_output = os_wrapper.execute(
                [os.environ['RQ_DEADLINECOMMAND'], batch_submission_file])
            if cmd_result:
                result_msg = "Successfully submitted %d job(s) to Deadline." % num_jobs

        else:  # Single job submission ---------------------------------------
            # Generate submission info files
            kwargs['renderLayer'] = None
            job_info_file = generate_job_info_file(**kwargs)
            plugin_info_file = generate_plugin_info_file(**kwargs)

            # Execute deadlinecommand
            cmd_result, cmd_output = os_wrapper.execute([
                os.environ['RQ_DEADLINECOMMAND'], job_info_file,
                plugin_info_file
            ])
            if cmd_result:
                result_msg = "Successfully submitted job to Deadline."

        if cmd_result:
            result = True
            verbose.print_(cmd_output)  #.decode())
            verbose.message(result_msg)
        else:
            raise RuntimeError(cmd_output)

    except:  # Submission failed ---------------------------------------------
        result = False
        exc_type, exc_value, exc_traceback = sys.exc_info()
        traceback.print_exception(exc_type, exc_value, exc_traceback)
        result_msg = "Failed to submit job to Deadline."
        verbose.error(result_msg)
        if (exc_type == RuntimeError) and cmd_output:
            result_msg += "\n" + cmd_output
        else:
            result_msg += "\nCheck console output for details."
        #output_str = "Either the Deadline executable could not be found, or the submission info files could not be written."
        #output_str = traceback.format_exception_only(exc_type, exc_value)[0]

    return result, result_msg
Beispiel #12
0
    def setupUI(self,
                window_object,
                window_title="",
                ui_file="",
                stylesheet="",
                prefs_file=None,
                store_window_geometry=True):
        """ Setup the UI.
		"""
        verbose.debug("Window object: %s Parent: %s" % (self, self.parent))

        # Instantiate preferences data class
        if prefs_file is None:
            self.prefs = None
        else:
            self.prefs = self.createPrefs(prefs_file)

        # Define some global variables
        self.currentAttrStr = ""

        # Load UI & stylesheet
        found_ui_file = self.checkFilePath(ui_file,
                                           searchpath=[
                                               os.environ['IC_FORMSDIR'],
                                           ])
        if os.path.isfile(found_ui_file):
            self.ui = QtCompat.loadUi(found_ui_file, self)
        else:
            verbose.error("UI file does not exist: %s" % found_ui_file)

        # Store some system UI colours & define colour palette
        self.col = {}
        self.col['text'] = QtGui.QColor(204, 204, 204)
        self.col['disabled'] = QtGui.QColor(102, 102, 102)
        self.col['highlighted-text'] = QtGui.QColor(255, 255, 255)
        tmpWidget = QtWidgets.QWidget()
        self.col['sys-window'] = tmpWidget.palette().color(
            QtGui.QPalette.Window)
        self.col['sys-highlight'] = tmpWidget.palette().color(
            QtGui.QPalette.Highlight)
        # self.col['window'] = self.col['sys-window']
        self.col['highlight'] = self.col['sys-highlight']
        self.col['window'] = QtGui.QColor('#444444')
        # self.col['highlight'] = QtGui.QColor('#78909c')
        self.computeUIPalette()

        # Load and set stylesheet
        self.stylesheet = self.checkFilePath(stylesheet,
                                             searchpath=[
                                                 os.environ['IC_FORMSDIR'],
                                             ])
        self.loadStyleSheet()

        # Set window title
        self.setObjectName(window_object)
        if window_title:
            self.setWindowTitle(window_title)
        else:
            window_title = self.windowTitle()

        # Perform custom widget setup
        self.setupWidgets(self.ui)

        # Restore window geometry and state
        self.store_window_geometry = store_window_geometry
        if self.store_window_geometry:
            try:
                uiName = self.objectName()
                if os.environ['IC_ENV'] != 'STANDALONE':
                    uiName += "_" + os.environ['IC_ENV'].lower()
                self.settings = QtCore.QSettings(os.environ['IC_VENDOR'],
                                                 uiName)
                self.restoreGeometry(self.settings.value("geometry", ""))
                verbose.print_("Restoring window geometry for '%s'." %
                               self.objectName())
            except (KeyError, TypeError):
                verbose.warning("Could not restore window geometry for '%s'." %
                                self.objectName())

            # # Use QSettings to store window geometry and state.
            # # (Restore state may cause issues with PyQt5)
            # if os.environ['IC_ENV'] == 'STANDALONE':
            # 	verbose.print_("Restoring window geometry for '%s'." %self.objectName())
            # 	try:
            # 		self.settings = QtCore.QSettings(
            # 			os.environ['IC_VENDOR'], window_title)
            # 		self.restoreGeometry(self.settings.value("geometry", ""))
            # 		# self.restoreState(self.settings.value("windowState", ""))
            # 	except:
            # 		pass

            # # Makes Maya perform magic which makes the window stay on top in
            # # OS X and Linux. As an added bonus, it'll make Maya remember the
            # # window position.
            # elif os.environ['IC_ENV'] == 'MAYA':
            # 	self.setProperty("saveWindowPref", True)

            # elif os.environ['IC_ENV'] == 'NUKE':
            # 	pass

        # else:
        # 	# Move to centre of active screen
        # 	desktop = QtWidgets.QApplication.desktop()
        # 	screen = desktop.screenNumber(desktop.cursor().pos())
        # 	self.move(desktop.screenGeometry(screen).center() - self.frameGeometry().center())
        # 	# Move to centre of parent window
        # 	self.move(self.parent.frameGeometry().center() - self.frameGeometry().center())

        # Set up keyboard shortcuts
        self.shortcutUnloadStyleSheet = QtWidgets.QShortcut(self)
        self.shortcutUnloadStyleSheet.setKey('Ctrl+Shift+R')
        self.shortcutUnloadStyleSheet.activated.connect(self.unloadStyleSheet)

        self.shortcutReloadStyleSheet = QtWidgets.QShortcut(self)
        self.shortcutReloadStyleSheet.setKey('Ctrl+R')
        self.shortcutReloadStyleSheet.activated.connect(self.loadStyleSheet)
Beispiel #13
0
def parse(filepath,
          base_dir=os.environ['SCNMGR_SAVE_DIR'],
          convention=os.environ['SCNMGR_CONVENTION']):
    """ Parse the given filepath (relative to base_dir) based on a naming
		convention and return a dictionary of elements for processing.
		TODO: check shot, artist, discipline etc. against valid whitelist
	"""
    if not os.path.isfile(filepath):
        verbose.print_("Could not parse filename as file doesn't exist: %s" %
                       filepath)
        return None

    filepath = os.path.normpath(filepath)
    base_dir = os.path.normpath(base_dir)

    # Make filepath relative to base_dir
    if filepath.startswith(base_dir):
        filepath = filepath.replace(base_dir, '', 1)
        filepath = filepath.replace('\\', '/')  # Convert to forward slashes
        if filepath.startswith('/'):
            filepath = filepath.replace('/', '', 1)  # Remove leading slash

    # Find optional parts in naming convention
    # (only one optional section is allowed, if there are more, all optional
    # parts will be ignored.)
    valid_conventions = [convention.replace('[', '').replace(']', '')]
    pattern = r'\[.+?\]'
    optionals = re.findall(pattern, convention)
    if len(optionals) == 1:
        for i, optional in enumerate(optionals):
            valid_conventions.append(convention.replace(optional, '', i + 1))
    # print valid_conventions

    # # Find tokens in naming convention
    # pattern = r'<\w+>'
    # tokens = re.findall(pattern, convention)

    # # Remove duplicates & sort list
    # tokens = list(set(tokens))
    # # tokens.sort()
    # print tokens

    # # Generate regular expression to represent naming convention

    token_dict = {}
    success = False
    f = explode_path(filepath)
    for con in valid_conventions:
        c = explode_path(con)

        if same_structure(f, c):
            for i, dirs in enumerate(c):
                for j, token in enumerate(dirs):
                    value = f[i][j]
                    if token in token_dict:  # Sanity check duplicated tokens
                        if token_dict[token] != value:
                            verbose.error(
                                "Could not parse filename due to a token value mismatch."
                            )
                            return None
                    else:
                        token_dict[token] = value

            success = True

    if success:
        # print(token_dict)
        return token_dict

    else:
        msg = "The filename '%s' could not be parsed because it does not comply with the naming convention." % filepath
        for con in valid_conventions:
            msg += "\n" + con
        verbose.error(msg)
        return None