diff -r de0718b80010 -r d476667171a1 src/eric7/EricWidgets/EricListSelectionDialog.py --- a/src/eric7/EricWidgets/EricListSelectionDialog.py Mon Sep 25 12:09:23 2023 +0200 +++ b/src/eric7/EricWidgets/EricListSelectionDialog.py Tue Sep 26 18:26:21 2023 +0200 @@ -31,13 +31,15 @@ message="", checkBoxSelection=False, doubleClickOk=False, + emptySelectionOk=False, + showSelectAll=False, parent=None, ): """ Constructor @param entries list of entries to select from - @type list of str + @type list of str or list of tuple of (str, Any) @param selectionMode selection mode for the list @type QAbstractItemView.SelectionMode @param title title of the dialog @@ -50,6 +52,10 @@ @param doubleClickOk flag indicating to accept the dialog upon a double click of an item (single selection only) @type bool + @param emptySelectionOk flag indicating that an empty selection is allowed + @type bool + @param showSelectAll flag indicating to show a 'Select All' button + @type bool @param parent reference to the parent widget @type QWidget """ @@ -63,22 +69,39 @@ self.__checkCount = 0 self.__isCheckBoxSelection = checkBoxSelection - if self.__isCheckBoxSelection: - self.selectionList.setSelectionMode( - QAbstractItemView.SelectionMode.NoSelection - ) - for entry in entries: + self.__doubleClickOk = doubleClickOk + self.__emptySelectionOk = emptySelectionOk + + self.selectionList.setSelectionMode( + QAbstractItemView.SelectionMode.NoSelection + if self.__isCheckBoxSelection + else selectionMode + ) + + for entry in entries: + if isinstance(entry, tuple): + itm = QListWidgetItem(entry[0]) + itm.setData(Qt.ItemDataRole.UserRole, entry[1]) + else: itm = QListWidgetItem(entry) + if self.__isCheckBoxSelection: itm.setFlags( Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsEnabled ) itm.setCheckState(Qt.CheckState.Unchecked) - self.selectionList.addItem(itm) - else: - self.selectionList.setSelectionMode(selectionMode) - self.selectionList.addItems(entries) + self.selectionList.addItem(itm) - self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False) + if showSelectAll: + self.buttonBox.addButton( + self.tr("Deselect All"), QDialogButtonBox.ButtonRole.ActionRole + ).clicked.connect(lambda: self.__selectAll(False)) + self.buttonBox.addButton( + self.tr("Select All"), QDialogButtonBox.ButtonRole.ActionRole + ).clicked.connect(lambda: self.__selectAll(True)) + + self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( + emptySelectionOk + ) @pyqtSlot() def on_selectionList_itemSelectionChanged(self): @@ -87,9 +110,10 @@ """ if not self.__isCheckBoxSelection: self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( - len(self.selectionList.selectedItems()) > 0 + len(self.selectionList.selectedItems()) > 0 or self.__emptySelectionOk ) + @pyqtSlot(QListWidgetItem) def on_selectionList_itemChanged(self, itm): """ Private slot handling a change of an item. @@ -103,7 +127,7 @@ elif self.__checkCount > 0: self.__checkCount -= 1 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( - self.__checkCount > 0 + self.__checkCount > 0 or self.__emptySelectionOk ) @pyqtSlot(QListWidgetItem) @@ -118,23 +142,66 @@ not self.__isCheckBoxSelection and self.selectionList.selectionMode() == QAbstractItemView.SelectionMode.SingleSelection + and self.__doubleClickOk ): self.accept() + def __selectAll(self, state): + """ + Private method to select or deselect all entries. + + @param state flag indicating the desired selection state + @type bool + """ + for row in range(self.selectionList.count()): + item = self.selectionList.item(row) + if self.__isCheckBoxSelection: + if state: + item.setCheckState(Qt.CheckState.Checked) + else: + item.setCheckState(Qt.CheckState.Unchecked) + else: + item.setSelected(state) + + def setSelection(self, selection): + """ + Public method to preselect a list of entries. + + @param selection list of selected entries + @type list of str + """ + for name in selection: + itemList = self.selectionList.findItems( + name, Qt.MatchFlag.MatchCaseSensitive | Qt.MatchFlag.MatchStartsWith + ) + if itemList: + if self.__isCheckBoxSelection: + itemList[0].setCheckState(Qt.CheckState.Checked) + else: + itemList[0].setSelected(True) + def getSelection(self): """ Public method to retrieve the selected items. @return selected entries - @rtype list of str + @rtype list of str or list of tuple of (str, Any) """ entries = [] if self.__isCheckBoxSelection: for row in range(self.selectionList.count()): item = self.selectionList.item(row) if item.checkState() == Qt.CheckState.Checked: - entries.append(item.text()) + data = item.data(Qt.ItemDataRole.UserRole) + if data is None: + entries.append(item.text()) + else: + entries.append((item.text(), data)) else: for item in self.selectionList.selectedItems(): - entries.append(item.text()) + data = item.data(Qt.ItemDataRole.UserRole) + if data is None: + entries.append(item.text()) + else: + entries.append((item.text(), data)) return entries