# Created By: Virgil Dupras # Created On: 2011-09-06 # Copyright 2015 Hardcoded Software (http://www.hardcoded.net) # # This software is licensed under the "GPLv3" License as described in the "LICENSE" file, # which should be included with this package. The terms are also available at # http://www.gnu.org/licenses/gpl-3.0.html from PyQt5.QtCore import Qt, QAbstractListModel, QItemSelection, QItemSelectionModel class SelectableList(QAbstractListModel): def __init__(self, model, view, **kwargs): super().__init__(**kwargs) self._updating = False self.view = view self.model = model self.view.setModel(self) self.model.view = self # --- Override def data(self, index, role): if not index.isValid(): return None # We need EditRole for QComboBoxes with setEditable(True) if role in {Qt.DisplayRole, Qt.EditRole}: return self.model[index.row()] return None def rowCount(self, index): if index.isValid(): return 0 return len(self.model) # --- Virtual def _updateSelection(self): raise NotImplementedError() def _restoreSelection(self): raise NotImplementedError() # --- model --> view def refresh(self): self._updating = True self.beginResetModel() self.endResetModel() self._updating = False self._restoreSelection() def update_selection(self): self._restoreSelection() class ComboboxModel(SelectableList): def __init__(self, model, view, **kwargs): super().__init__(model, view, **kwargs) self.view.currentIndexChanged[int].connect(self.selectionChanged) # --- Override def _updateSelection(self): index = self.view.currentIndex() if index != self.model.selected_index: self.model.select(index) def _restoreSelection(self): index = self.model.selected_index if index is not None: self.view.setCurrentIndex(index) # --- Events def selectionChanged(self, index): if not self._updating: self._updateSelection() class ListviewModel(SelectableList): def __init__(self, model, view, **kwargs): super().__init__(model, view, **kwargs) self.view.selectionModel().selectionChanged[(QItemSelection, QItemSelection)].connect(self.selectionChanged) # --- Override def _updateSelection(self): new_indexes = [modelIndex.row() for modelIndex in self.view.selectionModel().selectedRows()] if new_indexes != self.model.selected_indexes: self.model.select(new_indexes) def _restoreSelection(self): new_selection = QItemSelection() for index in self.model.selected_indexes: new_selection.select(self.createIndex(index, 0), self.createIndex(index, 0)) self.view.selectionModel().select(new_selection, QItemSelectionModel.ClearAndSelect) if len(new_selection.indexes()): current_index = new_selection.indexes()[0] self.view.selectionModel().setCurrentIndex(current_index, QItemSelectionModel.Current) self.view.scrollTo(current_index) # --- Events def selectionChanged(self, index): if not self._updating: self._updateSelection()