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()
Esempio n. 3
0
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()
Esempio n. 6
0
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()
Esempio n. 7
0
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()