class ScenarioSelectionDialog(QDialog): """ A dialog used for selecting from available scenarios """ def __init__(self, scenario_registry: ScenarioRegistry, parent=None): """ Constructor for ScenarioSelectionDialog :param scenario_registry: linked scenario registry :param parent: parent widget """ super().__init__(parent) self.scenario_registry = scenario_registry self.setWindowTitle(self.tr('Select Current Scenario')) layout = QVBoxLayout() self.search = QgsFilterLineEdit() self.search.setShowSearchIcon(True) self.search.setPlaceholderText(self.tr('Search for scenario')) self.search.textChanged.connect(self.filter_changed) layout.addWidget(self.search) self.list = QListWidget() for title, scenario_id in scenario_registry.scenario_titles().items(): item = QListWidgetItem(title) item.setData(Qt.UserRole, scenario_id) self.list.addItem(item) layout.addWidget(self.list, 10) button_box = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel) layout.addWidget(button_box) button_box.rejected.connect(self.reject) button_box.accepted.connect(self.accept) self.setLayout(layout) self.list.itemDoubleClicked.connect( self.accept) # select last scenario by default if self.list.count() > 0: self.list.item(self.list.count() - 1).setSelected(True) def set_selected_scenario(self, scenario): """ Sets the scenario selected in the dialog :param scenario: scenario to select """ for i in range(self.list.count()): if self.list.item(i).data(Qt.UserRole) == scenario: self.list.item(i).setSelected(True) return def selected_scenario(self): """ Returns the scenario selected in the dialog """ if self.list.selectedItems(): return self.list.selectedItems()[0].data(Qt.UserRole) return None def filter_changed(self, filter_text): """ Handles search filter changes """ for i in range(self.list.count()): item = self.list.item(i) item.setHidden(filter_text.upper() not in item.text().upper())
class GroupSelectParameterWidget(GenericParameterWidget): """Widget class for Group Select Parameter.""" def __init__(self, parameter, parent=None): """Constructor. :param parameter: A GroupSelectParameter object. :type parameter: GroupSelectParameter """ QWidget.__init__(self, parent) self._parameter = parameter # Store spin box self.spin_boxes = {} # Create elements # Label (name) self.label = QLabel(self._parameter.name) # Layouts self.main_layout = QVBoxLayout() self.input_layout = QVBoxLayout() # _inner_input_layout must be filled with widget in the child class self.inner_input_layout = QVBoxLayout() self.radio_button_layout = QGridLayout() # Create radio button group self.input_button_group = QButtonGroup() # List widget self.list_widget = QListWidget() self.list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.list_widget.setDragDropMode(QAbstractItemView.DragDrop) self.list_widget.setDefaultDropAction(Qt.MoveAction) self.list_widget.setEnabled(False) self.list_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) for i, key in enumerate(self._parameter.options): value = self._parameter.options[key] radio_button = QRadioButton(value.get('label')) self.radio_button_layout.addWidget(radio_button, i, 0) if value.get('type') == SINGLE_DYNAMIC: percentage_spin_box = PercentageSpinBox(self) self.radio_button_layout.addWidget(percentage_spin_box, i, 1) percentage_spin_box.setValue(value.get('value', 0)) step = percentage_spin_box.singleStep() if step > 1: precision = 0 else: precision = len(str(step).split('.')[1]) if precision > 3: precision = 3 percentage_spin_box.setDecimals(precision) self.spin_boxes[key] = percentage_spin_box # Enable spin box depends on the selected option if self._parameter.selected == key: percentage_spin_box.setEnabled(True) else: percentage_spin_box.setEnabled(False) elif value.get('type') == STATIC: static_value = value.get('value', 0) if static_value is not None: self.radio_button_layout.addWidget( QLabel(str(static_value * 100) + ' %'), i, 1) elif value.get('type') == MULTIPLE_DYNAMIC: if self._parameter.selected == key: self.list_widget.setEnabled(True) else: self.list_widget.setEnabled(False) self.input_button_group.addButton(radio_button, i) if self._parameter.selected == key: radio_button.setChecked(True) # Help text self.help_label = QLabel(self._parameter.help_text) self.help_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) self.help_label.setWordWrap(True) self.help_label.setAlignment(Qt.AlignTop) self.inner_input_layout.addLayout(self.radio_button_layout) self.inner_input_layout.addWidget(self.list_widget) # Put elements into layouts self.input_layout.addWidget(self.label) self.input_layout.addLayout(self.inner_input_layout) self.help_layout = QVBoxLayout() self.help_layout.addWidget(self.help_label) self.main_layout.addLayout(self.input_layout) self.main_layout.addLayout(self.help_layout) self.setLayout(self.main_layout) self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) # Update list widget self.update_list_widget() # Connect signal # noinspection PyUnresolvedReferences self.input_button_group.buttonClicked.connect( self.radio_buttons_clicked) def get_parameter(self): """Obtain list parameter object from the current widget state. :returns: A DefaultValueParameter from the current state of widget :rtype: DefaultValueParameter """ # Set value for each key for key, value in list(self._parameter.options.items()): if value.get('type') == STATIC: continue elif value.get('type') == SINGLE_DYNAMIC: new_value = self.spin_boxes.get(key).value() self._parameter.set_value_for_key(key, new_value) elif value.get('type') == MULTIPLE_DYNAMIC: # Need to iterate through all items items = [] for index in range(self.list_widget.count()): items.append(self.list_widget.item(index)) new_value = [i.text() for i in items] self._parameter.set_value_for_key(key, new_value) # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id == -1: self._parameter.selected = None else: self._parameter.selected = list( self._parameter.options.keys())[radio_button_checked_id] return self._parameter def update_list_widget(self): """Update list widget when radio button is clicked.""" # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id > -1: selected_dict = list( self._parameter.options.values())[radio_button_checked_id] if selected_dict.get('type') == MULTIPLE_DYNAMIC: for field in selected_dict.get('value'): # Update list widget field_item = QListWidgetItem(self.list_widget) field_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) field_item.setData(Qt.UserRole, field) field_item.setText(field) self.list_widget.addItem(field_item) def radio_buttons_clicked(self): """Handler when selected radio button changed.""" # Disable all spin boxes for spin_box in list(self.spin_boxes.values()): spin_box.setEnabled(False) # Disable list widget self.list_widget.setEnabled(False) # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() if radio_button_checked_id > -1: selected_value = list( self._parameter.options.values())[radio_button_checked_id] if selected_value.get('type') == MULTIPLE_DYNAMIC: # Enable list widget self.list_widget.setEnabled(True) elif selected_value.get('type') == SINGLE_DYNAMIC: selected_key = list( self._parameter.options.keys())[radio_button_checked_id] self.spin_boxes[selected_key].setEnabled(True) def select_radio_button(self, key): """Helper to select a radio button with key. :param key: The key of the radio button. :type key: str """ key_index = list(self._parameter.options.keys()).index(key) radio_button = self.input_button_group.button(key_index) radio_button.click()
class TagsDialog(QDialog): def __init__(self, dockwidget, parent, params): QDialog.__init__(self, parent) main_lay = QVBoxLayout(self) self.dockwidget = dockwidget self.params = params self.setWindowTitle('Tags editor') # Top frame self.fra_top = QFrame() fra_top_lay = QVBoxLayout(self.fra_top) self.lst_main = QListWidget(self) self.btn_add = QPushButton('Add tag') self.btn_add.clicked.connect(self.add_tag) self.btn_remove = QPushButton('Remove tag') self.btn_remove.clicked.connect(self.remove_tag) fra_top_lay.addWidget(self.lst_main) fra_top_lay.addWidget(self.btn_add) fra_top_lay.addWidget(self.btn_remove) # Bottom frame self.fra_bottom = QFrame() fra_bottom_lay = QHBoxLayout(self.fra_bottom) btb_main = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) btb_main.accepted.connect(self.ok) btb_main.rejected.connect(self.reject) fra_bottom_lay.addWidget(btb_main) # Main main_lay.addWidget(self.fra_top) main_lay.addWidget(self.fra_bottom) self.initialize() def initialize(self): for tag_name in self.params.tag_names: self.lst_main.insertItem(self.lst_main.count(), QListWidgetItem(tag_name, self.lst_main)) def ok(self): tag_names = [] for r in range(self.lst_main.count()): tag_names.append(self.lst_main.item(r).text()) self.params.tag_names = tag_names self.setVisible(False) def reject(self): self.setVisible(False) def add_tag(self): tag_name_dialog = TagNameDialog(self.dockwidget, self) tag_name_dialog.exec_() tag_name = tag_name_dialog.get_tag_name() if tag_name is not None: current_row = self.lst_main.currentRow() if current_row is None: current_row = self.lst_main.count() self.lst_main.insertItem(current_row, QListWidgetItem(tag_name, self.lst_main)) def remove_tag(self): sel_items = self.lst_main.selectedItems() for sel_item in sel_items: self.lst_main.takeItem(self.lst_main.row(sel_item))
class DeprecateElectorateDialog(QDialog): """ A dialog used for selecting electorates to deprecate (or un-deprecate) :param district_registry: associated registry of available districts to show """ def __init__(self, electorate_registry: LinzElectoralDistrictRegistry, parent=None): super().__init__(parent) self.electorate_registry = electorate_registry self.setWindowTitle(self.tr('Deprecate Electorate')) layout = QVBoxLayout() self.search = QgsFilterLineEdit() self.search.setShowSearchIcon(True) self.search.setPlaceholderText( self.tr('Search for {}').format( electorate_registry.type_string_sentence())) self.search.textChanged.connect(self.filter_changed) layout.addWidget(self.search) request = QgsFeatureRequest() request.setFlags(QgsFeatureRequest.NoGeometry) request.setSubsetOfAttributes([ electorate_registry.source_field_index, electorate_registry.title_field_index, electorate_registry.deprecated_field_index ]) self.list = QListWidget() for f in electorate_registry.source_layer.getFeatures(request): title = f[electorate_registry.title_field_index] code = f[electorate_registry.source_field_index] deprecated = f[electorate_registry.deprecated_field_index] if deprecated: title = '*' + title item = QListWidgetItem(title) item.setData(Qt.UserRole, code) self.list.addItem(item) layout.addWidget(self.list, 10) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) layout.addWidget(button_box) button_box.rejected.connect(self.reject) button_box.accepted.connect(self.accept) self.setLayout(layout) self.list.itemDoubleClicked.connect(self.accept) def selected_district(self): """ Returns the electorate selected in the dialog """ if self.list.selectedItems(): return self.list.selectedItems()[0].data(Qt.UserRole) return None def filter_changed(self, filter_text): """ Handles search filter changes """ for i in range(self.list.count()): item = self.list.item(i) item.setHidden(filter_text.upper() not in item.text().upper())
class GroupSelectParameterWidget(GenericParameterWidget): """Widget class for Group Select Parameter.""" def __init__(self, parameter, parent=None): """Constructor. :param parameter: A GroupSelectParameter object. :type parameter: GroupSelectParameter """ QWidget.__init__(self, parent) self._parameter = parameter # Store spin box self.spin_boxes = {} # Create elements # Label (name) self.label = QLabel(self._parameter.name) # Layouts self.main_layout = QVBoxLayout() self.input_layout = QVBoxLayout() # _inner_input_layout must be filled with widget in the child class self.inner_input_layout = QVBoxLayout() self.radio_button_layout = QGridLayout() # Create radio button group self.input_button_group = QButtonGroup() # List widget self.list_widget = QListWidget() self.list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.list_widget.setDragDropMode(QAbstractItemView.DragDrop) self.list_widget.setDefaultDropAction(Qt.MoveAction) self.list_widget.setEnabled(False) self.list_widget.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Expanding) for i, key in enumerate(self._parameter.options): value = self._parameter.options[key] radio_button = QRadioButton(value.get('label')) self.radio_button_layout.addWidget(radio_button, i, 0) if value.get('type') == SINGLE_DYNAMIC: percentage_spin_box = PercentageSpinBox(self) self.radio_button_layout.addWidget(percentage_spin_box, i, 1) percentage_spin_box.setValue(value.get('value', 0)) step = percentage_spin_box.singleStep() if step > 1: precision = 0 else: precision = len(str(step).split('.')[1]) if precision > 3: precision = 3 percentage_spin_box.setDecimals(precision) self.spin_boxes[key] = percentage_spin_box # Enable spin box depends on the selected option if self._parameter.selected == key: percentage_spin_box.setEnabled(True) else: percentage_spin_box.setEnabled(False) elif value.get('type') == STATIC: static_value = value.get('value', 0) if static_value is not None: self.radio_button_layout.addWidget( QLabel(str(static_value * 100) + ' %'), i, 1) elif value.get('type') == MULTIPLE_DYNAMIC: if self._parameter.selected == key: self.list_widget.setEnabled(True) else: self.list_widget.setEnabled(False) self.input_button_group.addButton(radio_button, i) if self._parameter.selected == key: radio_button.setChecked(True) # Help text self.help_label = QLabel(self._parameter.help_text) self.help_label.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Expanding) self.help_label.setWordWrap(True) self.help_label.setAlignment(Qt.AlignTop) self.inner_input_layout.addLayout(self.radio_button_layout) self.inner_input_layout.addWidget(self.list_widget) # Put elements into layouts self.input_layout.addWidget(self.label) self.input_layout.addLayout(self.inner_input_layout) self.help_layout = QVBoxLayout() self.help_layout.addWidget(self.help_label) self.main_layout.addLayout(self.input_layout) self.main_layout.addLayout(self.help_layout) self.setLayout(self.main_layout) self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) # Update list widget self.update_list_widget() # Connect signal # noinspection PyUnresolvedReferences self.input_button_group.buttonClicked.connect( self.radio_buttons_clicked) def get_parameter(self): """Obtain list parameter object from the current widget state. :returns: A DefaultValueParameter from the current state of widget :rtype: DefaultValueParameter """ # Set value for each key for key, value in list(self._parameter.options.items()): if value.get('type') == STATIC: continue elif value.get('type') == SINGLE_DYNAMIC: new_value = self.spin_boxes.get(key).value() self._parameter.set_value_for_key(key, new_value) elif value.get('type') == MULTIPLE_DYNAMIC: # Need to iterate through all items items = [] for index in range(self.list_widget.count()): items.append(self.list_widget.item(index)) new_value = [i.text() for i in items] self._parameter.set_value_for_key(key, new_value) # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id == -1: self._parameter.selected = None else: self._parameter.selected = list(self._parameter.options.keys())[ radio_button_checked_id] return self._parameter def update_list_widget(self): """Update list widget when radio button is clicked.""" # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id > -1: selected_dict = list(self._parameter.options.values())[ radio_button_checked_id] if selected_dict.get('type') == MULTIPLE_DYNAMIC: for field in selected_dict.get('value'): # Update list widget field_item = QListWidgetItem(self.list_widget) field_item.setFlags( Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) field_item.setData(Qt.UserRole, field) field_item.setText(field) self.list_widget.addItem(field_item) def radio_buttons_clicked(self): """Handler when selected radio button changed.""" # Disable all spin boxes for spin_box in list(self.spin_boxes.values()): spin_box.setEnabled(False) # Disable list widget self.list_widget.setEnabled(False) # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() if radio_button_checked_id > -1: selected_value = list(self._parameter.options.values())[ radio_button_checked_id] if selected_value.get('type') == MULTIPLE_DYNAMIC: # Enable list widget self.list_widget.setEnabled(True) elif selected_value.get('type') == SINGLE_DYNAMIC: selected_key = list(self._parameter.options.keys())[ radio_button_checked_id] self.spin_boxes[selected_key].setEnabled(True) def select_radio_button(self, key): """Helper to select a radio button with key. :param key: The key of the radio button. :type key: str """ key_index = list(self._parameter.options.keys()).index(key) radio_button = self.input_button_group.button(key_index) radio_button.click()
class AnnotationManager: def __init__(self, iface): locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join(os.path.dirname(__file__), 'i18n', 'annotationManager_{}.qm'.format(locale)) self.translator = None if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) self.iface = iface self.iface.projectRead.connect(self.projectOpen) self.dock = QDockWidget(self.tr('Annotations')) self.manager = QWidget() toolbar = QToolBar() self.annotationList = QListWidget() self.annotationList.setSelectionMode( QAbstractItemView.ExtendedSelection) self.annotationList.itemSelectionChanged.connect(self.selectAnnotation) self.annotationList.itemChanged.connect(self.checkItem) action_refresh = QAction( QIcon(':/plugins/annotationManager/resources/mActionDraw.png'), self.tr('Refresh the annotations list'), self.manager) action_refresh.triggered.connect(self.refreshAnnotations) action_remove = QAction( QIcon( ':/plugins/annotationManager/resources/mActionRemoveAnnotation.png' ), self.tr('Remove the selected annotation'), self.manager) action_remove.triggered.connect(self.removeAnnotation) viewMenu = QMenu() action_showAll = QAction( QIcon(':/plugins/annotationManager/resources/mActionShowAll.png'), self.tr('Show all annotations'), self.manager) action_showAll.triggered.connect(self.showAll) action_hideAll = QAction( QIcon(':/plugins/annotationManager/resources/mActionHideAll.png'), self.tr('Hide all annotations'), self.manager) action_hideAll.triggered.connect(self.hideAll) action_showAllSelected = QAction( QIcon(':/plugins/annotationManager/resources/mActionShowAll.png'), self.tr('Show all selected annotations'), self.manager) action_showAllSelected.triggered.connect(self.showAllSelected) action_hideAllSelected = QAction( QIcon(':/plugins/annotationManager/resources/mActionHideAll.png'), self.tr('Hide all selected annotations'), self.manager) action_hideAllSelected.triggered.connect(self.hideAllSelected) viewMenu.addAction(action_showAll) viewMenu.addAction(action_hideAll) viewMenu.addAction(action_showAllSelected) viewMenu.addAction(action_hideAllSelected) viewButton = QToolButton() viewButton.setIcon( QIcon(':/plugins/annotationManager/resources/mActionShowAll.png')) viewButton.setPopupMode(2) viewButton.setMenu(viewMenu) toolbar.addAction(action_refresh) toolbar.addAction(action_remove) toolbar.addWidget(viewButton) toolbar.setIconSize(QSize(16, 16)) p1_vertical = QVBoxLayout() p1_vertical.setContentsMargins(0, 0, 0, 0) p1_vertical.addWidget(toolbar) p1_vertical.addWidget(self.annotationList) self.manager.setLayout(p1_vertical) self.dock.setWidget(self.manager) self.dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dock) self.rb = QgsRubberBand(self.iface.mapCanvas(), QgsWkbTypes.PolygonGeometry) self.project = QgsProject.instance() self.annotationManager = self.project.annotationManager() self.annotationManager.annotationAdded.connect(self.refreshAnnotations) self.annotationManager.annotationRemoved.connect( self.refreshAnnotations) def checkItem(self, item): index = self.annotationList.row(item) if item.checkState() == Qt.Checked: self.annotationManager.annotations()[index].setVisible(True) else: self.annotationManager.annotations()[index].setVisible(False) if item.isSelected(): item.setSelected(False) self.rb.reset(QgsWkbTypes.PolygonGeometry) def selectAnnotation(self): self.rb.reset(QgsWkbTypes.PolygonGeometry) self.rb.setColor(QColor(0, 0, 255, 128)) for item in self.annotationList.selectedItems(): index = self.annotationList.row(item) mapTool = QgsMapTool(self.iface.mapCanvas()) point = mapTool.toCanvasCoordinates( self.annotationManager.annotations()[index].mapPosition()) pt1 = mapTool.toMapCoordinates( QPoint(point.x() - 10, point.y() - 10)) pt2 = mapTool.toMapCoordinates( QPoint(point.x() + 10, point.y() + 10)) rect = QgsRectangle(pt1, pt2) poly = QgsGeometry().fromRect(rect) self.rb.addGeometry(poly, None) def showAll(self): count = self.annotationList.count() for i in range(count): self.annotationList.item(i).setCheckState(Qt.Checked) def hideAll(self): count = self.annotationList.count() for i in range(count): self.annotationList.item(i).setCheckState(Qt.Unchecked) def showAllSelected(self): for item in self.annotationList.selectedItems(): item.setCheckState(Qt.Checked) def hideAllSelected(self): for item in self.annotationList.selectedItems(): item.setCheckState(Qt.Unchecked) def unload(self): del self.dock def tr(self, message): return QCoreApplication.translate('AnnotationManager', message) def refreshAnnotationTitle(self, annotation=None): if annotation is None: annotation = self.project.annotationManager().sender() item = self.annotationList.item( self.annotationManager.annotations().index(annotation)) title = 'Annotation' if isinstance(annotation, QgsTextAnnotation): title = annotation.document().toPlainText().split('\n')[0] if len(title) > 40: title = title[:40] + '(...)' item.setText(title) def refreshAnnotations(self): self.annotationList.clearSelection() self.annotationList.clear() for annotation in self.annotationManager.annotations(): item = QListWidgetItem() annotation.appearanceChanged.connect(self.refreshAnnotationTitle) if annotation.isVisible(): item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) item.setFlags(item.flags()) self.annotationList.addItem(item) self.refreshAnnotationTitle(annotation) def removeAnnotation(self): if len(self.annotationList.selectedItems()) > 0: self.annotationManager.annotationRemoved.disconnect() trash = [] for item in self.annotationList.selectedItems(): index = self.annotationList.row(item) trash.append(self.annotationManager.annotations()[index]) while trash: self.annotationManager.removeAnnotation(trash.pop()) self.refreshAnnotations() self.annotationManager.annotationRemoved.connect( self.refreshAnnotations) def projectOpen(self): self.refreshAnnotations() def initGui(self): self.refreshAnnotations()
class MultiSelectComboBox(QComboBox): SEARCH_BAR_IDX = 0 SELECT_ALL_IDX = 1 RESERVED_IDXS_COUNT = 2 selection_changed = pyqtSignal() item_was_clicked = pyqtSignal(str, bool) def __init__(self, parent, mono=False): super().__init__(parent) self.mono = mono if self.mono: return self.mlist = QListWidget(self) self.line_edit = ComplexLineEdit(self) self.clear() self.line_edit.setReadOnly(True) self.line_edit.installEventFilter(self) self.setModel(self.mlist.model()) self.setView(self.mlist) self.view().setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setLineEdit(self.line_edit) # NOTE: this is necessary to handle the case in which an item in the # list is clicked to its right part, outside the text self.activated.connect(self.itemClicked) def on_select_all_toggled(self, state): for i in range(self.RESERVED_IDXS_COUNT, self.mlist.count()): checkbox = self.mlist.itemWidget(self.mlist.item(i)) if self.search_bar.text().lower() in checkbox.text().lower(): checkbox.setChecked(state) def itemClicked(self, idx): if self.mono: self.item_was_clicked.emit(self.currentText(), True) return super().itemClicked(idx) if idx not in [self.SEARCH_BAR_IDX, self.SELECT_ALL_IDX]: checkbox = self.mlist.itemWidget(self.mlist.item(idx)) checkbox.setChecked(not checkbox.isChecked()) self.item_was_clicked.emit(checkbox.text(), checkbox.isChecked()) def hidePopup(self): if self.mono: return super().hidePopup() width = self.width() height = self.mlist.height() x = (QCursor.pos().x() - self.mapToGlobal(self.geometry().topLeft()).x() + self.geometry().x()) y = (QCursor.pos().y() - self.mapToGlobal(self.geometry().topLeft()).y() + self.geometry().y()) if (x >= 0 and x <= width and y >= self.height() and y <= height + self.height()): # Item was clicked, do not hide popup pass else: super().hidePopup() def stateChanged(self, state): if self.mono: return super().stateChanged(state) # NOTE: not using state selected_data = "" separator = "; " for i in range(self.RESERVED_IDXS_COUNT, self.mlist.count()): checkbox = self.mlist.itemWidget(self.mlist.item(i)) if checkbox.isChecked(): selected_data += checkbox.text() + separator if selected_data.endswith(separator): selected_data = selected_data[:-len(separator)] if selected_data: self.line_edit.setText(selected_data) else: self.line_edit.clear() self.line_edit.setToolTip(selected_data) self.selection_changed.emit() def on_checkbox_stateChanged(self, text, state): self.item_was_clicked.emit(text, state) def add_selected_items(self, items): if self.mono: return super().addItems(items) self.addItems(items, selected=True) def add_unselected_items(self, items): if self.mono: return super().addItems(items) self.addItems(items, selected=False) def set_selected_items(self, items): if self.mono: return self.set_items_selection(items, True) def set_unselected_items(self, items): if self.mono: return self.set_items_selection(items, False) def set_idxs_selection(self, idxs, checked=True): if self.mono: # NOTE: this method is not expected to be used for mono selectors. # Anyway, we are making it possible to use it, and the selector # will point to the first element of idxs return self.setCurrentIndex(idxs[0]) for i in range(self.RESERVED_IDXS_COUNT, self.mlist.count()): checkbox = self.mlist.itemWidget(self.mlist.item(i)) if i - self.RESERVED_IDXS_COUNT in idxs: checkbox.setChecked(checked) else: checkbox.setChecked(not checked) def set_items_selection(self, items, checked): if self.mono: return for i in range(self.RESERVED_IDXS_COUNT, self.mlist.count()): checkbox = self.mlist.itemWidget(self.mlist.item(i)) if checkbox.text() in items: checkbox.setChecked(checked) else: checkbox.setChecked(not checked) def get_selected_items(self): items = [] if self.mono: if super().currentText(): return [super().currentText()] else: return [] for i in range(self.RESERVED_IDXS_COUNT, self.mlist.count()): checkbox = self.mlist.itemWidget(self.mlist.item(i)) if checkbox.isChecked(): items.append(checkbox.text()) return items def get_unselected_items(self): items = [] if self.mono: selected_text = self.currentText() for i in range(self.count()): item_text = self.itemText(i) if item_text and item_text != selected_text: items.append(item_text) return items for i in range(self.RESERVED_IDXS_COUNT, self.mlist.count()): checkbox = self.mlist.itemWidget(self.mlist.item(i)) if not checkbox.isChecked(): items.append(checkbox.text()) return items def addItem(self, text, user_data=None, selected=False): if self.mono: return super().addItem(text, user_data) # NOTE: not using user_data list_widget_item = QListWidgetItem(self.mlist) checkbox = QCheckBox(self) checkbox.setText(text) self.mlist.addItem(list_widget_item) self.mlist.setItemWidget(list_widget_item, checkbox) checkbox.stateChanged.connect(self.stateChanged) checkbox.stateChanged.connect( lambda state: self.on_checkbox_stateChanged( checkbox.text(), state)) checkbox.setChecked(selected) def currentText(self): if self.mono: return super().currentText() return self.line_edit.current_text() def addItems(self, texts, selected=False): if self.mono: return super().addItems(texts) for text in texts: self.addItem(text, selected=selected) def count(self): if self.mono: return super().count() # do not count search bar and toggle select all count = self.mlist.count() - self.RESERVED_IDXS_COUNT if count < 0: count = 0 return count def selected_count(self): if self.mono: if self.currentIndex() == -1: return 0 else: return 1 return len(self.get_selected_items()) def onSearch(self, search_str): self.setMaxVisibleItems(min(10, self.mlist.count())) for i in range(self.RESERVED_IDXS_COUNT, self.mlist.count()): checkbox = self.mlist.itemWidget(self.mlist.item(i)) if search_str.lower() in checkbox.text().lower(): self.mlist.item(i).setHidden(False) else: self.mlist.item(i).setHidden(True) # NOTE: hack to fix problem when you first filter and have few items, # then filter again and have more items self.hidePopup() self.showPopup() # NOTE: hide/show would lose focus from the search bar self.search_bar.setFocus() def set_search_bar_placeholder_text(self, text): self.search_bar.setPlaceholderText(text) def clear(self): if self.mono: return super().clear() self.mlist.clear() self.search_bar = QLineEdit(self) self.search_item = QListWidgetItem(self.mlist) self.search_bar.setPlaceholderText("Search...") self.search_bar.setClearButtonEnabled(True) self.mlist.addItem(self.search_item) self.mlist.setItemWidget(self.search_item, self.search_bar) self.toggle_select_item = QListWidgetItem(self.mlist) self.toggle_ckb = QCheckBox(self) self.toggle_ckb.setText('Select/unselect all') self.mlist.addItem(self.toggle_select_item) self.mlist.setItemWidget(self.toggle_select_item, self.toggle_ckb) self.toggle_ckb.stateChanged.connect(self.on_select_all_toggled) self.search_bar.textChanged[str].connect(self.onSearch) def wheelEvent(self, wheel_event): if self.mono: return super().wheelEvent(wheel_event) # do not handle the wheel event pass def eventFilter(self, obj, event): if self.mono: return super().eventFilter(obj, event) # this is handled by ComplexLineEdit return False def keyPressEvent(self, event): if self.mono: return super().keyPressEvent(event) # do not handle key event pass # def setCurrentText(self, text): # pass def setCurrentText(self, texts): if self.mono: # NOTE: using the first text return super().setCurrentText(texts[0]) for i in range(self.RESERVED_IDXS_COUNT, self.mlist.count()): checkbox = self.mlist.itemWidget(self.mlist.item(i)) checkbox_str = checkbox.text() if checkbox_str in texts: checkbox.setChecked(True) def resetSelection(self): if self.mono: return super().setCurrentIndex(-1) for i in range(self.RESERVED_IDXS_COUNT, self.mlist.count()): checkbox = self.mlist.itemWidget(self.mlist.item(i)) checkbox.setChecked(False)
class DistrictSelectionDialog(QDialog): """ A dialog used for selecting from available districts :param district_registry: associated registry of available districts to show """ def __init__(self, district_registry, parent=None): super().__init__(parent) self.district_registry = district_registry self.setWindowTitle(self.tr('Select New {}').format( district_registry.type_string_title())) layout = QVBoxLayout() self.recent_label = QLabel(self.tr('Recently used {}').format( district_registry.type_string_sentence_plural())) layout.addWidget(self.recent_label) self.recent_list = QListWidget() self.recent_list.setMaximumHeight(100) for d in district_registry.recent_districts_list(): item = QListWidgetItem(self.district_registry.get_district_title(d)) item.setData(Qt.UserRole, d) self.recent_list.addItem(item) layout.addWidget(self.recent_list, 0) self.available_label = QLabel(self.tr('Available {}').format( district_registry.type_string_sentence_plural() )) layout.addWidget(self.available_label) self.search = QgsFilterLineEdit() self.search.setShowSearchIcon(True) self.search.setPlaceholderText(self.tr('Search for {}').format( district_registry.type_string_sentence())) self.search.textChanged.connect(self.filter_changed) layout.addWidget(self.search) self.list = QListWidget() for title, code in district_registry.district_titles().items(): item = QListWidgetItem(title) item.setData(Qt.UserRole, code) self.list.addItem(item) layout.addWidget(self.list, 10) button_box = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel) layout.addWidget(button_box) button_box.rejected.connect(self.reject) button_box.accepted.connect(self.accept) if self.district_registry.flags() & DistrictRegistry.FLAG_ALLOWS_SPATIAL_SELECT: self.select_from_map_button = button_box.addButton( self.tr("Select from Map"), QDialogButtonBox.ActionRole) self.select_from_map_button.clicked.connect(self.pick_from_map) else: self.select_from_map_button = None self.chose_pick_from_map = False self.setLayout(layout) self.recent_list.itemSelectionChanged.connect( self.recent_list_item_selected) self.list.itemSelectionChanged.connect( self.list_item_selected) self.recent_list.itemDoubleClicked.connect( self.accept) self.list.itemDoubleClicked.connect( self.accept) # select most recently used district by default if self.recent_list.count() > 0: self.recent_list.item(0).setSelected(True) def recent_list_item_selected(self): """ Handles a selection made in the recent district list """ if self.recent_list.selectedItems(): self.list.clearSelection() def list_item_selected(self): """ Handles a selection made in the complete district list """ if self.list.selectedItems(): self.recent_list.clearSelection() def set_selected_district(self, district): """ Sets the district selected in the dialog :param district: district to select """ for i in range(self.list.count()): if self.list.item(i).data(Qt.UserRole) == district: self.list.item(i).setSelected(True) return def selected_district(self): """ Returns the district selected in the dialog """ if self.recent_list.selectedItems(): return self.recent_list.selectedItems()[0].data(Qt.UserRole) elif self.list.selectedItems(): return self.list.selectedItems()[0].data(Qt.UserRole) return None def accept(self): # pylint: disable=missing-docstring self.district_registry.push_recent_district(self.selected_district()) super().accept() def filter_changed(self, filter_text): """ Handles search filter changes """ for i in range(self.list.count()): item = self.list.item(i) item.setHidden(filter_text.upper() not in item.text().upper()) def pick_from_map(self): """ Triggered when a user selects the "Select from Map" option """ self.chose_pick_from_map = True self.reject()
class CommitSelectDialog(QDialog): def __init__(self, repo, until=None, path=None, parent=None): super(CommitSelectDialog, self).__init__(parent or iface.mainWindow()) self.repo = repo self.ref = None self.path = path self.until = until self.initGui() def initGui(self): layout = QVBoxLayout() buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Close) self.filterBox = QLineEdit() self.filterBox.setPlaceholderText( "[enter text or date in dd/mm/yyyy format to filter history]") self.filterBox.textChanged.connect(self.filterCommits) self.list = QListWidget() self.list.setAlternatingRowColors(True) self.list.setSelectionMode(QAbstractItemView.SingleSelection) self.list.setSelectionBehavior(QAbstractItemView.SelectRows) log = self.repo.log(until=self.until, path=self.path, limit=100) for commit in log: item = CommitListItem(commit) self.list.addItem(item) layout.addWidget(self.filterBox) layout.addWidget(self.list) layout.addWidget(buttonBox) self.setLayout(layout) buttonBox.accepted.connect(self.okPressed) buttonBox.rejected.connect(self.cancelPressed) self.resize(500, 400) self.setWindowTitle("Select commit") def filterCommits(self): text = self.filterBox.text().strip() try: t = datetime.datetime.strptime(text, "%d/%m/%Y") found = False for i in range(self.list.count()): item = self.list.item(i) if found: item.setHidden(True) else: delta = item.commit.committerdate - t found = delta.days < 0 item.setHidden(not found) except ValueError as e: for i in range(self.list.count()): item = self.list.item(i) msg = item.commit.message item.setHidden(text != "" and text not in msg) def okPressed(self): selected = self.list.selectedItems() if len(selected) == 0: QMessageBox.warning(self, 'No commit selected', "Select 1 commits from the commit list.", QMessageBox.Ok) else: self.ref = selected[0].commit self.close() def cancelPressed(self): self.ref = None self.close()