Created
August 1, 2016 13:14
-
-
Save ghtmtt/4e6d40505c1312c85e23849f468de542 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
allows multiple selection in a large list | |
Contact : marco@opengis.ch | |
.. note:: This program is free software; you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation; either version 2 of the License, or | |
(at your option) any later version. | |
""" | |
__author__ = 'marco@opengis.ch' | |
__revision__ = '$Format:%H$' | |
__date__ = '9/07/2013' | |
from qgis.PyQt.QtWidgets import (QGroupBox, | |
QListWidget, | |
QPushButton, | |
QSizePolicy, | |
QLabel, | |
QHBoxLayout, | |
QVBoxLayout, | |
QListWidget, | |
QAbstractItemView) | |
from qgis.PyQt.QtGui import QFont | |
from qgis.PyQt.QtCore import pyqtSignal | |
from PyQt4 import QtCore | |
class ListMultiSelectWidget(QGroupBox): | |
"""Widget to show two parallel lists and move elements between the two | |
usage from code: | |
self.myWidget = ListMultiSelectWidget(title='myTitle') | |
self.myLayout.insertWidget(1, self.myWidget) | |
usage from designer: | |
insert a QGroupBox in your UI file | |
optionally give a title to the QGroupBox | |
promote it to ListMultiSelectWidget | |
""" | |
selection_changed = pyqtSignal() | |
def __init__(self, parent=None, title=None): | |
QGroupBox.__init__(self) | |
self.setTitle(title) | |
self.selected_widget = None | |
self.unselected_widget = None | |
self._setupUI() | |
# connect actions | |
self.select_all_btn.clicked.connect(self._select_all) | |
self.deselect_all_btn.clicked.connect(self._deselect_all) | |
self.select_btn.clicked.connect(self._select) | |
self.deselect_btn.clicked.connect(self._deselect) | |
self.unselected_widget.itemDoubleClicked.connect(self._select) | |
self.selected_widget.itemDoubleClicked.connect(self._deselect) | |
def get_selected_items(self): | |
""" | |
:return list with all the selected items text | |
""" | |
return self._get_items(self.selected_widget) | |
def get_unselected_items(self): | |
""" | |
:return list with all the unselected items text | |
""" | |
return self._get_items(self.unselected_widget) | |
def add_selected_items(self, items): | |
""" | |
:param items list of strings to be added in the selected list | |
""" | |
self._add_items(self.selected_widget, items) | |
def add_unselected_items(self, items): | |
""" | |
:param items list of strings to be added in the unselected list | |
""" | |
self._add_items(self.unselected_widget, items) | |
def set_selected_items(self, items): | |
""" | |
:param items list of strings to be set as the selected list | |
""" | |
self._set_items(self.selected_widget, items) | |
def set_unselected_items(self, items): | |
""" | |
:param items list of strings to be set as the unselected list | |
""" | |
self._set_items(self.unselected_widget, items) | |
def clear(self): | |
""" | |
removes all items from selected and unselected | |
""" | |
self.set_selected_items([]) | |
self.set_unselected_items([]) | |
def addItem(self, item): | |
""" | |
This is for Processing | |
:param item: string to be added in the unselected list | |
""" | |
self.add_unselected_items([item]) | |
def addItems(self, items): | |
""" | |
This is for Processing | |
:param items: list of strings to be added in the unselected list | |
""" | |
self.add_unselected_items(items) | |
def _get_items(self, widget): | |
for i in range(widget.count()): | |
yield widget.item(i).text() | |
def _set_items(self, widget, items): | |
widget.clear() | |
self._add_items(widget, items) | |
def _add_items(self, widget, items): | |
widget.addItems(items) | |
def _select_all(self): | |
self.unselected_widget.selectAll() | |
self._do_move(self.unselected_widget, self.selected_widget) | |
def _deselect_all(self): | |
self.selected_widget.selectAll() | |
self._do_move(self.selected_widget, self.unselected_widget) | |
def _select(self): | |
self._do_move(self.unselected_widget, self.selected_widget) | |
def _deselect(self): | |
self._do_move(self.selected_widget, self.unselected_widget) | |
def _do_move(self, fromList, toList): | |
for item in fromList.selectedItems(): | |
prev_from_item = fromList.item(fromList.row(item) - 1) | |
toList.addItem(fromList.takeItem(fromList.row(item))) | |
fromList.scrollToItem(prev_from_item) | |
self.selection_changed.emit() | |
def _setupUI(self): | |
self.setSizePolicy( | |
QSizePolicy.Preferred, QSizePolicy.Ignored) | |
self.setMinimumHeight(180) | |
self.main_horizontal_layout = QHBoxLayout(self) | |
italic_font = QFont() | |
italic_font.setItalic(True) | |
# unselected widget | |
self.unselected_widget = QListWidget(self) | |
self._set_list_widget_defaults(self.unselected_widget) | |
unselected_label = QLabel() | |
unselected_label.setText('Unselected') | |
unselected_label.setAlignment(QtCore.Qt.AlignCenter) | |
unselected_label.setFont(italic_font) | |
unselected_v_layout = QVBoxLayout() | |
unselected_v_layout.addWidget(unselected_label) | |
unselected_v_layout.addWidget(self.unselected_widget) | |
# selected widget | |
self.selected_widget = QListWidget(self) | |
self._set_list_widget_defaults(self.selected_widget) | |
selected_label = QLabel() | |
selected_label.setText('Selected') | |
selected_label.setAlignment(QtCore.Qt.AlignCenter) | |
selected_label.setFont(italic_font) | |
selected_v_layout = QVBoxLayout() | |
selected_v_layout.addWidget(selected_label) | |
selected_v_layout.addWidget(self.selected_widget) | |
# buttons | |
self.buttons_vertical_layout = QVBoxLayout() | |
self.buttons_vertical_layout.setContentsMargins(0, -1, 0, -1) | |
self.select_all_btn = SmallQPushButton('>>') | |
self.deselect_all_btn = SmallQPushButton('<<') | |
self.select_btn = SmallQPushButton('>') | |
self.deselect_btn = SmallQPushButton('<') | |
self.select_btn.setToolTip('Add the selected items') | |
self.deselect_btn.setToolTip('Remove the selected items') | |
self.select_all_btn.setToolTip('Add all') | |
self.deselect_all_btn.setToolTip('Remove all') | |
# add buttons | |
spacer_label = QLabel() # pragmatic way to create a spacer with | |
# the same height of the labels on top | |
# of the lists, in order to align the | |
# buttons with the lists. | |
self.buttons_vertical_layout.addWidget(spacer_label) | |
self.buttons_vertical_layout.addWidget(self.select_btn) | |
self.buttons_vertical_layout.addWidget(self.deselect_btn) | |
self.buttons_vertical_layout.addWidget(self.select_all_btn) | |
self.buttons_vertical_layout.addWidget(self.deselect_all_btn) | |
# add sub widgets | |
self.main_horizontal_layout.addLayout(unselected_v_layout) | |
self.main_horizontal_layout.addLayout(self.buttons_vertical_layout) | |
self.main_horizontal_layout.addLayout(selected_v_layout) | |
def _set_list_widget_defaults(self, widget): | |
widget.setAlternatingRowColors(True) | |
widget.setSortingEnabled(True) | |
widget.setDragEnabled(True) | |
widget.setDragDropMode(QAbstractItemView.DragDrop) | |
widget.setDragDropOverwriteMode(False) | |
widget.setDefaultDropAction(QtCore.Qt.MoveAction) | |
widget.setSelectionMode(QAbstractItemView.MultiSelection) | |
class SmallQPushButton(QPushButton): | |
def __init__(self, text): | |
QPushButton.__init__(self) | |
self.setText(text) | |
buttons_size_policy = QSizePolicy( | |
QSizePolicy.Fixed, QSizePolicy.Fixed) | |
self.setSizePolicy(buttons_size_policy) | |
self.setMaximumSize(QtCore.QSize(30, 30)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment