Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
BenSouchet committed Dec 18, 2024
2 parents e86de2e + fb29750 commit 54a1172
Show file tree
Hide file tree
Showing 14 changed files with 173 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/quadpype/hosts/nuke/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -2598,7 +2598,7 @@ def make_format_string(self, **kwargs):

def set_context_settings(self):
os.environ["QUADPYPE_NUKE_SKIP_SAVE_EVENT"] = "True"
if get_project_settings(Context.project_name)["nuke"].get("set_resolution_startup", True):
if get_project_settings(Context.project_name)["nuke"]["general"].get("set_resolution_startup", True):
self.reset_resolution()
self.reset_frame_range_handles()
# add colorspace menu item
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
cmake_minimum_required(VERSION 3.17)

project(QuadPypePlugin C CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(IP_ENABLE_UNICODE OFF)
set(IP_ENABLE_DOCTEST OFF)

set(CMAKE_CONFIGURATION_TYPES "Release" CACHE STRING "" FORCE)

if(MSVC)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
Expand All @@ -19,7 +24,7 @@ if(MSVC)
endif()
endif()


set(BOOST_ROOT "C:/Boost")
set(OPENSSL_INCLUDE "C:/Program Files/OpenSSL-Win64/include")
set(OPENSSL_LIB_DIR "C:/Program Files/OpenSSL-Win64/lib")
set(WEBSOCKETPP_INCLUDE "./dependencies/websocketpp-0.8.2/")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ Edit the CMakeLists.txt to edit:

Then, follow the steps from [this tutorial](https://github.com/BenSouchet/compile-tvpaint-plugin).

The compilation lines, after editing the `CmakeLists.txt`, are:

```
cmake -G "Visual Studio 17 2022" -A Win32 -S . -B "build32"
cmake -G "Visual Studio 17 2022" -A x64 -S . -B "build64"
cmake --build build32 --config Release
cmake --build build64 --config Release
```

To ensure the `./dependencies/` folder is properly found, execute the cmake command from the `plugin_code` directory (use `cd` to navigate to that location before execution the commands).

## TODO
Expand Down
Binary file not shown.
Binary file not shown.
25 changes: 25 additions & 0 deletions src/quadpype/lib/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class UserHandler(ABC):
"last_connection_timestamp": datetime.now(timezone.utc),
"last_workstation_profile_index": 0,
"workstation_profiles": [],
"tracker_logins": {},
"settings": {}
}

Expand Down Expand Up @@ -64,6 +65,11 @@ def update_user_profile_on_startup(self):
"""Update the user profile on startup."""
pass

@abstractmethod
def set_tracker_login_to_user_profile(self, tracker_name, login_value):
"""Set the user login for a specific tracker in his profile."""
pass


class MongoUserHandler(UserHandler):
"""Settings handler that use mongo for store and load user info & settings.
Expand Down Expand Up @@ -154,6 +160,20 @@ def update_user_profile_on_startup(self):

return user_profile

def set_tracker_login_to_user_profile(self, tracker_name, login_value):
user_profile = self.get_user_profile()

if "tracker_logins" not in user_profile:
# Ensure the dict exists in the user profile
user_profile["tracker_logins"] = {}

user_profile["tracker_logins"][tracker_name] = login_value

self.collection.replace_one(
{"user_id": self.user_id},
user_profile, upsert=True
)

def save_user_settings(self, data):
"""Save user settings.
Expand Down Expand Up @@ -232,6 +252,11 @@ def update_user_profile_on_startup():
return _USER_HANDLER.update_user_profile_on_startup()


@require_user_handler
def set_tracker_login_to_user_profile(tracker_name, login_value):
return _USER_HANDLER.set_tracker_login_to_user_profile(tracker_name, login_value)


def _create_user_id(registry=None):
"""Create a user identifier."""
from coolname import generate_slug
Expand Down
26 changes: 13 additions & 13 deletions src/quadpype/modules/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1141,28 +1141,28 @@ class name and value is time delta of it's processing.
class TrayModulesManager(ModulesManager):
# Define order of modules in menu
modules_menu_order = (
# Menu ------------------------------------------
# QuadPype: STUDIO_NAME
# USERNAME
# VERSION
# QuadPype : STUDIO_NAME
# WORKSTATION USERNAME
# QUADPYPE VERSION
"ftrack", # ftrack
"kitsu", # Kitsu
"muster", # Muster
"launcher_tool", # Launcher
"avalon", # Loader
"tray_publisher", # Publisher
"standalone_publisher", # Publisher (legacy)
"clockify", # Clockify
"sync_server", # Sync Queue
# More Tools Submenu -----------------------------
"log_viewer", # Show Logs
"python_interpreter", # Console
# Admin Submenu ----------------------------------
"project_manager", # Project Manager (beta)
# User Settings ----------------------------------
"user_settings", # User Settings
# Services Submenu -------------------------------
# Submenu : More Tools --------------------------
"log_viewer", # Show Logs
"python_interpreter", # Console
# Admin Submenu (Will be merged in the Studio Control Panel)
"project_manager", # Project Manager (beta)
"control_panel", # Studio Control Panel
"user_settings", # User Settings
# Submenu : Services ----------------------------
"kitsu", # Kitsu
"event_handler", # Events Handler
"webserver" # Web Server
)

def __init__(self):
Expand Down
25 changes: 23 additions & 2 deletions src/quadpype/modules/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,25 @@ def label(self):
@staticmethod
def services_submenu(tray_menu):
if ITrayService._services_submenu is None:
from qtpy import QtWidgets
from qtpy import QtWidgets, QtCore

class SubMenu(QtWidgets.QMenu):
# Class that did not close the menu and submenu if
# the action isn't connected to function

def __init__(self, title: str, parent=None):
super().__init__(title, parent)
self.installEventFilter(self)

def mouseReleaseEvent(self, event):
# Get the active action (the one under the cursor)
action = self.activeAction()

services_submenu = QtWidgets.QMenu("Services", tray_menu)
if action and action.isEnabled():
if action.receivers(QtCore.SIGNAL("triggered()")) > 0:
super().mouseReleaseEvent(event)

services_submenu = SubMenu("Services", tray_menu)
services_submenu.menuAction().setVisible(False)
ITrayService._services_submenu = services_submenu
return ITrayService._services_submenu
Expand Down Expand Up @@ -348,6 +364,11 @@ def tray_menu(self, tray_menu):

self.add_service_action(action)

if hasattr(self, "on_action_trigger") and callable(self.on_action_trigger):
action.triggered.connect(self.on_action_trigger)
else:
action.triggered.disconnect()

self.set_service_running_icon()

def set_service_running_icon(self):
Expand Down
9 changes: 6 additions & 3 deletions src/quadpype/modules/kitsu/kitsu_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
click_wrap,
QuadPypeModule,
IPluginPaths,
ITrayAction,
ITrayService,
)


class KitsuModule(QuadPypeModule, IPluginPaths, ITrayAction):
class KitsuModule(QuadPypeModule, IPluginPaths, ITrayService):
"""Kitsu module class."""

label = "Kitsu Connect"
label = "Kitsu"
name = "kitsu"

def initialize(self, settings):
Expand Down Expand Up @@ -62,6 +62,9 @@ def tray_start(self):
else:
self.show_dialog()

def tray_exit(self):
return

def get_global_environments(self):
"""Kitsu's global environments."""
return {"KITSU_SERVER": self.server_url}
Expand Down
9 changes: 5 additions & 4 deletions src/quadpype/modules/kitsu/kitsu_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
)

from quadpype.tools.utils import PressHoverButton
from quadpype.lib.user import set_tracker_login_to_user_profile


class KitsuPasswordDialog(QtWidgets.QDialog):
Expand All @@ -33,7 +34,6 @@ def __init__(self, parent=None):

global_settings = get_global_settings()
user_login, user_pwd = load_credentials()
remembered = bool(user_login or user_pwd)

self._final_result = None
self._connectable = bool(
Expand All @@ -58,7 +58,7 @@ def __init__(self, parent=None):

login_input = QtWidgets.QLineEdit(
login_widget,
text=user_login if remembered else None,
text=user_login,
)
login_input.setPlaceholderText("Your Kitsu account login...")

Expand All @@ -74,7 +74,7 @@ def __init__(self, parent=None):

password_input = QtWidgets.QLineEdit(
password_widget,
text=user_pwd if remembered else None,
text=user_pwd,
)
password_input.setPlaceholderText("Your password...")
password_input.setEchoMode(QtWidgets.QLineEdit.Password)
Expand All @@ -100,7 +100,7 @@ def __init__(self, parent=None):

remember_checkbox = QtWidgets.QCheckBox("Remember", buttons_widget)
remember_checkbox.setObjectName("RememberCheckbox")
remember_checkbox.setChecked(remembered)
remember_checkbox.setChecked(True)

ok_btn = QtWidgets.QPushButton("Ok", buttons_widget)
cancel_btn = QtWidgets.QPushButton("Cancel", buttons_widget)
Expand Down Expand Up @@ -170,6 +170,7 @@ def _on_ok_click(self):
# Remember password cases
if remember:
save_credentials(login_value, pwd_value)
set_tracker_login_to_user_profile("kitsu", login_value)
else:
# Clear user settings
clear_credentials()
Expand Down
6 changes: 5 additions & 1 deletion src/quadpype/settings/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class SettingsStateInfo:
To create current machine and time information use 'create_new' method.
"""

timestamp_format = "%Y-%m-%d %H:%M:%S.%f"
timestamp_format = "%Y-%m-%d %H:%M:%S.%f%z"

def __init__(
self,
Expand All @@ -70,6 +70,10 @@ def __init__(

timestamp_obj = None
if timestamp:
if "+" not in timestamp:
# Ensure an UTC offset is set
timestamp += "+0000"

timestamp_obj = datetime.strptime(
timestamp, self.timestamp_format
)
Expand Down
67 changes: 57 additions & 10 deletions src/quadpype/tools/settings/settings/categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
get_user_id
)
from quadpype.tools.utils import set_style_property

from quadpype.settings import (
ADDONS_SETTINGS_KEY,
get_global_settings,
)
from quadpype.settings.entities import (
GlobalSettingsEntity,
ProjectSettingsEntity,
Expand Down Expand Up @@ -430,6 +435,10 @@ def __init__(self, controller, parent=None):

self.create_ui()

@property
def current_version(self):
return self._current_version

@staticmethod
def create_ui_for_entity(category_widget, entity, entity_widget):
args = (category_widget, entity, entity_widget)
Expand Down Expand Up @@ -1632,14 +1641,16 @@ def __lt__(self, other):

class UserManagerWidget(BaseControlPanelWidget):
_ws_profile_prefix = "last_workstation_profile/"
table_column_data = {
"_is_online": "Online",
_ws_profile_prefix + "username": "Username",
"user_id": "ID",
"role": "Role",
"last_connection_timestamp": "Last Connection",
_ws_profile_prefix + "workstation_name": "Last Workstation Name"
}
_tracker_login_prefix = "tracker_logins/"
_table_column_data = [
("_is_online", "Online"),
(_ws_profile_prefix + "username", "Username"),
("user_id", "ID"),
("role", "Role"),
("_tracker_logins", "Generated in constructor"),
("last_connection_timestamp", "Last Connection"),
(_ws_profile_prefix + "workstation_name", "Last Workstation Name")
]

def __init__(self, controller, parent=None):
super().__init__(controller, parent)
Expand All @@ -1655,7 +1666,6 @@ def __init__(self, controller, parent=None):
self._selected_user_id = None
self._current_sort_column = 1
self._current_sort_order = QtCore.Qt.SortOrder.AscendingOrder
self._column_count = len(self.table_column_data.keys())

self._spin_icon = resources.get_resource("icons", "spin.svg")

Expand All @@ -1671,8 +1681,38 @@ def __init__(self, controller, parent=None):
self._check_users_online_thread = CheckUsersOnlineThread(self)
self._check_users_online_thread.apply_online_icon_to_user.connect(self._update_online_icon_for_users)

# Generate the column template
self.table_column_data = {}
for (column_id, column_display_name) in self._table_column_data:
if column_id == "_tracker_logins":
# Handle special column
active_trackers = self._get_active_trackers()
for tracker_name in active_trackers:
tracker_column_id = self._tracker_login_prefix + tracker_name
self.table_column_data[tracker_column_id] = f"{tracker_name.capitalize()} Login"

continue # To skip adding this placeholder column_id

self.table_column_data[column_id] = column_display_name

self._column_count = len(self.table_column_data.keys())

self.create_ui()

@staticmethod
def _get_active_trackers():
# Currently no proper function to do that in a lib module
active_trackers = []
global_settings = get_global_settings()

tracker_names = ["ftrack", "kitsu"]
for tracker_name in tracker_names:
if global_settings[ADDONS_SETTINGS_KEY][tracker_name]["enabled"] and \
global_settings[ADDONS_SETTINGS_KEY][tracker_name]["server"]:
active_trackers.append(tracker_name)

return active_trackers

@property
def current_user_id(self):
return self._curr_user_id
Expand Down Expand Up @@ -1849,7 +1889,14 @@ def _update_user_list(self):
user_profile_key = user_profile_key.removeprefix(self._ws_profile_prefix)
cell_value = last_workstation_profile[user_profile_key]
else:
cell_value = user_profile[user_profile_key]
splitted = user_profile_key.split("/")
cell_value = user_profile
for curr_key in splitted:
if curr_key not in cell_value:
# Protection to avoid crash if a key isn't in the user profile
cell_value = ""
break
cell_value = cell_value[curr_key]

if isinstance(cell_value, datetime):
# Convert datetime to string (close to the ISO 8601 standard)
Expand Down
Loading

0 comments on commit 54a1172

Please sign in to comment.