diff --git a/pype/plugins/global/publish/collect_current_pype_user.py b/pype/plugins/global/publish/collect_current_pype_user.py new file mode 100644 index 0000000000..359e6b852c --- /dev/null +++ b/pype/plugins/global/publish/collect_current_pype_user.py @@ -0,0 +1,19 @@ +import os +import getpass +import pyblish.api + + +class CollectCurrentUserPype(pyblish.api.ContextPlugin): + """Inject the currently logged on user into the Context""" + + # Order must be after default pyblish-base CollectCurrentUser + order = pyblish.api.CollectorOrder + 0.001 + label = "Collect Pype User" + + def process(self, context): + user = os.getenv("PYPE_USERNAME", "").strip() + if not user: + return + + context.data["user"] = user + self.log.debug("Pype user is \"{}\"".format(user)) diff --git a/pype/user/__init__.py b/pype/user/__init__.py new file mode 100644 index 0000000000..04fe392c2c --- /dev/null +++ b/pype/user/__init__.py @@ -0,0 +1,5 @@ +from .user_module import UserModule + + +def tray_init(tray_widget, main_widget): + return UserModule(main_widget, tray_widget) diff --git a/pype/user/user_module.py b/pype/user/user_module.py new file mode 100644 index 0000000000..d70885b211 --- /dev/null +++ b/pype/user/user_module.py @@ -0,0 +1,123 @@ +import os +import json +import getpass + +import appdirs +from Qt import QtWidgets +from .widget_user import UserWidget + +from pype import api as pype + + +class UserModule: + cred_folder_path = os.path.normpath( + appdirs.user_data_dir('pype-app', 'pype') + ) + cred_filename = 'user_info.json' + env_name = "PYPE_USERNAME" + + log = pype.Logger().get_logger("UserModule", "user") + + def __init__(self, main_parent=None, parent=None): + self.cred = {} + + self.cred_path = os.path.normpath(os.path.join( + self.cred_folder_path, self.cred_filename + )) + self.widget_login = UserWidget(self) + + self.load_credentials() + + def tray_start(self): + """Store credentials to env and preset them to widget""" + username = "" + if self.cred: + username = self.cred.get("username") or "" + + os.environ[self.env_name] = username + self.widget_login.set_user(username) + + def process_modules(self, modules): + """ Gives ability to connect with imported modules from TrayManager. + + :param modules: All imported modules from TrayManager + :type modules: dict + """ + + if "RestApiServer" in modules: + def api_get_username(): + return self.cred + + def api_show_widget(): + self.action_show_widget.trigger() + + modules["RestApiServer"].register_callback( + "user/username", api_get_username, "get" + ) + modules["RestApiServer"].register_callback( + "user/show_widget", api_show_widget, "post" + ) + + # Definition of Tray menu + def tray_menu(self, parent_menu): + """Add menu or action to Tray(or parent)'s menu""" + action = QtWidgets.QAction("Username", parent_menu) + action.triggered.connect(self.show_widget) + parent_menu.addAction(action) + parent_menu.addSeparator() + + self.action_show_widget = action + + def load_credentials(self): + """Get credentials from JSON file """ + credentials = {} + try: + file = open(self.cred_path, "r") + credentials = json.load(file) + file.close() + + self.cred = credentials + username = credentials.get("username") + if username: + self.log.debug("Loaded Username \"{}\"".format(username)) + else: + self.log.debug("Pype Username is not set") + + return credentials + + except FileNotFoundError: + return self.save_credentials(getpass.getuser()) + + except json.decoder.JSONDecodeError: + self.log.warning(( + "File where users credentials should be stored" + " has invalid json format. Loading system username." + )) + return self.save_credentials(getpass.getuser()) + + def save_credentials(self, username): + """Save credentials to JSON file, env and widget""" + if username is None: + username = "" + + username = str(username).strip() + + self.cred = {"username": username} + os.environ[self.env_name] = username + self.widget_login.set_user(username) + try: + file = open(self.cred_path, "w") + file.write(json.dumps(self.cred)) + file.close() + self.log.debug("Username \"{}\" stored".format(username)) + except Exception: + self.log.error( + "Could not store username to file \"{}\"".format(self.cred_path), + exc_info=True + ) + + return self.cred + + def show_widget(self): + """Show dialog to enter credentials""" + self.widget_login.show() diff --git a/pype/user/widget_user.py b/pype/user/widget_user.py new file mode 100644 index 0000000000..7ca12ec4d4 --- /dev/null +++ b/pype/user/widget_user.py @@ -0,0 +1,88 @@ +import os +from Qt import QtCore, QtGui, QtWidgets +from pypeapp import style, resources + + +class UserWidget(QtWidgets.QWidget): + + MIN_WIDTH = 300 + + def __init__(self, module): + + super(UserWidget, self).__init__() + + self.module = module + + # Style + icon = QtGui.QIcon(resources.get_resource("icon.png")) + self.setWindowIcon(icon) + self.setWindowTitle("Username Settings") + self.setMinimumWidth(self.MIN_WIDTH) + self.setStyleSheet(style.load_stylesheet()) + + self.setWindowFlags( + QtCore.Qt.WindowCloseButtonHint | + QtCore.Qt.WindowMinimizeButtonHint + ) + + self.setLayout(self._main()) + + def show(self, *args, **kwargs): + super().show(*args, **kwargs) + # Move widget to center of active screen on show + screen = QtWidgets.QApplication.desktop().screen() + screen_center = lambda self: ( + screen.rect().center() - self.rect().center() + ) + self.move(screen_center(self)) + + def _main(self): + main_layout = QtWidgets.QVBoxLayout() + + form_layout = QtWidgets.QFormLayout() + form_layout.setContentsMargins(10, 15, 10, 5) + + label_username = QtWidgets.QLabel("Username:") + label_username.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) + label_username.setTextFormat(QtCore.Qt.RichText) + + input_username = QtWidgets.QLineEdit() + input_username.setPlaceholderText( + QtCore.QCoreApplication.translate("main", "e.g. John Smith") + ) + + form_layout.addRow(label_username, input_username) + + btn_save = QtWidgets.QPushButton("Save") + btn_save.clicked.connect(self.click_save) + + btn_cancel = QtWidgets.QPushButton("Cancel") + btn_cancel.clicked.connect(self.close) + + btn_group = QtWidgets.QHBoxLayout() + btn_group.addStretch(1) + btn_group.addWidget(btn_save) + btn_group.addWidget(btn_cancel) + + main_layout.addLayout(form_layout) + main_layout.addLayout(btn_group) + + self.input_username = input_username + + return main_layout + + def set_user(self, username): + self.input_username.setText(username) + + def click_save(self): + # all what should happen - validations and saving into appsdir + username = self.input_username.text() + self.module.save_credentials(username) + self._close_widget() + + def closeEvent(self, event): + event.ignore() + self._close_widget() + + def _close_widget(self): + self.hide()