Example #1
0
    def __init__(self,
                 parent=None,
                 editable=True,
                 nullable=True,
                 field_name='date',
                 validator=DateValidator(),
                 **kwargs):
        CustomEditor.__init__(self, parent)
        self.setSizePolicy(QtGui.QSizePolicy.Preferred,
                           QtGui.QSizePolicy.Fixed)
        self.setObjectName(field_name)
        self.date_format = local_date_format()
        line_edit = DecoratedLineEdit()
        line_edit.setValidator(validator)
        line_edit.setObjectName('date_line_edit')
        line_edit.set_minimum_width(
            six.text_type(
                QtCore.QDate(2000, 12, 22).toString(self.date_format)))
        line_edit.setPlaceholderText(
            QtCore.QDate(2000, 1, 1).toString(self.date_format))

        # The order of creation of this widgets and their parenting
        # seems very sensitive under windows and creates system crashes
        # so don't change this without extensive testing on windows
        special_date_menu = QtWidgets.QMenu(self)
        calendar_widget_action = QtWidgets.QWidgetAction(special_date_menu)
        self.calendar_widget = QtGui.QCalendarWidget(special_date_menu)
        self.calendar_widget.activated.connect(self.calendar_widget_activated)
        self.calendar_widget.clicked.connect(self.calendar_widget_activated)
        calendar_widget_action.setDefaultWidget(self.calendar_widget)

        self.calendar_action_trigger.connect(special_date_menu.hide)
        special_date_menu.addAction(calendar_widget_action)
        special_date_menu.addAction(_('Today'))
        special_date_menu.addAction(_('Far future'))
        self.special_date = QtWidgets.QToolButton(self)
        self.special_date.setIcon(self.special_date_icon.getQIcon())
        self.special_date.setAutoRaise(True)
        self.special_date.setToolTip(_('Calendar and special dates'))
        self.special_date.setMenu(special_date_menu)
        self.special_date.setPopupMode(QtWidgets.QToolButton.InstantPopup)
        self.special_date.setFixedHeight(self.get_height())
        self.special_date.setFocusPolicy(Qt.ClickFocus)
        # end of sensitive part

        if nullable:
            special_date_menu.addAction(_('Clear'))

        self.hlayout = QtWidgets.QHBoxLayout()
        self.hlayout.addWidget(line_edit)
        self.hlayout.addWidget(self.special_date)

        self.hlayout.setContentsMargins(0, 0, 0, 0)
        self.hlayout.setSpacing(0)
        self.hlayout.setAlignment(Qt.AlignRight | Qt.AlignVCenter)

        self.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.hlayout)

        self.minimum = datetime.date.min
        self.maximum = datetime.date.max
        self.setFocusProxy(line_edit)

        line_edit.editingFinished.connect(self.line_edit_finished)
        special_date_menu.triggered.connect(self.set_special_date)
Example #2
0
class VirtualAddressEditor(CustomEditor):
    def __init__(self,
                 parent=None,
                 address_type=None,
                 field_name='virtual_address',
                 **kwargs):
        """
        :param address_type: limit the allowed address to be entered to be
            of a certain time, can be 'phone', 'fax', 'email', 'mobile', 'pager'.
            If set to None, all types are allowed.
            
        Upto now, the corrected address returned by the address validator is
        not yet taken into account.
        """
        CustomEditor.__init__(self, parent)
        self.setSizePolicy(QtGui.QSizePolicy.Preferred,
                           QtGui.QSizePolicy.Fixed)
        self.setObjectName(field_name)
        self._address_type = address_type
        self.layout = QtWidgets.QHBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.combo = QtWidgets.QComboBox()
        self.combo.addItems(camelot.types.VirtualAddress.virtual_address_types)
        self.layout.addWidget(self.combo)
        self.editor = DecoratedLineEdit(self)
        self.editor.set_minimum_width(30)
        if address_type:
            self.combo.setVisible(False)
            idx = camelot.types.VirtualAddress.virtual_address_types.index(
                address_type)
            self.combo.setCurrentIndex(idx)
        self.layout.addWidget(self.editor)
        self.setFocusProxy(self.editor)
        nullIcon = Icon('tango/16x16/apps/internet-mail.png').getQIcon()
        self.label = QtWidgets.QToolButton()
        self.label.setIcon(nullIcon)
        self.label.setAutoRaise(True)
        self.label.setEnabled(False)
        self.label.setToolButtonStyle(Qt.ToolButtonIconOnly)
        self.label.setFocusPolicy(Qt.ClickFocus)
        self.label.clicked.connect(self.mail_click)
        self.label.hide()
        self.layout.addWidget(self.label)
        self.editor.editingFinished.connect(self.emit_editing_finished)
        self.combo.currentIndexChanged.connect(self.comboIndexChanged)
        self.setLayout(self.layout)
        self.update_validator()

    @QtCore.qt_slot()
    def comboIndexChanged(self):
        self.update_validator()
        self.emit_editing_finished()

    def set_value(self, value):
        value = CustomEditor.set_value(self, value)
        if value is None:
            self.editor.setText('')
        else:
            self.editor.setText(value[1])
            idx = camelot.types.VirtualAddress.virtual_address_types.index(
                self._address_type or value[0])
            self.combo.setCurrentIndex(idx)
            icon = Icon('tango/16x16/devices/printer.png').getQIcon()
            if six.text_type(self.combo.currentText()) == 'fax':
                icon = Icon('tango/16x16/devices/printer.png').getQIcon()
            if six.text_type(self.combo.currentText()) == 'email':
                icon = Icon('tango/16x16/apps/internet-mail.png').getQIcon()
                self.label.setIcon(icon)
                self.label.show()
            else:
                self.label.hide()
                self.label.setIcon(icon)
                self.label.setToolButtonStyle(Qt.ToolButtonIconOnly)
            self.update_validator()

    def get_value(self):
        address_value = six.text_type(self.editor.text())
        if not len(address_value):
            value = None
        else:
            value = (six.text_type(self.combo.currentText()), address_value)
        return CustomEditor.get_value(self) or value

    def set_enabled(self, editable=True):
        self.combo.setEnabled(editable)
        self.editor.setEnabled(editable)
        if not editable:
            self.label.setEnabled(False)
        else:
            if self.combo.currentText() == 'email':
                self.label.setEnabled(True)

    def update_validator(self):
        address_type = six.text_type(self.combo.currentText())
        validator = validators.get(address_type, any_character_validator)
        # change the validator instead of the regexp of the validator to inform
        # the editor it needs to update its background color
        self.editor.setValidator(validator)

    @QtCore.qt_slot()
    def mail_click(self):
        address = self.editor.text()
        url = QtCore.QUrl()
        url.setUrl(u'mailto:%s?subject=Subject' % six.text_type(address))
        QtGui.QDesktopServices.openUrl(url)

    def emit_editing_finished(self):
        self.value = []
        self.value.append(six.text_type(self.combo.currentText()))
        self.value.append(six.text_type(self.editor.text()))
        self.set_value(self.value)
        # emiting editingFinished without a value for the mechanism itself will lead to
        # integrity errors
        if self.value[1]:
            self.editingFinished.emit()

    def set_background_color(self, background_color):
        set_background_color_palette(self.editor, background_color)

    def set_field_attributes(self, **kwargs):
        super(VirtualAddressEditor, self).set_field_attributes(**kwargs)
        self.set_enabled(kwargs.get('editable', False))
        self.setToolTip(six.text_type(kwargs.get('tooltip') or ''))