From 181c1faf002b8b8953b3fa76585c95d84a4a206e Mon Sep 17 00:00:00 2001 From: David Lai Date: Sat, 11 Sep 2021 17:26:38 +0800 Subject: [PATCH 01/21] add project archive confirm setting attribute --- openpype/settings/defaults/project_anatomy/attributes.json | 3 ++- .../projects_schema/schemas/schema_anatomy_attributes.json | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_anatomy/attributes.json b/openpype/settings/defaults/project_anatomy/attributes.json index 387e12bcea..77e6d5e07a 100644 --- a/openpype/settings/defaults/project_anatomy/attributes.json +++ b/openpype/settings/defaults/project_anatomy/attributes.json @@ -22,5 +22,6 @@ "aftereffects/2021", "unreal/4-26" ], - "tools_env": [] + "tools_env": [], + "archive_confirm": "" } \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json index 7391108a02..dc54fa598e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json @@ -69,6 +69,12 @@ "type": "tools-enum", "key": "tools_env", "label": "Tools" + }, + { + "type": "text", + "key": "archive_confirm", + "label": "Archive Project", + "placeholder": "Input project name to confirm archiving." } ] } From 394b714496e27aff5b7effd28a8950e749a9a0e8 Mon Sep 17 00:00:00 2001 From: David Lai Date: Sat, 11 Sep 2021 17:44:01 +0800 Subject: [PATCH 02/21] Launcher ignore archived project Based on avalon-core bfce450f --- openpype/tools/launcher/models.py | 16 +--------------- openpype/tools/launcher/window.py | 1 - 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/openpype/tools/launcher/models.py b/openpype/tools/launcher/models.py index 4988829c11..bbd419df1c 100644 --- a/openpype/tools/launcher/models.py +++ b/openpype/tools/launcher/models.py @@ -326,8 +326,6 @@ class ProjectModel(QtGui.QStandardItemModel): super(ProjectModel, self).__init__(parent=parent) self.dbcon = dbcon - - self.hide_invisible = False self.project_icon = qtawesome.icon("fa.map", color="white") self._project_names = set() @@ -380,16 +378,4 @@ class ProjectModel(QtGui.QStandardItemModel): self.invisibleRootItem().insertRows(row, items) def get_projects(self): - project_docs = [] - - for project_doc in sorted( - self.dbcon.projects(), key=lambda x: x["name"] - ): - if ( - self.hide_invisible - and not project_doc["data"].get("visible", True) - ): - continue - project_docs.append(project_doc) - - return project_docs + return sorted(self.dbcon.projects(no_archived=True), key=lambda x: x["name"]) diff --git a/openpype/tools/launcher/window.py b/openpype/tools/launcher/window.py index bd37a9b89c..4331892e94 100644 --- a/openpype/tools/launcher/window.py +++ b/openpype/tools/launcher/window.py @@ -271,7 +271,6 @@ class LauncherWindow(QtWidgets.QDialog): ) project_model = ProjectModel(self.dbcon) - project_model.hide_invisible = True project_handler = ProjectHandler(self.dbcon, project_model) project_panel = ProjectsPanel(project_handler) From 902334d384a9c6fe2fb4a1076298a5358028420d Mon Sep 17 00:00:00 2001 From: David Lai Date: Sat, 11 Sep 2021 17:44:22 +0800 Subject: [PATCH 03/21] ProjectManager ignore archived project Based on avalon-core bfce450f --- .../project_manager/project_manager/model.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/openpype/tools/project_manager/project_manager/model.py b/openpype/tools/project_manager/project_manager/model.py index 7ee43a6b61..e31dd2ccfe 100644 --- a/openpype/tools/project_manager/project_manager/model.py +++ b/openpype/tools/project_manager/project_manager/model.py @@ -43,18 +43,14 @@ class ProjectModel(QtGui.QStandardItemModel): none_project.setData(None) project_items.append(none_project) - database = self.dbcon.database project_names = set() - for project_name in database.collection_names(): - # Each collection will have exactly one project document - project_doc = database[project_name].find_one( - {"type": "project"}, - {"name": 1} - ) - if not project_doc: - continue - project_name = project_doc.get("name") + for doc in sorted( + self.dbcon.projects(projection={"name": 1}, no_archived=True), + key=lambda x: x["name"] + ): + + project_name = doc.get("name") if project_name: project_names.add(project_name) project_items.append(QtGui.QStandardItem(project_name)) From 07e248da8912092779b1ac9a96a3c2d7bb9a6a79 Mon Sep 17 00:00:00 2001 From: David Lai Date: Sat, 11 Sep 2021 17:44:57 +0800 Subject: [PATCH 04/21] StandalonePublisher ignore archived project Based on avalon-core bfce450f --- openpype/tools/standalonepublish/widgets/widget_asset.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openpype/tools/standalonepublish/widgets/widget_asset.py b/openpype/tools/standalonepublish/widgets/widget_asset.py index c39d71b055..e4fed1b9a7 100644 --- a/openpype/tools/standalonepublish/widgets/widget_asset.py +++ b/openpype/tools/standalonepublish/widgets/widget_asset.py @@ -273,8 +273,10 @@ class AssetWidget(QtWidgets.QWidget): def _set_projects(self): project_names = list() - for project in self.dbcon.projects(): - project_name = project.get("name") + + for doc in self.dbcon.projects(projection={"name": 1}, no_archived=True): + + project_name = doc.get("name") if project_name: project_names.append(project_name) @@ -299,7 +301,8 @@ class AssetWidget(QtWidgets.QWidget): def on_project_change(self): projects = list() - for project in self.dbcon.projects(): + + for project in self.dbcon.projects(projection={"name": 1}, no_archived=True): projects.append(project['name']) project_name = self.combo_projects.currentText() if project_name in projects: From 1ec69c37ceb0467947c79fc5218a8d422e93d629 Mon Sep 17 00:00:00 2001 From: David Lai Date: Sat, 11 Sep 2021 17:45:32 +0800 Subject: [PATCH 05/21] Settings ignore archived project Based on avalon-core bfce450f --- .../settings/local_settings/projects_widget.py | 2 +- openpype/tools/settings/settings/widgets.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/openpype/tools/settings/local_settings/projects_widget.py b/openpype/tools/settings/local_settings/projects_widget.py index a48c504d59..7d19c37bdf 100644 --- a/openpype/tools/settings/local_settings/projects_widget.py +++ b/openpype/tools/settings/local_settings/projects_widget.py @@ -809,7 +809,7 @@ class ProjectSettingsWidget(QtWidgets.QWidget): self.modules_manager = modules_manager - projects_widget = _ProjectListWidget(self) + projects_widget = _ProjectListWidget(self, no_archived=True) roos_site_widget = RootSiteWidget( modules_manager, project_settings, self ) diff --git a/openpype/tools/settings/settings/widgets.py b/openpype/tools/settings/settings/widgets.py index 2caf8c33ba..dd95eeb100 100644 --- a/openpype/tools/settings/settings/widgets.py +++ b/openpype/tools/settings/settings/widgets.py @@ -616,7 +616,7 @@ class ProjectListWidget(QtWidgets.QWidget): default = "< Default >" project_changed = QtCore.Signal() - def __init__(self, parent): + def __init__(self, parent, no_archived=False): self._parent = parent self.current_project = None @@ -645,6 +645,7 @@ class ProjectListWidget(QtWidgets.QWidget): self.project_list = project_list self.dbcon = None + self._no_archived = no_archived def on_item_clicked(self, new_index): new_project_name = new_index.data(QtCore.Qt.DisplayRole) @@ -731,14 +732,13 @@ class ProjectListWidget(QtWidgets.QWidget): self.current_project = None if self.dbcon: - database = self.dbcon.database - for project_name in database.collection_names(): - project_doc = database[project_name].find_one( - {"type": "project"}, - {"name": 1} - ) - if project_doc: - items.append(project_doc["name"]) + for doc in sorted( + self.dbcon.projects(projection={"name": 1}, + no_archived=self._no_archived), + key=lambda x: x["name"] + ): + items.append(doc["name"]) + for item in items: model.appendRow(QtGui.QStandardItem(item)) From 04d4afa9579d6e14e98087832213598439fe146e Mon Sep 17 00:00:00 2001 From: David Lai Date: Sun, 12 Sep 2021 19:09:11 +0800 Subject: [PATCH 06/21] evaluate archive flag on saving anatomy --- openpype/settings/entities/root_entities.py | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/openpype/settings/entities/root_entities.py b/openpype/settings/entities/root_entities.py index 05d20ee60b..e0a9ecdb35 100644 --- a/openpype/settings/entities/root_entities.py +++ b/openpype/settings/entities/root_entities.py @@ -755,6 +755,31 @@ class ProjectSettings(RootEntity): """ return DEFAULTS_DIR + def settings_value(self): + output = super(ProjectSettings, self).settings_value() + + anatomy = output.get(PROJECT_ANATOMY_KEY) or {} + + # Evaluate project archiving flag + # + archive_confirm = anatomy.get("attributes", {}).get("archive_confirm") + if archive_confirm: + # set flag + if archive_confirm == self.project_name: + self.log.debug( + "Project archiving." + ) + anatomy["attributes"]["archived"] = True + + else: + self.log.debug( + "Project archiving confirmation string not matched." + ) + anatomy["attributes"]["archive_confirm"] = "" + anatomy["attributes"]["archived"] = False + + return output + def _save_studio_values(self): settings_value = self.settings_value() From f817740a92c43df0c43f4d4d5c5d8e301b97c2ea Mon Sep 17 00:00:00 2001 From: David Lai Date: Sun, 12 Sep 2021 19:13:27 +0800 Subject: [PATCH 07/21] add archived sorting/filtering in Studio Settings --- openpype/tools/settings/settings/widgets.py | 103 +++++++++++++++++--- 1 file changed, 91 insertions(+), 12 deletions(-) diff --git a/openpype/tools/settings/settings/widgets.py b/openpype/tools/settings/settings/widgets.py index dd95eeb100..6dee90daa9 100644 --- a/openpype/tools/settings/settings/widgets.py +++ b/openpype/tools/settings/settings/widgets.py @@ -612,10 +612,34 @@ class ProjectListView(QtWidgets.QListView): super(ProjectListView, self).mouseReleaseEvent(event) +class ProjectListSortFilterProxy(QtCore.QSortFilterProxyModel): + + def __init__(self, *args, **kwargs): + super(ProjectListSortFilterProxy, self).__init__(*args, **kwargs) + self._enable_filter = True + + def filterAcceptsRow(self, source_row, source_parent): + if not self._enable_filter: + return True + + index = self.sourceModel().index(source_row, 0, source_parent) + return bool(index.data(self.filterRole())) + + def is_filter_enabled(self): + return self._enable_filter + + def set_filter_enabled(self, value): + self._enable_filter = value + self.invalidateFilter() + + class ProjectListWidget(QtWidgets.QWidget): default = "< Default >" project_changed = QtCore.Signal() + ProjectSortRole = QtCore.Qt.UserRole + 10 + ProjectFilterRole = QtCore.Qt.UserRole + 11 + def __init__(self, parent, no_archived=False): self._parent = parent @@ -625,8 +649,17 @@ class ProjectListWidget(QtWidgets.QWidget): self.setObjectName("ProjectListWidget") label_widget = QtWidgets.QLabel("Projects") + project_list = ProjectListView(self) - project_list.setModel(QtGui.QStandardItemModel()) + project_model = QtGui.QStandardItemModel() + project_proxy = ProjectListSortFilterProxy() + + project_proxy.setFilterRole(self.ProjectFilterRole) + project_proxy.setSortRole(self.ProjectSortRole) + project_proxy.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive) + + project_proxy.setSourceModel(project_model) + project_list.setModel(project_proxy) # Do not allow editing project_list.setEditTriggers( @@ -640,9 +673,24 @@ class ProjectListWidget(QtWidgets.QWidget): layout.addWidget(label_widget, 0) layout.addWidget(project_list, 1) + if no_archived: + archived_chk = None + else: + archived_chk = QtWidgets.QCheckBox(" Show Archived Project ") + archived_chk.setChecked(not project_proxy.is_filter_enabled()) + + layout.addSpacing(5) + layout.addWidget(archived_chk, 0) + layout.addSpacing(5) + + archived_chk.stateChanged.connect(self.on_archive_vis_changed) + project_list.left_mouse_released_at.connect(self.on_item_clicked) self.project_list = project_list + self.project_proxy = project_proxy + self.project_model = project_model + self.archived_chk = archived_chk self.dbcon = None self._no_archived = no_archived @@ -680,6 +728,14 @@ class ProjectListWidget(QtWidgets.QWidget): else: self.select_project(self.current_project) + def on_archive_vis_changed(self): + if self.archived_chk is None: + # should not happen. + return + + enable_filter = not self.archived_chk.isChecked() + self.project_proxy.set_filter_enabled(enable_filter) + def validate_context_change(self): return not self._parent.entity.has_unsaved_changes @@ -692,12 +748,16 @@ class ProjectListWidget(QtWidgets.QWidget): self.select_project(self.default) def select_project(self, project_name): - model = self.project_list.model() + model = self.project_model + proxy = self.project_proxy + found_items = model.findItems(project_name) if not found_items: found_items = model.findItems(self.default) index = model.indexFromItem(found_items[0]) + index = proxy.mapFromSource(index) + self.project_list.selectionModel().clear() self.project_list.selectionModel().setCurrentIndex( index, QtCore.QItemSelectionModel.SelectionFlag.SelectCurrent @@ -709,10 +769,10 @@ class ProjectListWidget(QtWidgets.QWidget): selected_project = index.data(QtCore.Qt.DisplayRole) break - model = self.project_list.model() + model = self.project_model model.clear() - items = [self.default] + items = [(self.default, None)] mongo_url = os.environ["OPENPYPE_MONGO"] @@ -732,15 +792,34 @@ class ProjectListWidget(QtWidgets.QWidget): self.current_project = None if self.dbcon: - for doc in sorted( - self.dbcon.projects(projection={"name": 1}, - no_archived=self._no_archived), - key=lambda x: x["name"] - ): - items.append(doc["name"]) - for item in items: - model.appendRow(QtGui.QStandardItem(item)) + for doc in self.dbcon.projects( + projection={"name": 1, "data.archived": 1}, + no_archived=self._no_archived + ): + items.append( + (doc["name"], doc.get("data", {}).get("archived")) + ) + + for project_name, is_archived in items: + visible = not is_archived + + row = QtGui.QStandardItem(project_name) + row.setData(visible, self.ProjectFilterRole) + + if is_archived: + row.setData("~" + project_name, self.ProjectSortRole) + + font = row.font() + font.setItalic(True) + row.setFont(font) + + else: + row.setData(project_name, self.ProjectSortRole) + + model.appendRow(row) + + self.project_proxy.sort(0) self.select_project(selected_project) From 02937e308f8346193df16637f84d0bd3a8ad60ce Mon Sep 17 00:00:00 2001 From: David Lai Date: Sun, 12 Sep 2021 19:33:43 +0800 Subject: [PATCH 08/21] SyncServer ignore archived project --- .../modules/default_modules/sync_server/tray/widgets.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openpype/modules/default_modules/sync_server/tray/widgets.py b/openpype/modules/default_modules/sync_server/tray/widgets.py index c9160733a0..1737b2e0c6 100644 --- a/openpype/modules/default_modules/sync_server/tray/widgets.py +++ b/openpype/modules/default_modules/sync_server/tray/widgets.py @@ -34,7 +34,7 @@ class SyncProjectListWidget(ProjectListWidget): """ def __init__(self, sync_server, parent): - super(SyncProjectListWidget, self).__init__(parent) + super(SyncProjectListWidget, self).__init__(parent, no_archived=True) self.sync_server = sync_server self.project_list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.project_list.customContextMenuRequested.connect( @@ -49,7 +49,7 @@ class SyncProjectListWidget(ProjectListWidget): return True def refresh(self): - model = self.project_list.model() + model = self.project_model model.clear() project_name = None @@ -70,8 +70,7 @@ class SyncProjectListWidget(ProjectListWidget): QtCore.Qt.DisplayRole ) if not self.current_project: - self.current_project = self.project_list.model().item(0). \ - data(QtCore.Qt.DisplayRole) + self.current_project = model.item(0).data(QtCore.Qt.DisplayRole) if project_name: self.local_site = self.sync_server.get_active_site(project_name) From c234cb907993282c00bff9a31083a7d7b1b5ab64 Mon Sep 17 00:00:00 2001 From: David Lai Date: Sun, 12 Sep 2021 23:21:10 +0800 Subject: [PATCH 09/21] register 'archived' to project anatomy schema So the settings can recognize and won't pop warnings --- openpype/settings/defaults/project_anatomy/attributes.json | 3 ++- .../projects_schema/schemas/schema_anatomy_attributes.json | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_anatomy/attributes.json b/openpype/settings/defaults/project_anatomy/attributes.json index 77e6d5e07a..ac91622726 100644 --- a/openpype/settings/defaults/project_anatomy/attributes.json +++ b/openpype/settings/defaults/project_anatomy/attributes.json @@ -23,5 +23,6 @@ "unreal/4-26" ], "tools_env": [], - "archive_confirm": "" + "archive_confirm": "", + "archived": false } \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json index dc54fa598e..f70ab2fc5f 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json @@ -75,6 +75,11 @@ "key": "archive_confirm", "label": "Archive Project", "placeholder": "Input project name to confirm archiving." + }, + { + "type": "boolean", + "key": "archived", + "label": "Is Archived" } ] } From 662e74816b16e108d80b80d55bc726c0859df056 Mon Sep 17 00:00:00 2001 From: David Lai Date: Sun, 12 Sep 2021 23:22:42 +0800 Subject: [PATCH 10/21] reset 'archived' to False if no confirmation string --- openpype/settings/entities/root_entities.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/settings/entities/root_entities.py b/openpype/settings/entities/root_entities.py index e0a9ecdb35..5701b60098 100644 --- a/openpype/settings/entities/root_entities.py +++ b/openpype/settings/entities/root_entities.py @@ -778,6 +778,10 @@ class ProjectSettings(RootEntity): anatomy["attributes"]["archive_confirm"] = "" anatomy["attributes"]["archived"] = False + else: + if anatomy and "attributes" in anatomy: + anatomy["attributes"]["archived"] = False + return output def _save_studio_values(self): From 921fc00e8f8471d00bb14d571ea77c0d232492b4 Mon Sep 17 00:00:00 2001 From: David Lai Date: Sun, 12 Sep 2021 23:26:53 +0800 Subject: [PATCH 11/21] keep selected project in view when being archived --- openpype/tools/settings/settings/widgets.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openpype/tools/settings/settings/widgets.py b/openpype/tools/settings/settings/widgets.py index 6dee90daa9..d1a8bd8958 100644 --- a/openpype/tools/settings/settings/widgets.py +++ b/openpype/tools/settings/settings/widgets.py @@ -623,7 +623,10 @@ class ProjectListSortFilterProxy(QtCore.QSortFilterProxyModel): return True index = self.sourceModel().index(source_row, 0, source_parent) - return bool(index.data(self.filterRole())) + is_active = bool(index.data(self.filterRole())) + is_selected = bool(index.data(ProjectListWidget.ProjectSelectedRole)) + + return is_active or is_selected def is_filter_enabled(self): return self._enable_filter @@ -639,6 +642,7 @@ class ProjectListWidget(QtWidgets.QWidget): ProjectSortRole = QtCore.Qt.UserRole + 10 ProjectFilterRole = QtCore.Qt.UserRole + 11 + ProjectSelectedRole = QtCore.Qt.UserRole + 12 def __init__(self, parent, no_archived=False): self._parent = parent @@ -756,6 +760,8 @@ class ProjectListWidget(QtWidgets.QWidget): found_items = model.findItems(self.default) index = model.indexFromItem(found_items[0]) + model.setData(index, True, self.ProjectSelectedRole) + index = proxy.mapFromSource(index) self.project_list.selectionModel().clear() @@ -806,6 +812,7 @@ class ProjectListWidget(QtWidgets.QWidget): row = QtGui.QStandardItem(project_name) row.setData(visible, self.ProjectFilterRole) + row.setData(False, self.ProjectSelectedRole) if is_archived: row.setData("~" + project_name, self.ProjectSortRole) From 453a813ec1ab2067927fc9ddc1eb4acb37f0b607 Mon Sep 17 00:00:00 2001 From: David Lai Date: Mon, 13 Sep 2021 00:03:12 +0800 Subject: [PATCH 12/21] fix linter --- openpype/tools/launcher/models.py | 3 ++- openpype/tools/standalonepublish/widgets/widget_asset.py | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/openpype/tools/launcher/models.py b/openpype/tools/launcher/models.py index bbd419df1c..53e2c19a3d 100644 --- a/openpype/tools/launcher/models.py +++ b/openpype/tools/launcher/models.py @@ -378,4 +378,5 @@ class ProjectModel(QtGui.QStandardItemModel): self.invisibleRootItem().insertRows(row, items) def get_projects(self): - return sorted(self.dbcon.projects(no_archived=True), key=lambda x: x["name"]) + return sorted(self.dbcon.projects(no_archived=True), + key=lambda x: x["name"]) diff --git a/openpype/tools/standalonepublish/widgets/widget_asset.py b/openpype/tools/standalonepublish/widgets/widget_asset.py index e4fed1b9a7..8ee09d2435 100644 --- a/openpype/tools/standalonepublish/widgets/widget_asset.py +++ b/openpype/tools/standalonepublish/widgets/widget_asset.py @@ -274,7 +274,8 @@ class AssetWidget(QtWidgets.QWidget): def _set_projects(self): project_names = list() - for doc in self.dbcon.projects(projection={"name": 1}, no_archived=True): + for doc in self.dbcon.projects(projection={"name": 1}, + no_archived=True): project_name = doc.get("name") if project_name: @@ -302,7 +303,8 @@ class AssetWidget(QtWidgets.QWidget): def on_project_change(self): projects = list() - for project in self.dbcon.projects(projection={"name": 1}, no_archived=True): + for project in self.dbcon.projects(projection={"name": 1}, + no_archived=True): projects.append(project['name']) project_name = self.combo_projects.currentText() if project_name in projects: From b0d166fe09b5f1a650ed476de43142cda243d9bd Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 15 Sep 2021 10:03:05 +0800 Subject: [PATCH 13/21] reverse project 'archive' to 'active' --- .../sync_server/tray/widgets.py | 2 +- .../defaults/project_anatomy/attributes.json | 2 +- .../schemas/schema_anatomy_attributes.json | 4 +-- openpype/tools/launcher/models.py | 2 +- .../project_manager/project_manager/model.py | 2 +- .../local_settings/projects_widget.py | 2 +- openpype/tools/settings/settings/widgets.py | 29 +++++++++---------- .../standalonepublish/widgets/widget_asset.py | 4 +-- 8 files changed, 23 insertions(+), 24 deletions(-) diff --git a/openpype/modules/default_modules/sync_server/tray/widgets.py b/openpype/modules/default_modules/sync_server/tray/widgets.py index 1737b2e0c6..13389ed36c 100644 --- a/openpype/modules/default_modules/sync_server/tray/widgets.py +++ b/openpype/modules/default_modules/sync_server/tray/widgets.py @@ -34,7 +34,7 @@ class SyncProjectListWidget(ProjectListWidget): """ def __init__(self, sync_server, parent): - super(SyncProjectListWidget, self).__init__(parent, no_archived=True) + super(SyncProjectListWidget, self).__init__(parent, only_active=True) self.sync_server = sync_server self.project_list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.project_list.customContextMenuRequested.connect( diff --git a/openpype/settings/defaults/project_anatomy/attributes.json b/openpype/settings/defaults/project_anatomy/attributes.json index ac91622726..128d5c14ca 100644 --- a/openpype/settings/defaults/project_anatomy/attributes.json +++ b/openpype/settings/defaults/project_anatomy/attributes.json @@ -24,5 +24,5 @@ ], "tools_env": [], "archive_confirm": "", - "archived": false + "active": true } \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json index f70ab2fc5f..fdae566655 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json @@ -78,8 +78,8 @@ }, { "type": "boolean", - "key": "archived", - "label": "Is Archived" + "key": "active", + "label": "Is Project Active" } ] } diff --git a/openpype/tools/launcher/models.py b/openpype/tools/launcher/models.py index 53e2c19a3d..f87871409e 100644 --- a/openpype/tools/launcher/models.py +++ b/openpype/tools/launcher/models.py @@ -378,5 +378,5 @@ class ProjectModel(QtGui.QStandardItemModel): self.invisibleRootItem().insertRows(row, items) def get_projects(self): - return sorted(self.dbcon.projects(no_archived=True), + return sorted(self.dbcon.projects(only_active=True), key=lambda x: x["name"]) diff --git a/openpype/tools/project_manager/project_manager/model.py b/openpype/tools/project_manager/project_manager/model.py index e31dd2ccfe..7036b65f87 100644 --- a/openpype/tools/project_manager/project_manager/model.py +++ b/openpype/tools/project_manager/project_manager/model.py @@ -46,7 +46,7 @@ class ProjectModel(QtGui.QStandardItemModel): project_names = set() for doc in sorted( - self.dbcon.projects(projection={"name": 1}, no_archived=True), + self.dbcon.projects(projection={"name": 1}, only_active=True), key=lambda x: x["name"] ): diff --git a/openpype/tools/settings/local_settings/projects_widget.py b/openpype/tools/settings/local_settings/projects_widget.py index 7d19c37bdf..9cd3b9a38e 100644 --- a/openpype/tools/settings/local_settings/projects_widget.py +++ b/openpype/tools/settings/local_settings/projects_widget.py @@ -809,7 +809,7 @@ class ProjectSettingsWidget(QtWidgets.QWidget): self.modules_manager = modules_manager - projects_widget = _ProjectListWidget(self, no_archived=True) + projects_widget = _ProjectListWidget(self, only_active=True) roos_site_widget = RootSiteWidget( modules_manager, project_settings, self ) diff --git a/openpype/tools/settings/settings/widgets.py b/openpype/tools/settings/settings/widgets.py index d1a8bd8958..133f59e862 100644 --- a/openpype/tools/settings/settings/widgets.py +++ b/openpype/tools/settings/settings/widgets.py @@ -644,7 +644,7 @@ class ProjectListWidget(QtWidgets.QWidget): ProjectFilterRole = QtCore.Qt.UserRole + 11 ProjectSelectedRole = QtCore.Qt.UserRole + 12 - def __init__(self, parent, no_archived=False): + def __init__(self, parent, only_active=False): self._parent = parent self.current_project = None @@ -677,7 +677,7 @@ class ProjectListWidget(QtWidgets.QWidget): layout.addWidget(label_widget, 0) layout.addWidget(project_list, 1) - if no_archived: + if only_active: archived_chk = None else: archived_chk = QtWidgets.QCheckBox(" Show Archived Project ") @@ -697,7 +697,7 @@ class ProjectListWidget(QtWidgets.QWidget): self.archived_chk = archived_chk self.dbcon = None - self._no_archived = no_archived + self._only_active = only_active def on_item_clicked(self, new_index): new_project_name = new_index.data(QtCore.Qt.DisplayRole) @@ -778,8 +778,6 @@ class ProjectListWidget(QtWidgets.QWidget): model = self.project_model model.clear() - items = [(self.default, None)] - mongo_url = os.environ["OPENPYPE_MONGO"] # Force uninstall of whole avalon connection if url does not match @@ -797,33 +795,34 @@ class ProjectListWidget(QtWidgets.QWidget): self.dbcon = None self.current_project = None + items = [(self.default, True)] + if self.dbcon: for doc in self.dbcon.projects( - projection={"name": 1, "data.archived": 1}, - no_archived=self._no_archived + projection={"name": 1, "data.active": 1}, + only_active=self._only_active ): items.append( - (doc["name"], doc.get("data", {}).get("archived")) + (doc["name"], doc.get("data", {}).get("active", True)) ) - for project_name, is_archived in items: - visible = not is_archived + for project_name, is_active in items: row = QtGui.QStandardItem(project_name) - row.setData(visible, self.ProjectFilterRole) + row.setData(is_active, self.ProjectFilterRole) row.setData(False, self.ProjectSelectedRole) - if is_archived: + if is_active: + row.setData(project_name, self.ProjectSortRole) + + else: row.setData("~" + project_name, self.ProjectSortRole) font = row.font() font.setItalic(True) row.setFont(font) - else: - row.setData(project_name, self.ProjectSortRole) - model.appendRow(row) self.project_proxy.sort(0) diff --git a/openpype/tools/standalonepublish/widgets/widget_asset.py b/openpype/tools/standalonepublish/widgets/widget_asset.py index 8ee09d2435..eb22883c11 100644 --- a/openpype/tools/standalonepublish/widgets/widget_asset.py +++ b/openpype/tools/standalonepublish/widgets/widget_asset.py @@ -275,7 +275,7 @@ class AssetWidget(QtWidgets.QWidget): project_names = list() for doc in self.dbcon.projects(projection={"name": 1}, - no_archived=True): + only_active=True): project_name = doc.get("name") if project_name: @@ -304,7 +304,7 @@ class AssetWidget(QtWidgets.QWidget): projects = list() for project in self.dbcon.projects(projection={"name": 1}, - no_archived=True): + only_active=True): projects.append(project['name']) project_name = self.combo_projects.currentText() if project_name in projects: From 0bf84ad8133732c7e367b85ef3dc3a9278d3ad18 Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 15 Sep 2021 11:13:04 +0800 Subject: [PATCH 14/21] refactor data role attrib to model --- openpype/tools/settings/settings/widgets.py | 28 +++++++++++---------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/openpype/tools/settings/settings/widgets.py b/openpype/tools/settings/settings/widgets.py index 133f59e862..73076deeee 100644 --- a/openpype/tools/settings/settings/widgets.py +++ b/openpype/tools/settings/settings/widgets.py @@ -602,6 +602,12 @@ class NiceCheckbox(QtWidgets.QFrame): return super(NiceCheckbox, self).mouseReleaseEvent(event) +class ProjectListModel(QtGui.QStandardItemModel): + sort_role = QtCore.Qt.UserRole + 10 + filter_role = QtCore.Qt.UserRole + 11 + selected_role = QtCore.Qt.UserRole + 12 + + class ProjectListView(QtWidgets.QListView): left_mouse_released_at = QtCore.Signal(QtCore.QModelIndex) @@ -624,7 +630,7 @@ class ProjectListSortFilterProxy(QtCore.QSortFilterProxyModel): index = self.sourceModel().index(source_row, 0, source_parent) is_active = bool(index.data(self.filterRole())) - is_selected = bool(index.data(ProjectListWidget.ProjectSelectedRole)) + is_selected = bool(index.data(ProjectListModel.selected_role)) return is_active or is_selected @@ -640,10 +646,6 @@ class ProjectListWidget(QtWidgets.QWidget): default = "< Default >" project_changed = QtCore.Signal() - ProjectSortRole = QtCore.Qt.UserRole + 10 - ProjectFilterRole = QtCore.Qt.UserRole + 11 - ProjectSelectedRole = QtCore.Qt.UserRole + 12 - def __init__(self, parent, only_active=False): self._parent = parent @@ -655,11 +657,11 @@ class ProjectListWidget(QtWidgets.QWidget): label_widget = QtWidgets.QLabel("Projects") project_list = ProjectListView(self) - project_model = QtGui.QStandardItemModel() + project_model = ProjectListModel() project_proxy = ProjectListSortFilterProxy() - project_proxy.setFilterRole(self.ProjectFilterRole) - project_proxy.setSortRole(self.ProjectSortRole) + project_proxy.setFilterRole(ProjectListModel.filter_role) + project_proxy.setSortRole(ProjectListModel.sort_role) project_proxy.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive) project_proxy.setSourceModel(project_model) @@ -760,7 +762,7 @@ class ProjectListWidget(QtWidgets.QWidget): found_items = model.findItems(self.default) index = model.indexFromItem(found_items[0]) - model.setData(index, True, self.ProjectSelectedRole) + model.setData(index, True, ProjectListModel.selected_role) index = proxy.mapFromSource(index) @@ -810,14 +812,14 @@ class ProjectListWidget(QtWidgets.QWidget): for project_name, is_active in items: row = QtGui.QStandardItem(project_name) - row.setData(is_active, self.ProjectFilterRole) - row.setData(False, self.ProjectSelectedRole) + row.setData(is_active, ProjectListModel.filter_role) + row.setData(False, ProjectListModel.selected_role) if is_active: - row.setData(project_name, self.ProjectSortRole) + row.setData(project_name, ProjectListModel.sort_role) else: - row.setData("~" + project_name, self.ProjectSortRole) + row.setData("~" + project_name, ProjectListModel.sort_role) font = row.font() font.setItalic(True) From 7ac2c04f613a77bceed2ff0e9e30b8e6ad24c6dd Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 15 Sep 2021 11:14:31 +0800 Subject: [PATCH 15/21] remove project archive confirmation --- .../defaults/project_anatomy/attributes.json | 1 - openpype/settings/entities/root_entities.py | 29 ------------------- .../schemas/schema_anatomy_attributes.json | 6 ---- 3 files changed, 36 deletions(-) diff --git a/openpype/settings/defaults/project_anatomy/attributes.json b/openpype/settings/defaults/project_anatomy/attributes.json index 128d5c14ca..983ac603f9 100644 --- a/openpype/settings/defaults/project_anatomy/attributes.json +++ b/openpype/settings/defaults/project_anatomy/attributes.json @@ -23,6 +23,5 @@ "unreal/4-26" ], "tools_env": [], - "archive_confirm": "", "active": true } \ No newline at end of file diff --git a/openpype/settings/entities/root_entities.py b/openpype/settings/entities/root_entities.py index 5701b60098..05d20ee60b 100644 --- a/openpype/settings/entities/root_entities.py +++ b/openpype/settings/entities/root_entities.py @@ -755,35 +755,6 @@ class ProjectSettings(RootEntity): """ return DEFAULTS_DIR - def settings_value(self): - output = super(ProjectSettings, self).settings_value() - - anatomy = output.get(PROJECT_ANATOMY_KEY) or {} - - # Evaluate project archiving flag - # - archive_confirm = anatomy.get("attributes", {}).get("archive_confirm") - if archive_confirm: - # set flag - if archive_confirm == self.project_name: - self.log.debug( - "Project archiving." - ) - anatomy["attributes"]["archived"] = True - - else: - self.log.debug( - "Project archiving confirmation string not matched." - ) - anatomy["attributes"]["archive_confirm"] = "" - anatomy["attributes"]["archived"] = False - - else: - if anatomy and "attributes" in anatomy: - anatomy["attributes"]["archived"] = False - - return output - def _save_studio_values(self): settings_value = self.settings_value() diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json index fdae566655..530bf70a7c 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json @@ -70,12 +70,6 @@ "key": "tools_env", "label": "Tools" }, - { - "type": "text", - "key": "archive_confirm", - "label": "Archive Project", - "placeholder": "Input project name to confirm archiving." - }, { "type": "boolean", "key": "active", From db9e5fa1df8d2c740cbe143c2179fad4a5a03b73 Mon Sep 17 00:00:00 2001 From: David Lai Date: Wed, 15 Sep 2021 23:30:00 +0800 Subject: [PATCH 16/21] Rephrase 'archived' to 'inactive' --- openpype/tools/settings/settings/widgets.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openpype/tools/settings/settings/widgets.py b/openpype/tools/settings/settings/widgets.py index 73076deeee..a461f3e675 100644 --- a/openpype/tools/settings/settings/widgets.py +++ b/openpype/tools/settings/settings/widgets.py @@ -680,23 +680,23 @@ class ProjectListWidget(QtWidgets.QWidget): layout.addWidget(project_list, 1) if only_active: - archived_chk = None + inactive_chk = None else: - archived_chk = QtWidgets.QCheckBox(" Show Archived Project ") - archived_chk.setChecked(not project_proxy.is_filter_enabled()) + inactive_chk = QtWidgets.QCheckBox(" Show Inactive Projects ") + inactive_chk.setChecked(not project_proxy.is_filter_enabled()) layout.addSpacing(5) - layout.addWidget(archived_chk, 0) + layout.addWidget(inactive_chk, 0) layout.addSpacing(5) - archived_chk.stateChanged.connect(self.on_archive_vis_changed) + inactive_chk.stateChanged.connect(self.on_inactive_vis_changed) project_list.left_mouse_released_at.connect(self.on_item_clicked) self.project_list = project_list self.project_proxy = project_proxy self.project_model = project_model - self.archived_chk = archived_chk + self.inactive_chk = inactive_chk self.dbcon = None self._only_active = only_active @@ -734,12 +734,12 @@ class ProjectListWidget(QtWidgets.QWidget): else: self.select_project(self.current_project) - def on_archive_vis_changed(self): - if self.archived_chk is None: + def on_inactive_vis_changed(self): + if self.inactive_chk is None: # should not happen. return - enable_filter = not self.archived_chk.isChecked() + enable_filter = not self.inactive_chk.isChecked() self.project_proxy.set_filter_enabled(enable_filter) def validate_context_change(self): From d0e0bcb67cbb9eb3ab2032651a0f1a8723ef809b Mon Sep 17 00:00:00 2001 From: David Lai Date: Thu, 16 Sep 2021 16:07:24 +0800 Subject: [PATCH 17/21] Update openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json Co-authored-by: Milan Kolar --- .../projects_schema/schemas/schema_anatomy_attributes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json index 530bf70a7c..a2a566da0e 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json @@ -73,7 +73,7 @@ { "type": "boolean", "key": "active", - "label": "Is Project Active" + "label": "Active Project" } ] } From 4fbf5dd8dbc43d2467d4ec3c10a0d644dca70566 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 16 Sep 2021 17:01:08 +0200 Subject: [PATCH 18/21] removed unused ProjectModel --- .../sync_server/tray/models.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/openpype/modules/default_modules/sync_server/tray/models.py b/openpype/modules/default_modules/sync_server/tray/models.py index 8c86d3b98f..96d09b8786 100644 --- a/openpype/modules/default_modules/sync_server/tray/models.py +++ b/openpype/modules/default_modules/sync_server/tray/models.py @@ -17,25 +17,6 @@ from . import lib log = PypeLogger().get_logger("SyncServer") -class ProjectModel(QtCore.QAbstractListModel): - def __init__(self, *args, projects=None, **kwargs): - super(ProjectModel, self).__init__(*args, **kwargs) - self.projects = projects or [] - - def data(self, index, role): - if role == Qt.DisplayRole: - # See below for the data structure. - status, text = self.projects[index.row()] - # Return the todo text only. - return text - - def rowCount(self, _index): - return len(self.todos) - - def columnCount(self, _index): - return len(self._header) - - class _SyncRepresentationModel(QtCore.QAbstractTableModel): COLUMN_LABELS = [] From a67cfcd5f54a1f8ba04bac0122078565235413bb Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 16 Sep 2021 17:01:28 +0200 Subject: [PATCH 19/21] delegate signal handler to method --- .../modules/default_modules/sync_server/tray/app.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/openpype/modules/default_modules/sync_server/tray/app.py b/openpype/modules/default_modules/sync_server/tray/app.py index 106076d81c..0299edb2eb 100644 --- a/openpype/modules/default_modules/sync_server/tray/app.py +++ b/openpype/modules/default_modules/sync_server/tray/app.py @@ -77,8 +77,8 @@ class SyncServerWindow(QtWidgets.QDialog): self.setWindowTitle("Sync Queue") self.projects.project_changed.connect( - lambda: repres.table_view.model().set_project( - self.projects.current_project)) + self._on_project_change + ) self.pause_btn.clicked.connect(self._pause) self.pause_btn.setAutoDefault(False) @@ -87,6 +87,13 @@ class SyncServerWindow(QtWidgets.QDialog): self.representationWidget = repres + def _on_project_change(self): + if self.projects.current_project is None: + return + self.representationWidget.table_view.model().set_project( + self.projects.current_project + ) + def showEvent(self, event): self.representationWidget.model.set_project( self.projects.current_project) From c5cc3fcf99c5eb2564476b4074eccff3f86c3369 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 16 Sep 2021 17:23:49 +0200 Subject: [PATCH 20/21] Transfer logic from settings project list widget to sync server --- .../sync_server/tray/widgets.py | 49 ++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/openpype/modules/default_modules/sync_server/tray/widgets.py b/openpype/modules/default_modules/sync_server/tray/widgets.py index 13389ed36c..e2009bd219 100644 --- a/openpype/modules/default_modules/sync_server/tray/widgets.py +++ b/openpype/modules/default_modules/sync_server/tray/widgets.py @@ -6,10 +6,7 @@ from functools import partial from Qt import QtWidgets, QtCore, QtGui from Qt.QtCore import Qt -from openpype.tools.settings import ( - ProjectListWidget, - style -) +from openpype.tools.settings import style from openpype.api import get_local_site_id from openpype.lib import PypeLogger @@ -28,25 +25,53 @@ from . import delegates log = PypeLogger().get_logger("SyncServer") -class SyncProjectListWidget(ProjectListWidget): +class SyncProjectListWidget(QtWidgets.QWidget): """ Lists all projects that are synchronized to choose from """ + project_changed = QtCore.Signal() def __init__(self, sync_server, parent): - super(SyncProjectListWidget, self).__init__(parent, only_active=True) + super(SyncProjectListWidget, self).__init__(parent) + self.setObjectName("ProjectListWidget") + + self._parent = parent + + label_widget = QtWidgets.QLabel("Projects", self) + project_list = QtWidgets.QListView(self) + project_model = QtGui.QStandardItemModel() + project_list.setModel(project_model) + project_list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + + # Do not allow editing + project_list.setEditTriggers( + QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers + ) + + layout = QtWidgets.QVBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(3) + layout.addWidget(label_widget, 0) + layout.addWidget(project_list, 1) + + project_list.customContextMenuRequested.connect(self._on_context_menu) + project_list.selectionModel().currentChanged.connect( + self._on_index_change + ) + + self.project_model = project_model + self.project_list = project_list self.sync_server = sync_server - self.project_list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) - self.project_list.customContextMenuRequested.connect( - self._on_context_menu) + self.current_project = None self.project_name = None self.local_site = None self.icons = {} - self.layout().setContentsMargins(0, 0, 0, 0) + def _on_index_change(self, new_idx, _old_idx): + project_name = new_idx.data(QtCore.Qt.DisplayRole) - def validate_context_change(self): - return True + self.current_project = project_name + self.project_changed.emit() def refresh(self): model = self.project_model From cca201729c821a0fa3bc55c2922d76ca4c8c9ddd Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 16 Sep 2021 17:24:22 +0200 Subject: [PATCH 21/21] modified how projects are queried for sync server --- .../sync_server/sync_server_module.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/openpype/modules/default_modules/sync_server/sync_server_module.py b/openpype/modules/default_modules/sync_server/sync_server_module.py index 976a349bfa..5e6a9d1823 100644 --- a/openpype/modules/default_modules/sync_server/sync_server_module.py +++ b/openpype/modules/default_modules/sync_server/sync_server_module.py @@ -815,17 +815,22 @@ class SyncServerModule(OpenPypeModule, ITrayModule): def _prepare_sync_project_settings(self, exclude_locals): sync_project_settings = {} system_sites = self.get_all_site_configs() - for collection in self.connection.database.collection_names(False): + project_docs = self.connection.projects( + projection={"name": 1}, + only_active=True + ) + for project_doc in project_docs: + project_name = project_doc["name"] sites = copy.deepcopy(system_sites) # get all configured sites proj_settings = self._parse_sync_settings_from_settings( - get_project_settings(collection, + get_project_settings(project_name, exclude_locals=exclude_locals)) sites.update(self._get_default_site_configs( - proj_settings["enabled"], collection)) + proj_settings["enabled"], project_name)) sites.update(proj_settings['sites']) proj_settings["sites"] = sites - sync_project_settings[collection] = proj_settings + sync_project_settings[project_name] = proj_settings if not sync_project_settings: log.info("No enabled and configured projects for sync.") return sync_project_settings