Example #1
0
    def pre_app_init(self):
        """
        Runs before apps have been initialized.
        """

        # Get Qt module regardless of version
        from sgtk.platform.qt import QtGui, QtCore

        # Here we're going to set the hyperlink text color to white
        # since the default is a dark blue that is pretty much unreadable
        # in a dark color environment like RV. It would be great if we
        # could style this in qss and only affect toolkit apps, but that's
        # no possible. As a result, we're modifying the QApplication-level
        # palette, which is also going to affect RV itself. This is generally
        # a BAD IDEA, but in this one case it is the best compromise solution
        # available.
        palette = QtGui.QApplication.palette()
        link_color = QtGui.QColor(255, 255, 255)
        palette.setColor(QtGui.QPalette.Link, link_color)
        palette.setColor(QtGui.QPalette.LinkVisited, link_color)
        palette.setColor(QtGui.QPalette.Button, QtGui.QColor(37, 38, 41))
        QtGui.QApplication.setPalette(palette)

        # We can't use import_framework here because the engine.py
        # wasn't imported via import_module itself. As a result, we
        # forgo the convenience and grab the framework ourselves and
        # import the submodules we need directly.
        shotgun_utils = self.frameworks["tk-framework-shotgunutils"]
        shotgun_globals = shotgun_utils.import_module("shotgun_globals")
        task_manager = shotgun_utils.import_module("task_manager")

        # We need a QObject to act as a parent for the task manager.
        # This will keep them and their threads from being garbage
        # collected prematurely by Qt.
        self.__task_parent = QtCore.QObject()

        # We will provide a task manager that apps can share.
        self._bg_task_manager = task_manager.BackgroundTaskManager(
            parent=self.__task_parent,
            start_processing=True,
            max_threads=RVEngine.MAX_THREADS,
        )

        shotgun_globals.register_bg_task_manager(self._bg_task_manager)

        # The "qss_watcher" setting causes us to monitor the engine's
        # style.qss file and re-apply it on the fly when it changes
        # on disk. This is very useful for development work,
        if self.get_setting("qss_watcher", False):
            self._qss_watcher = QtCore.QFileSystemWatcher([
                os.path.join(self.disk_location,
                             constants.BUNDLE_STYLESHEET_FILE)
            ], )

            self._qss_watcher.fileChanged.connect(self.reload_qss)

        # The assumption here is that the default case has us presenting a
        # Shotgun menu and loading it with at least Cutz Support and maybe
        # an expected Shotgun browser or two. _ui_enabled turns the menu on.
        # For shell access, setenv TK_RV_NO_UI NCC-1701 this is basically what
        # tk-maya does so following along.
        self._ui_enabled = os.environ.get("TK_RV_NO_UI") or True

        # Unicode characters returned by the shotgun api need to be converted
        # to display correctly in all of the app windows. Tell Qt to interpret
        # C strings as utf-8.
        utf8 = QtCore.QTextCodec.codecForName("utf-8")
        QtCore.QTextCodec.setCodecForCStrings(utf8)
Example #2
0
    def pre_app_init(self):
        """
        Called before all apps have initialized
        """
        from sgtk.platform.qt import QtCore

        self.log_debug("%s: Initializing..." % self)

        if self._get_max_version() > MaxEngine.MAXIMUM_SUPPORTED_VERSION:
            # Untested max version

            highest_supported_version = self._max_version_to_year(
                MaxEngine.MAXIMUM_SUPPORTED_VERSION)

            msg = (
                "Shotgun Pipeline Toolkit!\n\n"
                "The Shotgun Pipeline Toolkit has not yet been fully tested with 3ds Max versions greater than %s. "
                "You can continue to use the Toolkit but you may experience bugs or instability. "
                "Please report any issues you see to [email protected]"
                % highest_supported_version)

            # Display warning dialog
            max_year = self._max_version_to_year(self._get_max_version())
            max_next_year = highest_supported_version + 1
            if max_year >= self.get_setting("compatibility_dialog_min_version",
                                            max_next_year):
                MaxPlus.Core.EvalMAXScript('messagebox "Warning - ' + msg +
                                           '" title: "Shotgun Warning"')

            # and log the warning
            self.log_warning(msg)

        elif not self._is_at_least_max_2016():
            # Unsupported max version
            msg = (
                "Shotgun Pipeline Toolkit!\n\n"
                "The Shotgun Pipeline Toolkit does not work with 3ds max versions prior to 2016."
            )

            # Display warning dialog
            MaxPlus.Core.EvalMAXScript('messagebox "Warning - ' + msg +
                                       '" title: "Shotgun Warning"')

            # and log the warning
            self.log_warning(msg)

        self._safe_dialog = []

        # Add image formats since max doesn't add the correct paths by default and jpeg won't be readable
        maxpath = QtCore.QCoreApplication.applicationDirPath()
        pluginsPath = os.path.join(maxpath, "plugins")
        QtCore.QCoreApplication.addLibraryPath(pluginsPath)

        # Window focus objects are used to enable proper keyboard handling by the window instead of 3dsMax's accelerators
        engine = self

        class DialogEvents(QtCore.QObject):
            def eventFilter(self, obj, event):
                if event.type() == QtCore.QEvent.WindowActivate:
                    MaxPlus.CUI.DisableAccelerators()
                elif event.type() == QtCore.QEvent.WindowDeactivate:
                    MaxPlus.CUI.EnableAccelerators()

                # Remove from tracked dialogs
                if event.type() == QtCore.QEvent.Close:
                    if obj in engine._safe_dialog:
                        engine._safe_dialog.remove(obj)

                return False

        self.dialogEvents = DialogEvents()

        # set up a qt style sheet
        # note! - try to be smart about this and only run
        # the style setup once per session - it looks like
        # 3dsmax slows down if this is executed every engine restart.
        #
        # If we're in pre-Qt Max (before 2018) then we'll need to apply the
        # stylesheet to the QApplication. That's not safe in 2019.3+, as it's
        # possible that we'll get back a QCoreApplication from Max, which won't
        # carry references to a stylesheet. In that case, we apply our styling
        # to the dialog parent, which will be the top-level Max window.
        if self._max_version_to_year(self._get_max_version()) < 2018:
            parent_widget = sgtk.platform.qt.QtCore.QCoreApplication.instance()
        else:
            parent_widget = self._get_dialog_parent()

        curr_stylesheet = parent_widget.styleSheet()

        if "toolkit 3dsmax style extension" not in curr_stylesheet:
            # If we're in pre-2017 Max then we need to handle our own styling. Otherwise
            # we just inherit from Max.
            if self._max_version_to_year(self._get_max_version()) < 2017:
                self._initialize_dark_look_and_feel()

            curr_stylesheet += "\n\n /* toolkit 3dsmax style extension */ \n\n"
            curr_stylesheet += "\n\n QDialog#TankDialog > QWidget { background-color: #343434; }\n\n"
            parent_widget.setStyleSheet(curr_stylesheet)

        # This needs to be present for apps as it will be used in show_dialog when perforce asks for login
        # info very early on.
        self.tk_3dsmax = self.import_module("tk_3dsmaxplus")

        # The "qss_watcher" setting causes us to monitor the engine's
        # style.qss file and re-apply it on the fly when it changes
        # on disk. This is very useful for development work,
        if self.get_setting("qss_watcher", False):
            self._qss_watcher = QtCore.QFileSystemWatcher([
                os.path.join(self.disk_location,
                             sgtk.platform.constants.BUNDLE_STYLESHEET_FILE)
            ], )

            self._qss_watcher.fileChanged.connect(self.reload_qss)