From cd39250577a55cf75f0ea92b7c0ffd3daa2dc465 Mon Sep 17 00:00:00 2001
From: Ben Souchet <contact@bensouchet.dev>
Date: Thu, 5 Dec 2024 15:50:56 +0100
Subject: [PATCH 1/2] Fix loading issue for host

---
 src/quadpype/lib/__init__.py                  |  2 +
 src/quadpype/lib/user.py                      |  8 ++
 src/quadpype/resources/__init__.py            |  4 +-
 .../tools/settings/settings/categories.py     | 73 ++++++++++++++-----
 4 files changed, 68 insertions(+), 19 deletions(-)

diff --git a/src/quadpype/lib/__init__.py b/src/quadpype/lib/__init__.py
index 1dad2d6165..0381ebb521 100644
--- a/src/quadpype/lib/__init__.py
+++ b/src/quadpype/lib/__init__.py
@@ -134,6 +134,7 @@
     get_user_settings,
     save_user_settings,
     get_user_profile,
+    get_all_user_profiles,
     get_user_workstation_info
 )
 
@@ -271,6 +272,7 @@
     "get_user_settings",
     "save_user_settings",
     "get_user_profile",
+    "get_all_user_profiles",
     "get_user_workstation_info",
 
     "ApplicationLaunchFailed",
diff --git a/src/quadpype/lib/user.py b/src/quadpype/lib/user.py
index 9176c2d59e..3007396000 100644
--- a/src/quadpype/lib/user.py
+++ b/src/quadpype/lib/user.py
@@ -125,6 +125,9 @@ def get_user_profile(self):
 
         return user_profile
 
+    def get_all_user_profiles(self):
+        return self.collection.find({})
+
     def update_user_profile_on_startup(self):
         """Update user profile on startup"""
         user_profile = self.get_user_profile()
@@ -218,6 +221,11 @@ def get_user_profile():
     return _USER_HANDLER.get_user_profile()
 
 
+@require_user_handler
+def get_all_user_profiles():
+    return _USER_HANDLER.get_all_user_profiles()
+
+
 @require_user_handler
 def update_user_profile_on_startup():
     return _USER_HANDLER.update_user_profile_on_startup()
diff --git a/src/quadpype/resources/__init__.py b/src/quadpype/resources/__init__.py
index a0a197d169..629cb35f8f 100644
--- a/src/quadpype/resources/__init__.py
+++ b/src/quadpype/resources/__init__.py
@@ -1,5 +1,5 @@
 import os
-from quadpype.lib.version_utils import is_running_staging, is_running_locally
+from quadpype.lib.version_utils import is_staging_enabled, is_running_locally
 
 RESOURCES_DIR = os.path.dirname(os.path.abspath(__file__))
 
@@ -42,7 +42,7 @@ def get_liberation_font_path(bold=False, italic=False):
 def _get_app_image_variation_name():
     if is_running_locally():
         return "dev"
-    elif is_running_staging():
+    elif is_staging_enabled():
         return "staging"
 
     return "default"
diff --git a/src/quadpype/tools/settings/settings/categories.py b/src/quadpype/tools/settings/settings/categories.py
index d31c0929ee..bf4152c9a9 100644
--- a/src/quadpype/tools/settings/settings/categories.py
+++ b/src/quadpype/tools/settings/settings/categories.py
@@ -3,10 +3,15 @@
 import contextlib
 from abc import abstractmethod
 from enum import Enum
+from datetime import datetime
+
 from qtpy import QtWidgets, QtCore
 import qtawesome
 
-from quadpype.lib import get_quadpype_version
+from quadpype.lib import (
+    get_quadpype_version,
+    get_all_user_profiles
+)
 from quadpype.tools.utils import set_style_property
 from quadpype.settings.entities import (
     GlobalSettingsEntity,
@@ -1238,13 +1243,14 @@ def on_saved(self, saved_tab_widget):
 
 
 class UserManagerWidget(BaseControlPanelWidget):
-    table_column_labels = [
-        "Username",
-        "ID",
-        "Role",
-        "Last Connection",
-        "Last Workstation Name"
-    ]
+    _ws_profile_prefix = "last_workstation_profile/"
+    table_column_data = {
+        _ws_profile_prefix + "username": "Username",
+        "user_id": "ID",
+        "role": "Role",
+        "last_connection_timestamp": "Last Connection",
+        _ws_profile_prefix + "workstation_name": "Last Workstation Name"
+    }
 
     def __init__(self, controller, parent=None):
         super().__init__(controller, parent)
@@ -1276,7 +1282,7 @@ def update_column_widths(self):
             self.table_widget.setColumnWidth(column_index, columns_size[column_index] + additional_width_column)
 
         if additional_width_column:
-            # This means without adding width the sum of column wouldn't take the full width
+            # This means, without adding width, the sum of column wouldn't take the full width
             # Stretching the last column to ensure the row will be fully filled
             last_column_index = columns_count-1
             self.table_widget.horizontalHeader().setSectionResizeMode(last_column_index, QtWidgets.QHeaderView.Stretch)
@@ -1290,14 +1296,47 @@ def add_user_row(self, user_data):
             item.setTextAlignment(QtCore.Qt.AlignCenter)
             self.table_widget.setItem(row_index, column_index, item)
 
+    def _update_user_list(self):
+        # Remove all the rows (if any)
+        self.table_widget.setRowCount(0)
+
+        # Get the user profiles
+        user_profiles = get_all_user_profiles()
+
+        # Populate the table
+        for user_profile in user_profiles:
+            user_data = []
+
+            # Aggregate the user data
+            last_workstation_profile = \
+                user_profile["workstation_profiles"][user_profile["last_workstation_profile_index"]]
+            for user_profile_key in self.table_column_data:
+                if user_profile_key.startswith(self._ws_profile_prefix):
+                    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]
+
+                if isinstance(cell_value, datetime):
+                    # Convert datetime to string (close to the ISO 8601 standard)
+                    cell_value = cell_value.strftime("%Y-%m-%d, %H:%M:%S")
+
+                user_data.append(cell_value)
+
+            self.add_user_row(user_data)
+
+        if user_profiles.retrieved == 0:
+            # No profile found, this should be impossible unless the
+            # collection has been cleared while QuadPype was running
+
+            # Inserting an empty row to avoid issues:
+            user_data = [""] * len(self.table_column_data)
+            self.add_user_row(user_data)
+
     def resizeEvent(self, event):
         super().resizeEvent(event)
         self.update_column_widths()
 
-    def on_cell_clicked(self, row, column):
-        cell_value = self.table_widget.item(row, column).text() if self.table_widget.item(row, column) else ""
-        print(f"Cell clicked at row {row}, column {column}: {cell_value}")
-
     def on_selection_changed(self):
         selected_items = self.table_widget.selectedItems()
         if not selected_items:
@@ -1312,8 +1351,8 @@ def create_ui(self):
         self.table_widget = QtWidgets.QTableWidget(self.content_widget)
 
         self.table_widget.verticalHeader().hide()
-        self.table_widget.setColumnCount(len(self.table_column_labels))
-        self.table_widget.setHorizontalHeaderLabels(self.table_column_labels)
+        self.table_widget.setColumnCount(len(self.table_column_data))
+        self.table_widget.setHorizontalHeaderLabels(self.table_column_data.values())
 
         # Set selection mode to only allow single row selection
         self.table_widget.setSelectionMode(QtWidgets.QTableWidget.SingleSelection)
@@ -1323,7 +1362,7 @@ def create_ui(self):
 
         self.table_widget.setSortingEnabled(True)
 
-        self.add_user_row(["placeholder", "wealthy-warm-kestrel", "administrator", "2024-12-03 13:52", "computer"])
+        self._update_user_list()
 
         # Initially sort by the "Username" column (index 0)
         self.table_widget.sortItems(0)
@@ -1357,7 +1396,7 @@ def _on_path_edited(self, path):
         pass
 
     def _on_refresh_button_pressed(self):
-        pass
+        self._update_user_list()
 
     def _on_footer_button_pressed(self):
         pass

From 9c7c580b74c3d969bf6e62c3425ef4324df674ab Mon Sep 17 00:00:00 2001
From: Ben Souchet <contact@bensouchet.dev>
Date: Thu, 5 Dec 2024 15:51:27 +0100
Subject: [PATCH 2/2] Bump version to 4.0.9

---
 src/quadpype/version.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/quadpype/version.py b/src/quadpype/version.py
index fa11e49470..cf221b3986 100644
--- a/src/quadpype/version.py
+++ b/src/quadpype/version.py
@@ -1,3 +1,3 @@
 # -*- coding: utf-8 -*-
 """File declaring QuadPype version."""
-__version__ = "4.0.8"
+__version__ = "4.0.9"