From 51ae46bd6d7d41fe4bd52d546ee90a4e9d135c93 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 19 Jan 2021 12:21:08 +0100 Subject: [PATCH] SyncServer GUI - fix - keep selection during model refresh --- pype/modules/sync_server/sync_server.py | 5 +- pype/modules/sync_server/tray/app.py | 109 +++++++++++++++++++++--- 2 files changed, 102 insertions(+), 12 deletions(-) diff --git a/pype/modules/sync_server/sync_server.py b/pype/modules/sync_server/sync_server.py index b999518103..984e5e34a6 100644 --- a/pype/modules/sync_server/sync_server.py +++ b/pype/modules/sync_server/sync_server.py @@ -117,6 +117,9 @@ class SyncServer(PypeModule, ITrayModule): self.presets = None # settings for all enabled projects for sync self.sync_server_thread = None # asyncio requires new thread + self.connection = AvalonMongoDB() + self.connection.install() + self.action_show_widget = None def connect_with_modules(self, *_a, **kw): @@ -134,8 +137,6 @@ class SyncServer(PypeModule, ITrayModule): self.presets = None self.lock = threading.Lock() - self.connection = AvalonMongoDB() - self.connection.install() try: self.presets = self.get_synced_presets() diff --git a/pype/modules/sync_server/tray/app.py b/pype/modules/sync_server/tray/app.py index 09f7b9e3af..80680af749 100644 --- a/pype/modules/sync_server/tray/app.py +++ b/pype/modules/sync_server/tray/app.py @@ -136,6 +136,8 @@ class SyncRepresentationWidget(QtWidgets.QWidget): self.sync_server = sync_server + self._selected_id = None # keep last selected _id + self.filter = QtWidgets.QLineEdit() self.filter.setPlaceholderText("Filter representations..") @@ -185,19 +187,37 @@ class SyncRepresentationWidget(QtWidgets.QWidget): layout.addLayout(top_bar_layout) layout.addWidget(self.table_view) - self.table_view.doubleClicked.connect(self._doubleClicked) - self.table_view.clicked.connect(self._clicked) + self.table_view.doubleClicked.connect(self._double_clicked) self.filter.textChanged.connect(lambda: model.set_filter( self.filter.text())) self.table_view.customContextMenuRequested.connect( self._on_context_menu) - def _clicked(self, index): - print("clicked") - self.table_view.model()._selected_id = self.table_view.model().\ - data(index, Qt.UserRole) + self.table_view.model().modelReset.connect(self._set_selection) - def _doubleClicked(self, index): + self.selection_model = self.table_view.selectionModel() + self.selection_model.selectionChanged.connect(self._selection_changed) + + def _selection_changed(self, new_selection): + index = self.selection_model.currentIndex() + self._selected_id = self.table_view.model().data(index, Qt.UserRole) + + def _set_selection(self): + """ + Sets selection to 'self._selected_id' if exists. + + Keep selection during model refresh. + """ + if self._selected_id: + index = self.table_view.model().get_index(self._selected_id) + if index and index.isValid(): + mode = QtCore.QItemSelectionModel.Select | \ + QtCore.QItemSelectionModel.Rows + self.selection_model.setCurrentIndex(index, mode) + else: + self._selected_id = None + + def _double_clicked(self, index): """ Opens representation dialog with all files after doubleclick """ @@ -268,7 +288,6 @@ class SyncRepresentationModel(QtCore.QAbstractTableModel): self._rec_loaded = 0 self._buffer = [] # stash one page worth of records (actually cursor) self.filter = None - self._selected_id = None self._initialized = False @@ -465,6 +484,25 @@ class SyncRepresentationModel(QtCore.QAbstractTableModel): self._project = project self.refresh() + def get_index(self, id): + """ + Get index of 'id' value. + + Used for keeping selection after refresh. + + Args: + id (str): MongoDB _id + Returns: + (QModelIndex) + """ + index = None + for i in range(self.rowCount(None)): + index = self.index(i, 0) + value = self.data(index, Qt.UserRole) + if value == id: + return index + return index + def get_default_query(self, limit=0): """ Returns basic aggregate query for main table. @@ -744,6 +782,8 @@ class SyncRepresentationDetailWidget(QtWidgets.QWidget): self.sync_server = sync_server + self._selected_id = None + self.filter = QtWidgets.QLineEdit() self.filter.setPlaceholderText("Filter representation..") @@ -799,6 +839,30 @@ class SyncRepresentationDetailWidget(QtWidgets.QWidget): self.table_view.customContextMenuRequested.connect( self._on_context_menu) + self.table_view.model().modelReset.connect(self._set_selection) + + self.selection_model = self.table_view.selectionModel() + self.selection_model.selectionChanged.connect(self._selection_changed) + + def _selection_changed(self): + index = self.selection_model.currentIndex() + self._selected_id = self.table_view.model().data(index, Qt.UserRole) + + def _set_selection(self): + """ + Sets selection to 'self._selected_id' if exists. + + Keep selection during model refresh. + """ + if self._selected_id: + index = self.table_view.model().get_index(self._selected_id) + if index.isValid(): + mode = QtCore.QItemSelectionModel.Select | \ + QtCore.QItemSelectionModel.Rows + self.selection_model.setCurrentIndex(index, mode) + else: + self._selected_id = None + def _show_detail(self): """ Shows windows with error message for failed sync of a file. @@ -853,7 +917,10 @@ class SyncRepresentationDetailWidget(QtWidgets.QWidget): to_run() def _reset_local_site(self): - log.info("reset local site: {}".format(self.item._id)) + """ + Removes errors or success metadata for particular file >> forces + redo of upload/download + """ self.sync_server.reset_provider_for_file( self.table_view.model()._project, self.representation_id, @@ -861,7 +928,10 @@ class SyncRepresentationDetailWidget(QtWidgets.QWidget): 'local') def _reset_remote_site(self): - log.info("reset remote site: {}".format(self.item._id)) + """ + Removes errors or success metadata for particular file >> forces + redo of upload/download + """ self.sync_server.reset_provider_for_file( self.table_view.model()._project, self.representation_id, @@ -1093,6 +1163,25 @@ class SyncRepresentationDetailModel(QtCore.QAbstractTableModel): self.filter = filter self.refresh() + def get_index(self, id): + """ + Get index of 'id' value. + + Used for keeping selection after refresh. + + Args: + id (str): MongoDB _id + Returns: + (QModelIndex) + """ + index = None + for i in range(self.rowCount(None)): + index = self.index(i, 0) + value = self.data(index, Qt.UserRole) + if value == id: + return index + return index + def get_default_query(self, limit=0): """ Gets query that gets used when no extra sorting, filtering or