def pre_app_init(self): from tk_syntheyes.ui.sgtk_panel import Ui_SgtkPanel # Alternative way of starting the panel but it would be too big for now # self.ui = self.show_dialog('SGTK Panel', self, Ui_SgtkPanel) self.ui = Ui_SgtkPanel(self._get_dialog_parent())
class SyntheyesEngine(sgtk.platform.Engine): _logger = logging.getLogger('sgtk.syntheyes.engine') ############################################################################ # init and destroy def init_engine(self): self._init_logging() self.log_debug("%s: Initializing...", self) self.__qt_dialogs = [] def pre_app_init(self): from tk_syntheyes.ui.sgtk_panel import Ui_SgtkPanel # Alternative way of starting the panel but it would be too big for now # self.ui = self.show_dialog('SGTK Panel', self, Ui_SgtkPanel) self.ui = Ui_SgtkPanel(self._get_dialog_parent()) def post_app_init(self): import tk_syntheyes self._initialize_dark_look_and_feel() self._panel_generator = tk_syntheyes.PanelGenerator(self) self._panel_generator.populate_panel() self.ui.show() def destroy_engine(self): self.log_debug("%s: Destroying...", self) self._panel_generator.destroy_panel() ############################################################################ # UI def _define_qt_base(self): """ This will be called at initialisation time and will allow a user to control various aspects of how QT is being used by Toolkit. The method should return a dictionary with a number of specific keys, outlined below. * qt_core - the QtCore module to use * qt_gui - the QtGui module to use * dialog_base - base class for to use for Toolkit's dialog factory :returns: dict """ base = {} from PySide import QtCore, QtGui base["qt_core"] = QtCore base["qt_gui"] = QtGui base["dialog_base"] = QtGui.QDialog # tell QT to handle text strings as utf-8 by default utf8 = QtCore.QTextCodec.codecForName("utf-8") QtCore.QTextCodec.setCodecForCStrings(utf8) return base def _win32_get_syntheyes_process_id(self): """ Windows specific method to find the process id of SynthEyes. This assumes that it is the parent process of this python process """ if hasattr(self, "_win32_syntheyes_process_id"): return self._win32_syntheyes_process_id self._win32_syntheyes_process_id = None this_pid = os.getpid() from tk_syntheyes import win_32_api self._win32_syntheyes_process_id = win_32_api.find_parent_process_id( this_pid) return self._win32_syntheyes_process_id def _win32_get_syntheyes_main_hwnd(self): """ Windows specific method to find the main SynthEyes window handle (HWND) """ if hasattr(self, "_win32_syntheyes_main_hwnd"): return self._win32_syntheyes_main_hwnd self._win32_syntheyes_main_hwnd = None # find SynthEyes process id: se_process_id = self._win32_get_syntheyes_process_id() if se_process_id != None: # get main application window for SynthEyes process: from tk_syntheyes import win_32_api found_hwnds = win_32_api.find_windows(process_id=se_process_id, class_name='SynthEyes', stop_if_found=False) if len(found_hwnds) == 1: self._win32_syntheyes_main_hwnd = found_hwnds[0] return self._win32_syntheyes_main_hwnd def _win32_get_proxy_window(self): """ Windows specific method to get the proxy window that will 'own' all Toolkit dialogs. This will be parented to the main syntheyes application. Creates the proxy window if it doesn't already exist. """ if hasattr(self, "_win32_proxy_win"): return self._win32_proxy_win self._win32_proxy_win = None # get the main syntheyes window: se_hwnd = self._win32_get_syntheyes_main_hwnd() if se_hwnd != None: from sgtk.platform.qt import QtGui from tk_syntheyes import win_32_api # create the proxy QWidget: self._win32_proxy_win = QtGui.QWidget() self._win32_proxy_win.setWindowTitle('SGTK Dialog Owner Proxy') proxy_win_hwnd = win_32_api.qwidget_winid_to_hwnd( self._win32_proxy_win.winId()) # set no parent notify: try: win_ex_style = win_32_api.GetWindowLong(proxy_win_hwnd, win_32_api.GWL_EXSTYLE) win_32_api.SetWindowLong(proxy_win_hwnd, win_32_api.GWL_EXSTYLE, win_ex_style | win_32_api.WS_EX_NOPARENTNOTIFY) # parent to syntheyes application window: win_32_api.SetParent(proxy_win_hwnd, se_hwnd) except Exception as e: self.log_debug(e) return self._win32_proxy_win def _get_dialog_parent(self): """ Get the QWidget parent for all dialogs created through show_dialog & show_modal. """ # determine the parent widget to use: if sys.platform == "win32": # for windows, we create a proxy window parented to the # main application window that we can then set as the owner # for all Toolkit dialogs. # FIXME: Doesn't work. Crashes the workfiles app when opening a file # There seems to be an issue with SynthEyes having another # child window. The parenting itself works. Checked with # "Window Detective". The proxy QWidget is parented correctly. # Even the show_modal stuff seems to enable and disable the window # correctly. # But opening a file from the workfiles app will crash SynthEyes. # Either it's a problem in SynthEyes or there still is something # wrong in the hack parenting in _win32_get_proxy_window(). # parent_widget = self._win32_get_proxy_window() from sgtk.platform.qt import QtGui parent_widget = QtGui.QApplication.activeWindow() else: from sgtk.platform.qt import QtGui parent_widget = QtGui.QApplication.activeWindow() return parent_widget def show_dialog(self, title, bundle, widget_class, *args, **kwargs): """ Shows a non-modal dialog window in a way suitable for this engine. The engine will attempt to parent the dialog nicely to the host application. :param title: The title of the window :param bundle: The app, engine or framework object that is associated with this window :param widget_class: The class of the UI to be constructed. This must derive from QWidget. Additional parameters specified will be passed through to the widget_class constructor. :returns: the created widget_class instance """ if not self.has_ui: msg = ('Sorry, this environment does not support UI display!' 'Cannot show the requested window "%s".' % title) self.log_error(msg) return # create the dialog: dialog, widget = self._create_dialog_with_widget(title, bundle, widget_class, *args, **kwargs) # Note - the base engine implementation will try to clean up # dialogs and widgets after they've been closed. However this # can cause a crash in SynthEyes as the system may try to send # an event after the dialog has been deleted. # Keeping track of all dialogs will ensure this doesn't happen self.__qt_dialogs.append(dialog) # make sure the window raised so it doesn't # appear behind the main SynthEyes window dialog.raise_() dialog.activateWindow() # show the dialog: dialog.show() return widget def show_modal(self, title, bundle, widget_class, *args, **kwargs): """ Shows a modal dialog window in a way suitable for this engine. The engine will attempt to integrate it as seamlessly as possible into the host application. This call is blocking until the user closes the dialog. :param title: The title of the window :param bundle: The app, engine or framework object that is associated with this window :param widget_class: The class of the UI to be constructed. This must derive from QWidget. Additional parameters specified will be passed through to the widget_class constructor. :returns: (a standard QT dialog status return code, the created widget_class instance) """ if not self.has_ui: msg = ('Sorry, this environment does not support UI display!' 'Cannot show the requested window "%s".' % title) self.log_error(msg) return from sgtk.platform.qt import QtGui # create the dialog: dialog, widget = self._create_dialog_with_widget(title, bundle, widget_class, *args, **kwargs) # Note - the base engine implementation will try to clean up # dialogs and widgets after they've been closed. However this # can cause a crash in SynthEyes as the system may try to send # an event after the dialog has been deleted. # Keeping track of all dialogs will ensure this doesn't happen self.__qt_dialogs.append(dialog) # make sure the window raised so it doesn't # appear behind the main SynthEyes window dialog.raise_() dialog.activateWindow() status = QtGui.QDialog.Rejected if sys.platform == "win32": from tk_syntheyes import win_32_api saved_state = [] try: # find all syntheyes windows and save enabled state: se_process_id = self._win32_get_syntheyes_process_id() if se_process_id != None: found_hwnds = win_32_api.find_windows( process_id=se_process_id, class_name='SynthEyes', stop_if_found=False) for hwnd in found_hwnds: enabled = win_32_api.IsWindowEnabled(hwnd) saved_state.append((hwnd, enabled)) if enabled: win_32_api.EnableWindow(hwnd, False) # show dialog: status = dialog.exec_() except Exception, e: self.log_error("Error showing modal dialog: %s" % e) finally: