From b174fce9def5a084e901444b84a5a7fc1d9226bd Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 16 Nov 2018 15:12:22 +0100 Subject: [PATCH 1/9] first commit --- pype/ftrack/login_dialog.py | 4 +- pype/ftrack/login_tools.py | 4 +- pype/ftrack/tray.py | 129 ++++++++++++++++++++++++++++++++++++ pype/ftrack/tray2.py | 49 ++++++++++++++ 4 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 pype/ftrack/tray.py create mode 100644 pype/ftrack/tray2.py diff --git a/pype/ftrack/login_dialog.py b/pype/ftrack/login_dialog.py index 622cfc21b5..8cfceb6d91 100644 --- a/pype/ftrack/login_dialog.py +++ b/pype/ftrack/login_dialog.py @@ -1,7 +1,7 @@ import sys import os import requests -from PyQt5 import QtCore, QtGui, QtWidgets +from app.vendor.Qt import QtCore, QtGui, QtWidgets from app import style from . import credentials, login_tools @@ -11,7 +11,7 @@ class Login_Dialog_ui(QtWidgets.QWidget): SIZE_W = 300 SIZE_H = 230 - loginSignal = QtCore.pyqtSignal(object, object, object) + loginSignal = QtCore.Signal(object, object, object) _login_server_thread = None inputs = [] buttons = [] diff --git a/pype/ftrack/login_tools.py b/pype/ftrack/login_tools.py index 719e6bac37..e38d3fa994 100644 --- a/pype/ftrack/login_tools.py +++ b/pype/ftrack/login_tools.py @@ -2,7 +2,7 @@ from http.server import BaseHTTPRequestHandler, HTTPServer from urllib import parse import webbrowser import functools -from PyQt5 import QtCore +from app.vendor.Qt import QtCore # class LoginServerHandler(BaseHTTPServer.BaseHTTPRequestHandler): class LoginServerHandler(BaseHTTPRequestHandler): @@ -82,7 +82,7 @@ class LoginServerThread(QtCore.QThread): '''Login server thread.''' # Login signal. - loginSignal = QtCore.pyqtSignal(object, object, object) + loginSignal = QtCore.Signal(object, object, object) def start(self, url): diff --git a/pype/ftrack/tray.py b/pype/ftrack/tray.py new file mode 100644 index 0000000000..b8b3af1356 --- /dev/null +++ b/pype/ftrack/tray.py @@ -0,0 +1,129 @@ +import os +import sys +import textwrap +from app.vendor.Qt import QtCore, QtGui, QtWidgets + +menu_layout_dict = {'Ftrack': { + 'Avalon Core': [ + 'Config core', + 'Create new project', + None, + 'Save database', + ], + 'Avalon Users': [ + 'Config User', + 'Cre&ate new user', + ], + 'Avalon Workfiles': [ + 'Config Workfiles', + ], + 'Pyblish': [ + 'Config Pyblish', + 'Create new micro-plugin', + None, + 'Micro-plugins manager' + ], + 'Pipeline': [ + 'Config pipeline', + 'Create new template', + None, + 'Templates manager' + ], + 'CG-wire': [ + 'Config CG-wire', + None, + 'Pull database', + 'Push database' + ] + }, + 'Minimalize': "action", + #'Close': "action" + } +# print(menu_layout_dict) +class SystemTrayIcon(QtWidgets.QSystemTrayIcon): + def __init__(self, icon, parent=None): + QtWidgets.QSystemTrayIcon.__init__(self, icon, parent) + self.tray = QtWidgets.QSystemTrayIcon(icon, parent) + # print(tray) + self.tray.setToolTip("Avalon Launcher") + menu = QtWidgets.QMenu(parent) + # self.menuBar() + # self.main_layout = QtWidgets.QVBoxLayout(self.menu) + # self.menu.setLayout(self.main_layout) + # project_name_lbl = QtWidgets.QLabel('Project Name') + # self.main_layout.addWidget(project_name_lbl) + menu.setProperty('menu', 'on') + label = QtWidgets.QLabel('Avalon', menu) + menu.setStyleSheet(textwrap.dedent(''' + QWidget { + background-color: #444444; + color: #ffffff; + } + QLineEdit { + background-color: white; + } + QLineEdit:no-text-inside-it { + background-color: red; + } + QWidget[menu=on] { + background-color: #333333; + color: #ffffff; + } + ''' + ) + ) + for key, value in menu_layout_dict.items(): + if value == 'action': + # menu = QtWidgets.QMenu(menu) + # menu = QtWidgets.QMenu(menu) + separator = menu.addSeparator() + # spacer = QtWidgets.QWidget() + menu.addAction(key) + print(key, value) + else: + # menu = QtWidgets.QMenu(menu) + avalon_plugins = menu.addMenu(key) + avalon_plugins.setProperty('submenu', 'on') + self.eventFilter(avalon_plugins, QtCore.QEvent.HoverMove) + for skey, svalue in value.items(): + avalon_plugin = avalon_plugins.addMenu(skey) + avalon_plugin.setProperty('submenu', 'on') + # print(skey, svalue) + # plugins_Menu = avalon_plugin.addMenu(skey) + for action in svalue: + if action == None: + avalon_plugin.addSeparator() + else: + plugins_Action = avalon_plugin.addAction(action) + menu.addMenu(avalon_plugins) + exitAction = menu.addAction("Exit") + self.eventFilter(exitAction, QtCore.QEvent.HoverMove) + self.setContextMenu(menu) + menu.triggered.connect(self.exit) + # main_layout.addWidget(menu) + def eventFilter(self, object, event): + print(self, object, event) + # if event.type() == QtCore.QEvent.MouseButtonPress: + # print("You pressed the button") + # return True + # # + if event == QtCore.QEvent.HoverMove: + print("C'mon! CLick-meeee!!!") + return True + def exit(self): + QtCore.QCoreApplication.exit() + +def _sys_tray(image): + # code source: https://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application - add answer PyQt5 + #PyQt4 to PyQt5 version: https://stackoverflow.com/questions/20749819/pyqt5-failing-import-of-qtgui + app = QtWidgets.QApplication(sys.argv) + w = QtWidgets.QWidget() + trayIcon = SystemTrayIcon(QtGui.QIcon(image), w) + # menu = + trayIcon.show() + sys.exit(app.exec_()) + +if (__name__ == ('__main__')): + avalon_core_icon = r'C:\Users\jakub.trllo\CODE\pype-setup\repos\avalon-launcher\launcher\res\icon\main.png' + print(avalon_core_icon) + _sys_tray(avalon_core_icon) diff --git a/pype/ftrack/tray2.py b/pype/ftrack/tray2.py new file mode 100644 index 0000000000..97677a3091 --- /dev/null +++ b/pype/ftrack/tray2.py @@ -0,0 +1,49 @@ +from app.vendor.Qt import QtGui +from app.vendor.Qt import QtWidgets +import credentials + +app = QApplication([]) +app.setQuitOnLastWindowClosed(False) + +# Create the icon +avalon_core_icon = r'C:\Users\jakub.trllo\CODE\pype-setup\repos\avalon-launcher\launcher\res\icon\main.png' +icon = QIcon(avalon_core_icon) + +clipboard = QApplication.clipboard() +dialog = QColorDialog() + +def logout(): + credentials. + +def copy_color_hsv(): + if dialog.exec_(): + color = dialog.currentColor() + clipboard.setText("hsv(%d, %d, %d)" % ( + color.hue(), color.saturation(), color.value() + )) +def exit(): + self.close() +# Create the tray +tray = QSystemTrayIcon() +tray.setIcon(icon) +tray.setVisible(True) + +# Create the menu +menu = QMenu() +exit = QAction("Exit") +exit.triggered.connect(exit) + +logout = QAction("Logout") +logout.triggered.connect(logout) + +action3 = QAction("HSV") +action3.triggered.connect(copy_color_hsv) + +menu.addAction(exit) +# menu.addAction(action2) +# menu.addAction(action3) + +# Add the menu to the tray +tray.setContextMenu(menu) + +app.exec_() From ed2c37031ba079bc7bd40e17dae9e03065fe24eb Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 16 Nov 2018 17:21:30 +0100 Subject: [PATCH 2/9] First steps to understanding Tray apps --- pype/ftrack/ftrackRun.py | 11 ++++ pype/ftrack/tray.py | 135 +++++++++++++++++---------------------- pype/ftrack/tray2.py | 49 -------------- 3 files changed, 69 insertions(+), 126 deletions(-) delete mode 100644 pype/ftrack/tray2.py diff --git a/pype/ftrack/ftrackRun.py b/pype/ftrack/ftrackRun.py index 245f7f2b46..384f5032d8 100644 --- a/pype/ftrack/ftrackRun.py +++ b/pype/ftrack/ftrackRun.py @@ -32,6 +32,8 @@ parser.add_argument("--eventserver", action="store_true", help="launch action server for ftrack") parser.add_argument("--logout", action="store_true", help="launch action server for ftrack") +parser.add_argument("--systray", action="store_true", + help="launch action server for ftrack") kwargs, args = parser.parse_known_args() @@ -47,6 +49,15 @@ if kwargs.eventserver: sys.executable, "-u", fname ]) +elif kwargs.systray: + stud_config = os.getenv('PYPE_STUDIO_CONFIG') + items = [stud_config, "pype", "ftrack", "tray.py"] + fname = os.path.sep.join(items) + + returncode = forward([ + sys.executable, "-u", fname + ]) + else: fname = os.path.join(os.environ["FTRACK_ACTION_SERVER"], "actionServer.py") returncode = forward([ diff --git a/pype/ftrack/tray.py b/pype/ftrack/tray.py index b8b3af1356..ec951229b1 100644 --- a/pype/ftrack/tray.py +++ b/pype/ftrack/tray.py @@ -1,45 +1,38 @@ import os import sys import textwrap +from app import style from app.vendor.Qt import QtCore, QtGui, QtWidgets -menu_layout_dict = {'Ftrack': { - 'Avalon Core': [ - 'Config core', - 'Create new project', - None, - 'Save database', - ], - 'Avalon Users': [ - 'Config User', - 'Cre&ate new user', - ], - 'Avalon Workfiles': [ - 'Config Workfiles', - ], - 'Pyblish': [ - 'Config Pyblish', - 'Create new micro-plugin', - None, - 'Micro-plugins manager' - ], - 'Pipeline': [ - 'Config pipeline', - 'Create new template', - None, - 'Templates manager' - ], - 'CG-wire': [ - 'Config CG-wire', - None, - 'Pull database', - 'Push database' - ] - }, - 'Minimalize': "action", - #'Close': "action" - } -# print(menu_layout_dict) +ftrack_layout = { + 'Avalon Users': { + 'Config User', + 'Cre&ate new user', + }, + 'Avalon Workfiles': { + 'Config Workfiles', + }, + 'Pyblish': { + 'Config Pyblish', + 'Create new micro-plugin', + None, + 'Micro-plugins manager' + }, + 'Pipeline': { + 'Config pipeline', + 'Create new template', + None, + 'Templates manager' + }, + 'Logout': "action", +} +applications = { + 'app_one':'action', + 'app_two':'action' +} + +menu_layout_dict = {'Ftrack':ftrack_layout, 'Apps':applications} + class SystemTrayIcon(QtWidgets.QSystemTrayIcon): def __init__(self, icon, parent=None): QtWidgets.QSystemTrayIcon.__init__(self, icon, parent) @@ -53,50 +46,38 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon): # project_name_lbl = QtWidgets.QLabel('Project Name') # self.main_layout.addWidget(project_name_lbl) menu.setProperty('menu', 'on') - label = QtWidgets.QLabel('Avalon', menu) - menu.setStyleSheet(textwrap.dedent(''' - QWidget { - background-color: #444444; - color: #ffffff; - } - QLineEdit { - background-color: white; - } - QLineEdit:no-text-inside-it { - background-color: red; - } - QWidget[menu=on] { - background-color: #333333; - color: #ffffff; - } - ''' - ) - ) + + menu.setStyleSheet(style.load_stylesheet()) for key, value in menu_layout_dict.items(): - if value == 'action': - # menu = QtWidgets.QMenu(menu) - # menu = QtWidgets.QMenu(menu) + print(100*"*") + print(key) + print(value) + if value == 'action': separator = menu.addSeparator() # spacer = QtWidgets.QWidget() menu.addAction(key) - print(key, value) - else: + else: # menu = QtWidgets.QMenu(menu) - avalon_plugins = menu.addMenu(key) - avalon_plugins.setProperty('submenu', 'on') - self.eventFilter(avalon_plugins, QtCore.QEvent.HoverMove) + combo_box = menu.addMenu(key) + combo_box.setProperty('submenu', 'on') + self.eventFilter(combo_box, QtCore.QEvent.HoverMove) for skey, svalue in value.items(): - avalon_plugin = avalon_plugins.addMenu(skey) - avalon_plugin.setProperty('submenu', 'on') - # print(skey, svalue) - # plugins_Menu = avalon_plugin.addMenu(skey) - for action in svalue: - if action == None: - avalon_plugin.addSeparator() - else: - plugins_Action = avalon_plugin.addAction(action) - menu.addMenu(avalon_plugins) + if svalue == 'action': + combo_box.addAction(skey) + elif svalue is None: + combo_box.addSeparator() + else: + nextbox = combo_box.addMenu(skey) + nextbox.setProperty('submenu', 'on') + for action in svalue: + if action == None: + nextbox.addSeparator() + else: + nextbox.addAction(action) + menu.addMenu(combo_box) + exitAction = menu.addAction("Exit") + self.eventFilter(exitAction, QtCore.QEvent.HoverMove) self.setContextMenu(menu) menu.triggered.connect(self.exit) @@ -108,7 +89,6 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon): # return True # # if event == QtCore.QEvent.HoverMove: - print("C'mon! CLick-meeee!!!") return True def exit(self): QtCore.QCoreApplication.exit() @@ -116,7 +96,9 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon): def _sys_tray(image): # code source: https://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application - add answer PyQt5 #PyQt4 to PyQt5 version: https://stackoverflow.com/questions/20749819/pyqt5-failing-import-of-qtgui - app = QtWidgets.QApplication(sys.argv) + # app = QtWidgets.QApplication(sys.argv) + app = QtWidgets.QApplication([]) + app.setQuitOnLastWindowClosed(False) w = QtWidgets.QWidget() trayIcon = SystemTrayIcon(QtGui.QIcon(image), w) # menu = @@ -125,5 +107,4 @@ def _sys_tray(image): if (__name__ == ('__main__')): avalon_core_icon = r'C:\Users\jakub.trllo\CODE\pype-setup\repos\avalon-launcher\launcher\res\icon\main.png' - print(avalon_core_icon) _sys_tray(avalon_core_icon) diff --git a/pype/ftrack/tray2.py b/pype/ftrack/tray2.py deleted file mode 100644 index 97677a3091..0000000000 --- a/pype/ftrack/tray2.py +++ /dev/null @@ -1,49 +0,0 @@ -from app.vendor.Qt import QtGui -from app.vendor.Qt import QtWidgets -import credentials - -app = QApplication([]) -app.setQuitOnLastWindowClosed(False) - -# Create the icon -avalon_core_icon = r'C:\Users\jakub.trllo\CODE\pype-setup\repos\avalon-launcher\launcher\res\icon\main.png' -icon = QIcon(avalon_core_icon) - -clipboard = QApplication.clipboard() -dialog = QColorDialog() - -def logout(): - credentials. - -def copy_color_hsv(): - if dialog.exec_(): - color = dialog.currentColor() - clipboard.setText("hsv(%d, %d, %d)" % ( - color.hue(), color.saturation(), color.value() - )) -def exit(): - self.close() -# Create the tray -tray = QSystemTrayIcon() -tray.setIcon(icon) -tray.setVisible(True) - -# Create the menu -menu = QMenu() -exit = QAction("Exit") -exit.triggered.connect(exit) - -logout = QAction("Logout") -logout.triggered.connect(logout) - -action3 = QAction("HSV") -action3.triggered.connect(copy_color_hsv) - -menu.addAction(exit) -# menu.addAction(action2) -# menu.addAction(action3) - -# Add the menu to the tray -tray.setContextMenu(menu) - -app.exec_() From 7cfb2d055a92e4b14251b0ab80bf656c4f509f65 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 20 Nov 2018 18:22:13 +0100 Subject: [PATCH 3/9] Tray runs, but is not able to run subprocesses properly(login, server,...) --- pype/ftrack/ftrackRun.py | 155 ++++++++++++++++++++++-------------- pype/ftrack/login_dialog.py | 12 +-- pype/ftrack/tray.py | 101 ++++++----------------- 3 files changed, 122 insertions(+), 146 deletions(-) diff --git a/pype/ftrack/ftrackRun.py b/pype/ftrack/ftrackRun.py index 384f5032d8..021314bb99 100644 --- a/pype/ftrack/ftrackRun.py +++ b/pype/ftrack/ftrackRun.py @@ -1,67 +1,106 @@ import sys import os import argparse - -from app.lib.utils import forward +import subprocess +import threading +import time +from app import style +from app.vendor.Qt import QtCore, QtGui, QtWidgets from pype.ftrack import credentials, login_dialog as login_dialog # Validation if alredy logged into Ftrack -def validate(): - validation = False - cred = credentials._get_credentials() - if 'username' in cred and 'apiKey' in cred: - validation = credentials._check_credentials( - cred['username'], - cred['apiKey'] +class FtrackRunner: + def __init__(self): + # self.app = QtWidgets.QApplication(sys.argv) + # self.loginWidget = login_dialog() + # self.app.exec_() + # try: + # self.validate() + # except Exception as e: + # print(e) + self.setServer() + self.run_login() + self.validate() + + def run_login(self): + thread = threading.Thread(target=self.runServer, args=()) + thread.daemon = True + thread.start() + + def validate(self): + validation = False + cred = credentials._get_credentials() + try: + if 'username' in cred and 'apiKey' in cred: + validation = credentials._check_credentials( + cred['username'], + cred['apiKey'] + ) + if validation is False: + login_dialog.run_login() + else: + login_dialog.run_login() + + except Exception as e: + print(e) + + validation = credentials._check_credentials() + if not validation: + print("We are unable to connect to Ftrack") + sys.exit() + + def logout(self): + credentials._clear_credentials() + print("Logged out of Ftrack") + + def trayMenu(self, parent): + + # Menu for Tray App + menu = QtWidgets.QMenu('Ftrack', parent) + menu.setProperty('submenu', 'on') + menu.setStyleSheet(style.load_stylesheet()) + + # Actions - server + smActionS = menu.addMenu("Servers") + aRunActionS = QtWidgets.QAction("Run action server", smActionS) + aRunActionS.triggered.connect(self.runServer) + aStopActionS = QtWidgets.QAction("Stop action server", smActionS) + aStopActionS.triggered.connect(self.stopServer) + + smActionS.addAction(aRunActionS) + smActionS.addAction(aStopActionS) + + # Actions - basic + aLogin = QtWidgets.QAction("Login",menu) + aLogin.triggered.connect(self.validate) + aLogout = QtWidgets.QAction("Logout",menu) + aLogout.triggered.connect(self.logout) + + menu.addAction(aLogin) + menu.addAction(aLogout) + + return menu + + def setServer(self): + fname = os.path.join(os.environ["FTRACK_ACTION_SERVER"], "actionServer.py") + print(fname) + DETACHED_PROCESS = 0x00000008 + self.aServer = subprocess.Popen( + [fname], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + bufsize=1, + cwd=None, + env=os.environ, + executable=sys.executable, + creationflags=DETACHED_PROCESS ) - if validation is False: - login_dialog.run_login() - else: - login_dialog.run_login() - validation = credentials._check_credentials() - if not validation: - print("We are unable to connect to Ftrack") - sys.exit() + def runServer(self): + print("Running server") + self.aServer.wait() -# Entered arguments -parser = argparse.ArgumentParser() -parser.add_argument("--actionserver", action="store_true", - help="launch action server for ftrack") -parser.add_argument("--eventserver", action="store_true", - help="launch action server for ftrack") -parser.add_argument("--logout", action="store_true", - help="launch action server for ftrack") -parser.add_argument("--systray", action="store_true", - help="launch action server for ftrack") - -kwargs, args = parser.parse_known_args() - -if kwargs.logout: - credentials._clear_credentials() - sys.exit() -else: - validate() - -if kwargs.eventserver: - fname = os.path.join(os.environ["FTRACK_ACTION_SERVER"], "eventServer.py") - returncode = forward([ - sys.executable, "-u", fname - ]) - -elif kwargs.systray: - stud_config = os.getenv('PYPE_STUDIO_CONFIG') - items = [stud_config, "pype", "ftrack", "tray.py"] - fname = os.path.sep.join(items) - - returncode = forward([ - sys.executable, "-u", fname - ]) - -else: - fname = os.path.join(os.environ["FTRACK_ACTION_SERVER"], "actionServer.py") - returncode = forward([ - sys.executable, "-u", fname - ]) - -sys.exit(returncode) + def stopServer(self): + print("Stopping server") + self.aServer.close() diff --git a/pype/ftrack/login_dialog.py b/pype/ftrack/login_dialog.py index 8cfceb6d91..a314dce102 100644 --- a/pype/ftrack/login_dialog.py +++ b/pype/ftrack/login_dialog.py @@ -287,16 +287,8 @@ class Login_Dialog_ui(QtWidgets.QWidget): self.close() -class Login_Dialog(Login_Dialog_ui): - def __init__(self): - super(Login_Dialog, self).__init__() - - -def getApp(): - return QtWidgets.QApplication(sys.argv) - def run_login(): - app = getApp() - ui = Login_Dialog() + app = QtWidgets.QApplication(sys.argv) + ui = Login_Dialog_ui() ui.show() app.exec_() diff --git a/pype/ftrack/tray.py b/pype/ftrack/tray.py index ec951229b1..8d282c54f1 100644 --- a/pype/ftrack/tray.py +++ b/pype/ftrack/tray.py @@ -1,96 +1,42 @@ import os import sys import textwrap +from pype.ftrack.ftrackRun import FtrackRunner from app import style from app.vendor.Qt import QtCore, QtGui, QtWidgets -ftrack_layout = { - 'Avalon Users': { - 'Config User', - 'Cre&ate new user', - }, - 'Avalon Workfiles': { - 'Config Workfiles', - }, - 'Pyblish': { - 'Config Pyblish', - 'Create new micro-plugin', - None, - 'Micro-plugins manager' - }, - 'Pipeline': { - 'Config pipeline', - 'Create new template', - None, - 'Templates manager' - }, - 'Logout': "action", -} -applications = { - 'app_one':'action', - 'app_two':'action' -} - -menu_layout_dict = {'Ftrack':ftrack_layout, 'Apps':applications} class SystemTrayIcon(QtWidgets.QSystemTrayIcon): - def __init__(self, icon, parent=None): + def __init__(self, icon, parent=None): QtWidgets.QSystemTrayIcon.__init__(self, icon, parent) + + self.parent = parent self.tray = QtWidgets.QSystemTrayIcon(icon, parent) - # print(tray) self.tray.setToolTip("Avalon Launcher") - menu = QtWidgets.QMenu(parent) - # self.menuBar() - # self.main_layout = QtWidgets.QVBoxLayout(self.menu) - # self.menu.setLayout(self.main_layout) - # project_name_lbl = QtWidgets.QLabel('Project Name') - # self.main_layout.addWidget(project_name_lbl) - menu.setProperty('menu', 'on') - menu.setStyleSheet(style.load_stylesheet()) - for key, value in menu_layout_dict.items(): - print(100*"*") - print(key) - print(value) - if value == 'action': - separator = menu.addSeparator() - # spacer = QtWidgets.QWidget() - menu.addAction(key) - else: - # menu = QtWidgets.QMenu(menu) - combo_box = menu.addMenu(key) - combo_box.setProperty('submenu', 'on') - self.eventFilter(combo_box, QtCore.QEvent.HoverMove) - for skey, svalue in value.items(): - if svalue == 'action': - combo_box.addAction(skey) - elif svalue is None: - combo_box.addSeparator() - else: - nextbox = combo_box.addMenu(skey) - nextbox.setProperty('submenu', 'on') - for action in svalue: - if action == None: - nextbox.addSeparator() - else: - nextbox.addAction(action) - menu.addMenu(combo_box) + self.menu = QtWidgets.QMenu(self.parent) + self.menu.setStyleSheet(style.load_stylesheet()) - exitAction = menu.addAction("Exit") + # TODO - Recognize that ftrack is used: + self.ftrack = FtrackRunner() + self.menu.addMenu(self.ftrack.trayMenu(self.menu)) - self.eventFilter(exitAction, QtCore.QEvent.HoverMove) - self.setContextMenu(menu) - menu.triggered.connect(self.exit) - # main_layout.addWidget(menu) - def eventFilter(self, object, event): + aExit = QtWidgets.QAction("Exit", self) + aExit.triggered.connect(self.exit) + self.menu.addAction(aExit) + + self.setContextMenu(self.menu) + + def eventFilter(self, object, event): print(self, object, event) - # if event.type() == QtCore.QEvent.MouseButtonPress: - # print("You pressed the button") - # return True - # # + if event.type() == QtCore.QEvent.MouseButtonPress: + print("You pressed the button") + return True + if event == QtCore.QEvent.HoverMove: return True - def exit(self): + + def exit(self): QtCore.QCoreApplication.exit() def _sys_tray(image): @@ -98,10 +44,9 @@ def _sys_tray(image): #PyQt4 to PyQt5 version: https://stackoverflow.com/questions/20749819/pyqt5-failing-import-of-qtgui # app = QtWidgets.QApplication(sys.argv) app = QtWidgets.QApplication([]) - app.setQuitOnLastWindowClosed(False) + app.setQuitOnLastWindowClosed(True) w = QtWidgets.QWidget() trayIcon = SystemTrayIcon(QtGui.QIcon(image), w) - # menu = trayIcon.show() sys.exit(app.exec_()) From be64b7f1c2bdc459b51010312196d788fe759fd3 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 21 Nov 2018 14:10:40 +0100 Subject: [PATCH 4/9] Only backup --- pype/ftrack/ftrackRun.py | 32 +++++++++++++++++++------------- pype/ftrack/login_dialog.py | 8 ++++++-- pype/ftrack/tray.py | 10 +++++++--- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/pype/ftrack/ftrackRun.py b/pype/ftrack/ftrackRun.py index 021314bb99..eb85500341 100644 --- a/pype/ftrack/ftrackRun.py +++ b/pype/ftrack/ftrackRun.py @@ -10,22 +10,27 @@ from pype.ftrack import credentials, login_dialog as login_dialog # Validation if alredy logged into Ftrack class FtrackRunner: - def __init__(self): - # self.app = QtWidgets.QApplication(sys.argv) - # self.loginWidget = login_dialog() - # self.app.exec_() + def __init__(self, parent=None): + self.parent = parent + self.parent.loginWidget = login_dialog.Login_Dialog_ui() + # try: # self.validate() # except Exception as e: # print(e) - self.setServer() - self.run_login() + + # self.setServer() self.validate() - def run_login(self): - thread = threading.Thread(target=self.runServer, args=()) - thread.daemon = True - thread.start() + def showLoginWidget(self): + # self.parent.loginWidget.exec_() + + # self.parent.loginWidget.show() + # self.parent.loginWidget.showMe() + test = login_dialog.Login_Dialog_ui() + test.show() + del(test) + def validate(self): validation = False @@ -37,9 +42,11 @@ class FtrackRunner: cred['apiKey'] ) if validation is False: - login_dialog.run_login() + self.showLoginWidget() + # login_dialog.run_login() else: - login_dialog.run_login() + self.showLoginWidget() + # login_dialog.run_login() except Exception as e: print(e) @@ -54,7 +61,6 @@ class FtrackRunner: print("Logged out of Ftrack") def trayMenu(self, parent): - # Menu for Tray App menu = QtWidgets.QMenu('Ftrack', parent) menu.setProperty('submenu', 'on') diff --git a/pype/ftrack/login_dialog.py b/pype/ftrack/login_dialog.py index a314dce102..c3e1b72916 100644 --- a/pype/ftrack/login_dialog.py +++ b/pype/ftrack/login_dialog.py @@ -17,7 +17,7 @@ class Login_Dialog_ui(QtWidgets.QWidget): buttons = [] labels = [] - def __init__(self): + def __init__(self, parent=None): super().__init__() self.loginSignal.connect(self.loginWithCredentials) @@ -37,6 +37,9 @@ class Login_Dialog_ui(QtWidgets.QWidget): self.setLayout(self._main()) self.setWindowTitle('FTrack Login') + # self.showMe() + + def showMe(self): self.show() def _main(self): @@ -284,7 +287,8 @@ class Login_Dialog_ui(QtWidgets.QWidget): def _close_widget(self): - self.close() + # self.close() + self.hide() def run_login(): diff --git a/pype/ftrack/tray.py b/pype/ftrack/tray.py index 8d282c54f1..53aa725240 100644 --- a/pype/ftrack/tray.py +++ b/pype/ftrack/tray.py @@ -1,7 +1,7 @@ import os import sys import textwrap -from pype.ftrack.ftrackRun import FtrackRunner +from pype.ftrack.ftrackRun import FtrackRunner, login_dialog from app import style from app.vendor.Qt import QtCore, QtGui, QtWidgets @@ -9,16 +9,17 @@ from app.vendor.Qt import QtCore, QtGui, QtWidgets class SystemTrayIcon(QtWidgets.QSystemTrayIcon): def __init__(self, icon, parent=None): QtWidgets.QSystemTrayIcon.__init__(self, icon, parent) - + self.parent = parent self.tray = QtWidgets.QSystemTrayIcon(icon, parent) self.tray.setToolTip("Avalon Launcher") + self.menu = QtWidgets.QMenu(self.parent) self.menu.setStyleSheet(style.load_stylesheet()) # TODO - Recognize that ftrack is used: - self.ftrack = FtrackRunner() + self.ftrack = FtrackRunner(self) self.menu.addMenu(self.ftrack.trayMenu(self.menu)) aExit = QtWidgets.QAction("Exit", self) @@ -27,6 +28,9 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon): self.setContextMenu(self.menu) + # self.loginWidget = login_dialog.Login_Dialog_ui() + # self.loginWidget.show() + def eventFilter(self, object, event): print(self, object, event) if event.type() == QtCore.QEvent.MouseButtonPress: From a87b3fda7a8dc08c869fdef262d14263b6a899f2 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 21 Nov 2018 16:43:40 +0100 Subject: [PATCH 5/9] Tray is able to show Login Widget but Login Widget can't get cred from browser --- pype/ftrack/ftrackRun.py | 36 +++++++++++---------------- pype/ftrack/login_dialog.py | 29 ++++++++-------------- pype/ftrack/tray.py | 49 ++++++++++++++++--------------------- 3 files changed, 45 insertions(+), 69 deletions(-) diff --git a/pype/ftrack/ftrackRun.py b/pype/ftrack/ftrackRun.py index eb85500341..a1491c737e 100644 --- a/pype/ftrack/ftrackRun.py +++ b/pype/ftrack/ftrackRun.py @@ -10,27 +10,19 @@ from pype.ftrack import credentials, login_dialog as login_dialog # Validation if alredy logged into Ftrack class FtrackRunner: - def __init__(self, parent=None): + def __init__(self, main_parent=None, parent=None): + self.parent = parent - self.parent.loginWidget = login_dialog.Login_Dialog_ui() + self.loginWidget = login_dialog.Login_Dialog_ui() - # try: - # self.validate() - # except Exception as e: - # print(e) - - # self.setServer() - self.validate() + self.setServer() + try: + self.validate() + except Exception as e: + print(e) def showLoginWidget(self): - # self.parent.loginWidget.exec_() - - # self.parent.loginWidget.show() - # self.parent.loginWidget.showMe() - test = login_dialog.Login_Dialog_ui() - test.show() - del(test) - + self.loginWidget.show() def validate(self): validation = False @@ -43,18 +35,18 @@ class FtrackRunner: ) if validation is False: self.showLoginWidget() - # login_dialog.run_login() else: self.showLoginWidget() - # login_dialog.run_login() except Exception as e: + print("We are unable to connect to Ftrack") print(e) validation = credentials._check_credentials() - if not validation: - print("We are unable to connect to Ftrack") - sys.exit() + if validation is True: + print("You are connected to Ftrack") + else: + print("Please sign in") def logout(self): credentials._clear_credentials() diff --git a/pype/ftrack/login_dialog.py b/pype/ftrack/login_dialog.py index c3e1b72916..15d3caf7be 100644 --- a/pype/ftrack/login_dialog.py +++ b/pype/ftrack/login_dialog.py @@ -19,7 +19,8 @@ class Login_Dialog_ui(QtWidgets.QWidget): def __init__(self, parent=None): - super().__init__() + super(Login_Dialog_ui, self).__init__(parent) + self.loginSignal.connect(self.loginWithCredentials) self._translate = QtCore.QCoreApplication.translate @@ -37,11 +38,6 @@ class Login_Dialog_ui(QtWidgets.QWidget): self.setLayout(self._main()) self.setWindowTitle('FTrack Login') - # self.showMe() - - def showMe(self): - self.show() - def _main(self): self.main = QtWidgets.QVBoxLayout() self.main.setObjectName("main") @@ -166,15 +162,15 @@ class Login_Dialog_ui(QtWidgets.QWidget): entity.setStyleSheet("border: 1px solid red;") def enter_credentials(self): - user = self.user_input.text().strip() - api = self.api_input.text().strip() + username = self.user_input.text().strip() + apiKey = self.api_input.text().strip() msg = "You didn't enter " missing = [] - if user == "": + if username == "": missing.append("Username") self._invalid_input(self.user_input) - if api == "": + if apiKey == "": missing.append("API Key") self._invalid_input(self.api_input) @@ -182,7 +178,7 @@ class Login_Dialog_ui(QtWidgets.QWidget): self.setError("{0} {1}".format(msg, " and ".join(missing))) return - verification = credentials._check_credentials(user, api) + verification = credentials._check_credentials(username, apiKey) if verification: credentials._save_credentials(username, apiKey) @@ -285,14 +281,9 @@ class Login_Dialog_ui(QtWidgets.QWidget): credentials._set_env(username, apiKey) self._close_widget() + def closeEvent(self, event): + event.ignore() + self._close_widget() def _close_widget(self): - # self.close() self.hide() - - -def run_login(): - app = QtWidgets.QApplication(sys.argv) - ui = Login_Dialog_ui() - ui.show() - app.exec_() diff --git a/pype/ftrack/tray.py b/pype/ftrack/tray.py index 53aa725240..86e645475b 100644 --- a/pype/ftrack/tray.py +++ b/pype/ftrack/tray.py @@ -7,53 +7,46 @@ from app.vendor.Qt import QtCore, QtGui, QtWidgets class SystemTrayIcon(QtWidgets.QSystemTrayIcon): - def __init__(self, icon, parent=None): + def __init__(self, parent=None): + + icon = r'C:\Users\jakub.trllo\CODE\pype-setup\repos\avalon-launcher\launcher\res\icon\main.png' + icon = QtGui.QIcon(icon) + QtWidgets.QSystemTrayIcon.__init__(self, icon, parent) - + + # Store parent - QtWidgets.QMainWindow() self.parent = parent - self.tray = QtWidgets.QSystemTrayIcon(icon, parent) - self.tray.setToolTip("Avalon Launcher") - - self.menu = QtWidgets.QMenu(self.parent) + # Setup menu in Tray + self.menu = QtWidgets.QMenu() self.menu.setStyleSheet(style.load_stylesheet()) - # TODO - Recognize that ftrack is used: - self.ftrack = FtrackRunner(self) + # Add ftrack menu (TODO - Recognize that ftrack is used!!!!!!) + self.ftrack = FtrackRunner(self.parent, self) self.menu.addMenu(self.ftrack.trayMenu(self.menu)) + # Add Exit action to menu aExit = QtWidgets.QAction("Exit", self) aExit.triggered.connect(self.exit) self.menu.addAction(aExit) + # Add menu to Context of SystemTrayIcon self.setContextMenu(self.menu) - # self.loginWidget = login_dialog.Login_Dialog_ui() - # self.loginWidget.show() - - def eventFilter(self, object, event): - print(self, object, event) - if event.type() == QtCore.QEvent.MouseButtonPress: - print("You pressed the button") - return True - - if event == QtCore.QEvent.HoverMove: - return True - def exit(self): QtCore.QCoreApplication.exit() -def _sys_tray(image): + +def _sys_tray(): # code source: https://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application - add answer PyQt5 #PyQt4 to PyQt5 version: https://stackoverflow.com/questions/20749819/pyqt5-failing-import-of-qtgui - # app = QtWidgets.QApplication(sys.argv) - app = QtWidgets.QApplication([]) - app.setQuitOnLastWindowClosed(True) - w = QtWidgets.QWidget() - trayIcon = SystemTrayIcon(QtGui.QIcon(image), w) + app = QtWidgets.QApplication(sys.argv) + # app.setQuitOnLastWindowClosed(True) + w = QtWidgets.QMainWindow() + # w = QtWidgets.QWidget() + trayIcon = SystemTrayIcon(w) trayIcon.show() sys.exit(app.exec_()) if (__name__ == ('__main__')): - avalon_core_icon = r'C:\Users\jakub.trllo\CODE\pype-setup\repos\avalon-launcher\launcher\res\icon\main.png' - _sys_tray(avalon_core_icon) + _sys_tray() From 235bc1e35f2567f1dd7557c7666a36b176c1ee88 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 21 Nov 2018 20:08:37 +0100 Subject: [PATCH 6/9] changing way launcher actions are organized --- pype/launcher_actions.py | 100 ++++-------------- .../launcher/actions/FusionRenderNode.py | 38 +++++++ .../launcher/actions/VrayRenderSlave.py | 44 ++++++++ 3 files changed, 104 insertions(+), 78 deletions(-) create mode 100644 pype/plugins/launcher/actions/FusionRenderNode.py create mode 100644 pype/plugins/launcher/actions/VrayRenderSlave.py diff --git a/pype/launcher_actions.py b/pype/launcher_actions.py index 7d72cb2b38..cf68dfb5c1 100644 --- a/pype/launcher_actions.py +++ b/pype/launcher_actions.py @@ -1,86 +1,30 @@ import os -from avalon import api, lib, pipeline +import sys +from avalon import api, pipeline -class FusionRenderNode(api.Action): - - name = "fusionrendernode9" - label = "F9 Render Node" - icon = "object-group" - order = 997 - - def is_compatible(self, session): - """Return whether the action is compatible with the session""" - if "AVALON_PROJECT" in session: - return False - return True - - def process(self, session, **kwargs): - """Implement the behavior for when the action is triggered - - Args: - session (dict): environment dictionary - - Returns: - Popen instance of newly spawned process - - """ - - # Update environment with session - env = os.environ.copy() - env.update(session) - - # Get executable by name - app = lib.get_application(self.name) - env.update(app["environment"]) - executable = lib.which(app["executable"]) - - return lib.launch(executable=executable, args=[], environment=env) - - -class VrayRenderSlave(api.Action): - - name = "vrayrenderslave" - label = "V-Ray Slave" - icon = "object-group" - order = 996 - - def is_compatible(self, session): - """Return whether the action is compatible with the session""" - if "AVALON_PROJECT" in session: - return False - return True - - def process(self, session, **kwargs): - """Implement the behavior for when the action is triggered - - Args: - session (dict): environment dictionary - - Returns: - Popen instance of newly spawned process - - """ - - # Update environment with session - env = os.environ.copy() - env.update(session) - - # Get executable by name - app = lib.get_application(self.name) - env.update(app["environment"]) - executable = lib.which(app["executable"]) - - # Run as server - arguments = ["-server", "-portNumber=20207"] - - return lib.launch(executable=executable, - args=arguments, - environment=env) +PACKAGE_DIR = os.path.dirname(__file__) +PLUGINS_DIR = os.path.join(PACKAGE_DIR, "plugins", "launcher") +ACTIONS_DIR = os.path.join(PLUGINS_DIR, "actions") def register_launcher_actions(): """Register specific actions which should be accessible in the launcher""" - pipeline.register_plugin(api.Action, FusionRenderNode) - pipeline.register_plugin(api.Action, VrayRenderSlave) + actions = [] + ext = ".py" + sys.path.append(ACTIONS_DIR) + + for f in os.listdir(ACTIONS_DIR): + file, extention = os.path.splitext(f) + if ext in extention: + module = __import__(file) + klass = getattr(module, file) + actions.append(klass) + + if actions is []: + return + + for action in actions: + print("Using launcher action from config @ '{}'".format(action.name)) + pipeline.register_plugin(api.Action, action) diff --git a/pype/plugins/launcher/actions/FusionRenderNode.py b/pype/plugins/launcher/actions/FusionRenderNode.py new file mode 100644 index 0000000000..d866215fac --- /dev/null +++ b/pype/plugins/launcher/actions/FusionRenderNode.py @@ -0,0 +1,38 @@ +import os +from avalon import api, lib + + +class FusionRenderNode(api.Action): + + name = "fusionrendernode9" + label = "F9 Render Node" + icon = "object-group" + order = 997 + + def is_compatible(self, session): + """Return whether the action is compatible with the session""" + if "AVALON_PROJECT" in session: + return False + return True + + def process(self, session, **kwargs): + """Implement the behavior for when the action is triggered + + Args: + session (dict): environment dictionary + + Returns: + Popen instance of newly spawned process + + """ + + # Update environment with session + env = os.environ.copy() + env.update(session) + + # Get executable by name + app = lib.get_application(self.name) + env.update(app["environment"]) + executable = lib.which(app["executable"]) + + return lib.launch(executable=executable, args=[], environment=env) diff --git a/pype/plugins/launcher/actions/VrayRenderSlave.py b/pype/plugins/launcher/actions/VrayRenderSlave.py new file mode 100644 index 0000000000..7461cfc0dd --- /dev/null +++ b/pype/plugins/launcher/actions/VrayRenderSlave.py @@ -0,0 +1,44 @@ +import os + +from avalon import api, lib + + +class VrayRenderSlave(api.Action): + + name = "vrayrenderslave" + label = "V-Ray Slave" + icon = "object-group" + order = 996 + + def is_compatible(self, session): + """Return whether the action is compatible with the session""" + if "AVALON_PROJECT" in session: + return False + return True + + def process(self, session, **kwargs): + """Implement the behavior for when the action is triggered + + Args: + session (dict): environment dictionary + + Returns: + Popen instance of newly spawned process + + """ + + # Update environment with session + env = os.environ.copy() + env.update(session) + + # Get executable by name + app = lib.get_application(self.name) + env.update(app["environment"]) + executable = lib.which(app["executable"]) + + # Run as server + arguments = ["-server", "-portNumber=20207"] + + return lib.launch(executable=executable, + args=arguments, + environment=env) From 2dcd070dfc47158658a6b5f9ebf57861a20a064d Mon Sep 17 00:00:00 2001 From: antirotor Date: Thu, 22 Nov 2018 12:43:07 +0100 Subject: [PATCH 7/9] added support for flake8 --- .flake8 | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000000..9de8d23bb2 --- /dev/null +++ b/.flake8 @@ -0,0 +1,9 @@ +[flake8] +# ignore = D203 +exclude = + .git, + __pycache__, + docs, + */vendor + +max-complexity = 30 From bf1994a0746b5bc538592ca2e4361edfda95ea89 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 22 Nov 2018 17:58:24 +0100 Subject: [PATCH 8/9] Added event server, seems like working properly --- pype/ftrack/ftrackRun.py | 195 +++++++++++++++++++++++++++--------- pype/ftrack/login_dialog.py | 11 +- pype/ftrack/tray.py | 52 ---------- 3 files changed, 155 insertions(+), 103 deletions(-) delete mode 100644 pype/ftrack/tray.py diff --git a/pype/ftrack/ftrackRun.py b/pype/ftrack/ftrackRun.py index a1491c737e..6e7f20ba1d 100644 --- a/pype/ftrack/ftrackRun.py +++ b/pype/ftrack/ftrackRun.py @@ -7,19 +7,24 @@ import time from app import style from app.vendor.Qt import QtCore, QtGui, QtWidgets from pype.ftrack import credentials, login_dialog as login_dialog +from app.api import Logger +import actionServer, eventServer +log = Logger.getLogger(__name__) # Validation if alredy logged into Ftrack class FtrackRunner: def __init__(self, main_parent=None, parent=None): self.parent = parent - self.loginWidget = login_dialog.Login_Dialog_ui() + self.loginWidget = login_dialog.Login_Dialog_ui(self) + self.actionThread = None + self.actionServer = actionServer.FtrackActionServer() + self.eventThread = None + self.eventServer = eventServer.FtrackEventServer() - self.setServer() - try: - self.validate() - except Exception as e: - print(e) + self.boolLogged = False + self.boolActionServer = False + self.boolEventServer = False def showLoginWidget(self): self.loginWidget.show() @@ -39,66 +44,158 @@ class FtrackRunner: self.showLoginWidget() except Exception as e: - print("We are unable to connect to Ftrack") - print(e) + log.error("We are unable to connect to Ftrack: {0}".format(e)) validation = credentials._check_credentials() if validation is True: - print("You are connected to Ftrack") + log.info("Connected to Ftrack successfully") + self.loginChange() else: - print("Please sign in") + log.warning("Please sign in to Ftrack") + self.boolLogged = False + self.setMenuVisibility() + + return validation + + # Necessary - login_dialog works with this method after logging in + def loginChange(self): + self.boolLogged = True + self.setMenuVisibility() + self.runActionServer() def logout(self): credentials._clear_credentials() - print("Logged out of Ftrack") + self.stopActionServer() + self.stopEventServer() + log.info("Logged out of Ftrack") + self.boolLogged = False + self.setMenuVisibility() + + # Actions part + def runActionServer(self): + if self.actionThread is None: + self.actionThread = threading.Thread(target=self.setActionServer) + self.actionThread.daemon=True + self.actionThread.start() + + log.info("Ftrack action server launched") + self.boolActionServer = True + self.setMenuVisibility() + + def setActionServer(self): + self.actionServer.run_action_server() + + def resetActionServer(self): + self.stopActionServer() + self.runActionServer() + + def stopActionServer(self): + try: + self.actionServer.stop_action_session() + if self.actionThread is not None: + self.actionThread.join() + self.actionThread = None + + log.info("Ftrack action server stopped") + self.boolActionServer = False + self.setMenuVisibility() + except Exception as e: + log.error("During Killing action server: {0}".format(e)) + + # Events part + def runEventServer(self): + if self.eventThread is None: + self.eventThread = threading.Thread(target=self.setEventServer) + self.eventThread.daemon=True + self.eventThread.start() + + log.info("Ftrack event server launched") + self.boolEventServer = True + self.setMenuVisibility() + + def setEventServer(self): + self.eventServer.run_event_server() + + def resetEventServer(self): + self.stopEventServer() + self.runEventServer() + + def stopEventServer(self): + try: + self.eventServer.stop_event_session() + if self.eventThread is not None: + self.eventThread.join() + self.eventThread = None + + log.info("Ftrack event server stopped") + self.boolEventServer = False + self.setMenuVisibility() + except Exception as e: + log.error("During Killing Event server: {0}".format(e)) + + # Definition of Tray menu def trayMenu(self, parent): # Menu for Tray App - menu = QtWidgets.QMenu('Ftrack', parent) - menu.setProperty('submenu', 'on') - menu.setStyleSheet(style.load_stylesheet()) + self.menu = QtWidgets.QMenu('Ftrack', parent) + self.menu.setProperty('submenu', 'on') + self.menu.setStyleSheet(style.load_stylesheet()) # Actions - server - smActionS = menu.addMenu("Servers") - aRunActionS = QtWidgets.QAction("Run action server", smActionS) - aRunActionS.triggered.connect(self.runServer) - aStopActionS = QtWidgets.QAction("Stop action server", smActionS) - aStopActionS.triggered.connect(self.stopServer) + self.smActionS = self.menu.addMenu("Action server") + self.aRunActionS = QtWidgets.QAction("Run action server", self.smActionS) + self.aRunActionS.triggered.connect(self.runActionServer) + self.aResetActionS = QtWidgets.QAction("Reset action server", self.smActionS) + self.aResetActionS.triggered.connect(self.resetActionServer) + self.aStopActionS = QtWidgets.QAction("Stop action server", self.smActionS) + self.aStopActionS.triggered.connect(self.stopActionServer) - smActionS.addAction(aRunActionS) - smActionS.addAction(aStopActionS) + self.smActionS.addAction(self.aRunActionS) + self.smActionS.addAction(self.aResetActionS) + self.smActionS.addAction(self.aStopActionS) + + # Actions - server + self.smEventS = self.menu.addMenu("Event server") + self.aRunEventS = QtWidgets.QAction("Run event server", self.smEventS) + self.aRunEventS.triggered.connect(self.runEventServer) + self.aResetEventS = QtWidgets.QAction("Reset event server", self.smEventS) + self.aResetEventS.triggered.connect(self.resetEventServer) + self.aStopEventS = QtWidgets.QAction("Stop event server", self.smEventS) + self.aStopEventS.triggered.connect(self.stopEventServer) + + self.smEventS.addAction(self.aRunEventS) + self.smEventS.addAction(self.aResetEventS) + self.smEventS.addAction(self.aStopEventS) # Actions - basic - aLogin = QtWidgets.QAction("Login",menu) - aLogin.triggered.connect(self.validate) - aLogout = QtWidgets.QAction("Logout",menu) - aLogout.triggered.connect(self.logout) + self.aLogin = QtWidgets.QAction("Login",self.menu) + self.aLogin.triggered.connect(self.validate) + self.aLogout = QtWidgets.QAction("Logout",self.menu) + self.aLogout.triggered.connect(self.logout) - menu.addAction(aLogin) - menu.addAction(aLogout) + self.menu.addAction(self.aLogin) + self.menu.addAction(self.aLogout) - return menu + self.boolLogged = False + self.setMenuVisibility() - def setServer(self): - fname = os.path.join(os.environ["FTRACK_ACTION_SERVER"], "actionServer.py") - print(fname) - DETACHED_PROCESS = 0x00000008 - self.aServer = subprocess.Popen( - [fname], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True, - bufsize=1, - cwd=None, - env=os.environ, - executable=sys.executable, - creationflags=DETACHED_PROCESS - ) + return self.menu - def runServer(self): - print("Running server") - self.aServer.wait() + # Definition of visibility of each menu actions + def setMenuVisibility(self): - def stopServer(self): - print("Stopping server") - self.aServer.close() + self.smActionS.menuAction().setVisible(self.boolLogged) + self.smEventS.menuAction().setVisible(self.boolLogged) + self.aLogin.setVisible(not self.boolLogged) + self.aLogout.setVisible(self.boolLogged) + + if self.boolLogged is False: + return + + self.aRunActionS.setVisible(not self.boolActionServer) + self.aResetActionS.setVisible(self.boolActionServer) + self.aStopActionS.setVisible(self.boolActionServer) + + self.aRunEventS.setVisible(not self.boolEventServer) + self.aResetEventS.setVisible(self.boolEventServer) + self.aStopEventS.setVisible(self.boolEventServer) diff --git a/pype/ftrack/login_dialog.py b/pype/ftrack/login_dialog.py index 15d3caf7be..020f917b9a 100644 --- a/pype/ftrack/login_dialog.py +++ b/pype/ftrack/login_dialog.py @@ -19,8 +19,13 @@ class Login_Dialog_ui(QtWidgets.QWidget): def __init__(self, parent=None): - super(Login_Dialog_ui, self).__init__(parent) + super(Login_Dialog_ui, self).__init__() + self.parent = parent + + self.setWindowIcon(self.parent.parent.icon) + self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowMinimizeButtonHint) + self.loginSignal.connect(self.loginWithCredentials) self._translate = QtCore.QCoreApplication.translate @@ -33,10 +38,11 @@ class Login_Dialog_ui(QtWidgets.QWidget): self.resize(self.SIZE_W, self.SIZE_H) self.setMinimumSize(QtCore.QSize(self.SIZE_W, self.SIZE_H)) + self.setMaximumSize(QtCore.QSize(self.SIZE_W+100, self.SIZE_H+100)) self.setStyleSheet(style.load_stylesheet()) self.setLayout(self._main()) - self.setWindowTitle('FTrack Login') + self.setWindowTitle('Pype - Ftrack Login') def _main(self): self.main = QtWidgets.QVBoxLayout() @@ -279,6 +285,7 @@ class Login_Dialog_ui(QtWidgets.QWidget): if verification is True: credentials._save_credentials(username, apiKey) credentials._set_env(username, apiKey) + self.parent.loginChange() self._close_widget() def closeEvent(self, event): diff --git a/pype/ftrack/tray.py b/pype/ftrack/tray.py deleted file mode 100644 index 86e645475b..0000000000 --- a/pype/ftrack/tray.py +++ /dev/null @@ -1,52 +0,0 @@ -import os -import sys -import textwrap -from pype.ftrack.ftrackRun import FtrackRunner, login_dialog -from app import style -from app.vendor.Qt import QtCore, QtGui, QtWidgets - - -class SystemTrayIcon(QtWidgets.QSystemTrayIcon): - def __init__(self, parent=None): - - icon = r'C:\Users\jakub.trllo\CODE\pype-setup\repos\avalon-launcher\launcher\res\icon\main.png' - icon = QtGui.QIcon(icon) - - QtWidgets.QSystemTrayIcon.__init__(self, icon, parent) - - # Store parent - QtWidgets.QMainWindow() - self.parent = parent - - # Setup menu in Tray - self.menu = QtWidgets.QMenu() - self.menu.setStyleSheet(style.load_stylesheet()) - - # Add ftrack menu (TODO - Recognize that ftrack is used!!!!!!) - self.ftrack = FtrackRunner(self.parent, self) - self.menu.addMenu(self.ftrack.trayMenu(self.menu)) - - # Add Exit action to menu - aExit = QtWidgets.QAction("Exit", self) - aExit.triggered.connect(self.exit) - self.menu.addAction(aExit) - - # Add menu to Context of SystemTrayIcon - self.setContextMenu(self.menu) - - def exit(self): - QtCore.QCoreApplication.exit() - - -def _sys_tray(): - # code source: https://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application - add answer PyQt5 - #PyQt4 to PyQt5 version: https://stackoverflow.com/questions/20749819/pyqt5-failing-import-of-qtgui - app = QtWidgets.QApplication(sys.argv) - # app.setQuitOnLastWindowClosed(True) - w = QtWidgets.QMainWindow() - # w = QtWidgets.QWidget() - trayIcon = SystemTrayIcon(w) - trayIcon.show() - sys.exit(app.exec_()) - -if (__name__ == ('__main__')): - _sys_tray() From 40fd26fd75e36aec39b9da28ec8080275ee889a4 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 23 Nov 2018 16:29:28 +0100 Subject: [PATCH 9/9] New FtrackServer implemented --- pype/ftrack/ftrackRun.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pype/ftrack/ftrackRun.py b/pype/ftrack/ftrackRun.py index 6e7f20ba1d..e90530b3b2 100644 --- a/pype/ftrack/ftrackRun.py +++ b/pype/ftrack/ftrackRun.py @@ -8,7 +8,7 @@ from app import style from app.vendor.Qt import QtCore, QtGui, QtWidgets from pype.ftrack import credentials, login_dialog as login_dialog from app.api import Logger -import actionServer, eventServer +from FtrackServer import FtrackServer log = Logger.getLogger(__name__) # Validation if alredy logged into Ftrack @@ -18,9 +18,9 @@ class FtrackRunner: self.parent = parent self.loginWidget = login_dialog.Login_Dialog_ui(self) self.actionThread = None - self.actionServer = actionServer.FtrackActionServer() + self.actionServer = FtrackServer('action') self.eventThread = None - self.eventServer = eventServer.FtrackEventServer() + self.eventServer = FtrackServer('event') self.boolLogged = False self.boolActionServer = False @@ -84,7 +84,7 @@ class FtrackRunner: self.setMenuVisibility() def setActionServer(self): - self.actionServer.run_action_server() + self.actionServer.run_server() def resetActionServer(self): self.stopActionServer() @@ -92,7 +92,7 @@ class FtrackRunner: def stopActionServer(self): try: - self.actionServer.stop_action_session() + self.actionServer.stop_session() if self.actionThread is not None: self.actionThread.join() self.actionThread = None @@ -115,7 +115,7 @@ class FtrackRunner: self.setMenuVisibility() def setEventServer(self): - self.eventServer.run_event_server() + self.eventServer.run_server() def resetEventServer(self): self.stopEventServer() @@ -123,7 +123,7 @@ class FtrackRunner: def stopEventServer(self): try: - self.eventServer.stop_event_session() + self.eventServer.stop_session() if self.eventThread is not None: self.eventThread.join() self.eventThread = None