From cb248a013d47ac5c08f095fa9bfa714e32a40e15 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 29 Oct 2021 10:57:20 +0200 Subject: [PATCH] OPPYPE-1905 - fixes after review --- .../sync_server/sync_server.py | 80 ----------------- .../sync_server/sync_server_module.py | 89 +++++++++++++++++-- .../sync_server/tray/widgets.py | 73 ++++++++++----- 3 files changed, 135 insertions(+), 107 deletions(-) diff --git a/openpype/modules/default_modules/sync_server/sync_server.py b/openpype/modules/default_modules/sync_server/sync_server.py index c09916898f..9f16c4b945 100644 --- a/openpype/modules/default_modules/sync_server/sync_server.py +++ b/openpype/modules/default_modules/sync_server/sync_server.py @@ -164,86 +164,6 @@ def resolve_paths(module, file_path, collection, return local_file_path, remote_file_path -def validate_project(module, collection, site_name, remove_missing=False): - """ - Validate 'collection' of 'site_name' and its local files - - If file present and not marked with a 'site_name' in DB, DB is - updated with site name and file modified date. - - Args: - module (SyncServerModule) - collection (string): project name - site_name (string): active site name - remove_missing (bool): if True remove sites in DB if missing - physically - """ - module.log.debug("Validation of {} for {} started".format(collection, - site_name)) - query = { - "type": "representation" - } - - representations = list( - module.connection.database[collection].find(query)) - if not representations: - module.log.debug("No repre found") - return - - sites_added = 0 - sites_removed = 0 - for repre in representations: - repre_id = repre["_id"] - for repre_file in repre.get("files", []): - try: - has_site = site_name in [site["name"] - for site in repre_file["sites"]] - except TypeError: - module.log.debug("Structure error in {}".format(repre_id)) - continue - - if has_site and not remove_missing: - continue - - file_path = repre_file.get("path", "") - local_file_path = module.get_local_file_path(collection, - site_name, - file_path) - - if local_file_path and os.path.exists(local_file_path): - module.log.debug("Adding site {} for {}".format(site_name, - repre_id)) - if not has_site: - query = { - "_id": ObjectId(repre_id) - } - created_dt = datetime.fromtimestamp( - os.path.getmtime(local_file_path)) - elem = {"name": site_name, - "created_dt": created_dt} - module._add_site(collection, query, [repre], elem, - site_name=site_name, - file_id=repre_file["_id"]) - sites_added += 1 - else: - if has_site and remove_missing: - module.log.debug("Removing site {} for {}". - format(site_name, repre["_id"])) - module.reset_provider_for_file(collection, - repre["_id"], - file_id=repre_file["_id"], - remove=True) - sites_removed += 1 - - if sites_added % 100 == 0: - module.log.debug("Sites added {}".format(sites_added)) - - module.log.debug("Validation of {} for {} ended".format(collection, - site_name)) - module.log.info("Sites added {}, sites removed {}".format(sites_added, - sites_removed)) - - def site_is_working(module, project_name, site_name): """ Confirm that 'site_name' is configured correctly for 'project_name'. 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 ce6ef6ef7d..0484864e8e 100644 --- a/openpype/modules/default_modules/sync_server/sync_server_module.py +++ b/openpype/modules/default_modules/sync_server/sync_server_module.py @@ -215,15 +215,93 @@ class SyncServerModule(OpenPypeModule, ITrayModule): Task will run on a asyncio loop, shouldn't be blocking. """ - from .sync_server import validate_project task = { "type": "validate", "project_name": collection, - "func": lambda: validate_project(self, collection, site_name) + "func": lambda: self.validate_project(collection, site_name) } self.projects_processed.add(collection) self.long_running_tasks.append(task) + def validate_project(self, collection, site_name, remove_missing=False): + """ + Validate 'collection' of 'site_name' and its local files + + If file present and not marked with a 'site_name' in DB, DB is + updated with site name and file modified date. + + Args: + module (SyncServerModule) + collection (string): project name + site_name (string): active site name + remove_missing (bool): if True remove sites in DB if missing + physically + """ + self.log.debug("Validation of {} for {} started".format(collection, + site_name)) + query = { + "type": "representation" + } + + representations = list( + self.connection.database[collection].find(query)) + if not representations: + self.log.debug("No repre found") + return + + sites_added = 0 + sites_removed = 0 + for repre in representations: + repre_id = repre["_id"] + for repre_file in repre.get("files", []): + try: + has_site = site_name in [site["name"] + for site in repre_file["sites"]] + except TypeError: + self.log.debug("Structure error in {}".format(repre_id)) + continue + + if has_site and not remove_missing: + continue + + file_path = repre_file.get("path", "") + local_file_path = self.get_local_file_path(collection, + site_name, + file_path) + + if local_file_path and os.path.exists(local_file_path): + self.log.debug("Adding site {} for {}".format(site_name, + repre_id)) + if not has_site: + query = { + "_id": repre_id + } + created_dt = datetime.fromtimestamp( + os.path.getmtime(local_file_path)) + elem = {"name": site_name, + "created_dt": created_dt} + self._add_site(collection, query, [repre], elem, + site_name=site_name, + file_id=repre_file["_id"]) + sites_added += 1 + else: + if has_site and remove_missing: + self.log.debug("Removing site {} for {}". + format(site_name, repre_id)) + self.reset_provider_for_file(collection, + repre_id, + file_id=repre_file["_id"], + remove=True) + sites_removed += 1 + + if sites_added % 100 == 0: + self.log.debug("Sites added {}".format(sites_added)) + + self.log.debug("Validation of {} for {} ended".format(collection, + site_name)) + self.log.info("Sites added {}, sites removed {}".format(sites_added, + sites_removed)) + def pause_representation(self, collection, representation_id, site_name): """ Sets 'representation_id' as paused, eg. no syncing should be @@ -740,22 +818,23 @@ class SyncServerModule(OpenPypeModule, ITrayModule): self.lock = threading.Lock() try: + self.enabled = False self.sync_server_thread = SyncServerThread(self) from .tray.app import SyncServerWindow self.widget = SyncServerWindow(self) + self.enabled = True except ValueError: log.info("No system setting for sync. Not syncing.", exc_info=True) - self.enabled = False except KeyError: log.info(( "There are not set presets for SyncServer OR " "Credentials provided are invalid, " "no syncing possible"). format(str(self.sync_project_settings)), exc_info=True) - self.enabled = False except: - log.info("fck", exc_info=True) + log.error("Uncaught exception durin start of SyncServer", + exc_info=True) def tray_start(self): """ diff --git a/openpype/modules/default_modules/sync_server/tray/widgets.py b/openpype/modules/default_modules/sync_server/tray/widgets.py index 4ecdd131a5..ce3867beae 100644 --- a/openpype/modules/default_modules/sync_server/tray/widgets.py +++ b/openpype/modules/default_modules/sync_server/tray/widgets.py @@ -32,7 +32,7 @@ class SyncProjectListWidget(QtWidgets.QWidget): project_changed = QtCore.Signal() message_generated = QtCore.Signal(str) - REFRESH_SEC = 10000 + refresh_msec = 10000 def __init__(self, sync_server, parent): super(SyncProjectListWidget, self).__init__(parent) @@ -58,8 +58,8 @@ class SyncProjectListWidget(QtWidgets.QWidget): layout.addWidget(project_list, 1) project_list.customContextMenuRequested.connect(self._on_context_menu) - project_list.selectionModel().currentChanged.connect( - self._on_index_change + project_list.selectionModel().selectionChanged.connect( + self._on_selection_changed ) self.project_model = project_model @@ -71,28 +71,43 @@ class SyncProjectListWidget(QtWidgets.QWidget): self.remote_site = None self.icons = {} - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.tick) - self.timer.start(self.REFRESH_SEC) + self._selection_changed = False + self._model_reset = False - def tick(self): - """ - Triggers refresh of model. - """ - self.refresh() - self.timer.start(self.REFRESH_SEC) + timer = QtCore.QTimer() + timer.setInterval(self.refresh_msec) + timer.timeout.connect(self.refresh) + timer.start() - def _on_index_change(self, new_idx, _old_idx): - project_name = new_idx.data(QtCore.Qt.DisplayRole) + self.timer = timer + def _on_selection_changed(self, new_selection, _old_selection): + # block involuntary selection changes + if self._selection_changed or self._model_reset: + return + + indexes = new_selection.indexes() + if not indexes: + return + + project_name = indexes[0].data(QtCore.Qt.DisplayRole) + + if self.current_project == project_name: + return + self._selection_changed = True self.current_project = project_name self.project_changed.emit() + self.refresh() + self._selection_changed = False def refresh(self): + selected_index = None model = self.project_model + self._model_reset = True model.clear() + self._model_reset = False - project_name = None + selected_item = None for project_name in self.sync_server.sync_project_settings.\ keys(): if self.sync_server.is_paused() or \ @@ -104,20 +119,34 @@ class SyncProjectListWidget(QtWidgets.QWidget): if project_name in self.sync_server.projects_processed: icon = self._get_icon("refresh") - model.appendRow(QtGui.QStandardItem(icon, project_name)) + item = QtGui.QStandardItem(icon, project_name) + model.appendRow(item) + + if self.current_project == project_name: + selected_item = item + + if selected_item: + selected_index = model.indexFromItem(selected_item) if len(self.sync_server.sync_project_settings.keys()) == 0: model.appendRow(QtGui.QStandardItem(lib.DUMMY_PROJECT)) - self.current_project = self.project_list.currentIndex().data( - QtCore.Qt.DisplayRole - ) if not self.current_project: self.current_project = model.item(0).data(QtCore.Qt.DisplayRole) - if project_name: - self.local_site = self.sync_server.get_active_site(project_name) - self.remote_site = self.sync_server.get_remote_site(project_name) + self.project_model = model + + if selected_index and selected_index.isValid() and \ + not self._selection_changed: + mode = QtCore.QItemSelectionModel.Select | \ + QtCore.QItemSelectionModel.Rows + self.project_list.selectionModel().select(selected_index, mode) + + if self.current_project: + self.local_site = self.sync_server.get_active_site( + self.current_project) + self.remote_site = self.sync_server.get_remote_site( + self.current_project) def _can_edit(self): """Returns true if some site is user local site, eg. could edit"""