Exemple #1
0
    def init_ui(self):
        super().init_ui()

        layout = QHBoxLayout()
        with self.setup_provided(layout):
            self.x_edit = QLineEdit()
            self.x_edit.setPlaceholderText('X')
            self.x_edit.textChanged.connect(self.change_value)
            layout.addWidget(self.x_edit)

            self.y_edit = QLineEdit()
            self.y_edit.setPlaceholderText('Y')
            self.y_edit.textChanged.connect(self.change_value)
            layout.addWidget(self.y_edit)
        self.setLayout(layout)
Exemple #2
0
class PointWidget(Fidget[Tuple[float, float]]):
    MAKE_TITLE = MAKE_PLAINTEXT = MAKE_INDICATOR = True

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.x_edit = None
        self.y_edit = None
        self.init_ui()
        self.change_value()

    def init_ui(self):
        super().init_ui()

        layout = QHBoxLayout()
        with self.setup_provided(layout):
            self.x_edit = QLineEdit()
            self.x_edit.setPlaceholderText('X')
            self.x_edit.textChanged.connect(self.change_value)
            layout.addWidget(self.x_edit)

            self.y_edit = QLineEdit()
            self.y_edit.setPlaceholderText('Y')
            self.y_edit.textChanged.connect(self.change_value)
            layout.addWidget(self.y_edit)
        self.setLayout(layout)

    def parse(self):
        try:
            x = float(self.x_edit.text())
        except ValueError as e:
            raise ParseError('error in x') from e

        try:
            y = float(self.y_edit.text())
        except ValueError as e:
            raise ParseError('error in y') from e

        return x, y

    def plaintext_parsers(self):
        yield from super().plaintext_parsers()
        yield tuple_
        yield json_dict

    def fill(self, t):
        x, y = t
        self.x_edit.setText(str(x))
        self.y_edit.setText(str(y))
Exemple #3
0
    def init_ui(self, dialog=None):
        super().init_ui()
        self.dialog = self._args_to_filedialog(
            first_valid(dialog=dialog, DIALOG=self.DIALOG, _self=self))

        layout = QHBoxLayout(self)

        with self.setup_provided(layout):
            self.edit = QLineEdit()
            self.edit.textChanged.connect(self.change_value)
            layout.addWidget(self.edit)

            browse_btn = QPushButton('...')
            browse_btn.pressed.connect(self.browse)
            layout.addWidget(browse_btn)

        self.setFocusProxy(self.edit)

        return layout
Exemple #4
0
class FidgetFilePath(Fidget[Path]):
    """
    A Fidget to store a Path to a file
    """

    MAKE_INDICATOR = True
    MAKE_PLAINTEXT = False

    def __init__(self, title: str, exist_cond: Optional[bool] = None, dialog: FileDialogArgs = None, **kwargs):
        """
        :param title: the title
        :param exist_cond: whether the file must exist (True), or must not exist (False)
        :param dialog: either a QFileDialog, a constructor, or arguments for a QFileDialog.
        :param kwargs: forwarded to Fidget
        """
        super().__init__(title, **kwargs)
        self.exist_cond = exist_cond if exist_cond is not None else self.EXIST_COND

        self.dialog: QFileDialog = None
        self.edit: QLineEdit = None

        self.init_ui(dialog)

    DEFAULT_DIALOG_CLS : Type[QFileDialog] = RememberingFileDialog
    DIALOG: FileDialogArgs = RememberingFileDialog
    EXIST_COND = None

    def init_ui(self, dialog=None):
        super().init_ui()
        self.dialog = self._args_to_filedialog(first_valid(dialog=dialog, DIALOG=self.DIALOG, _self=self))

        if self.exist_cond:
            self.dialog.setFileMode(QFileDialog.ExistingFile)
        else:
            self.dialog.setFileMode(QFileDialog.AnyFile)

        layout = QHBoxLayout(self)

        with self.setup_provided(layout):
            self.edit = QLineEdit()
            self.edit.textChanged.connect(self.change_value)
            layout.addWidget(self.edit)

            browse_btn = QPushButton('...')
            browse_btn.pressed.connect(self.browse)
            layout.addWidget(browse_btn)

        self.setFocusProxy(self.edit)

        return layout

    def browse(self, *a):
        if self.dialog.exec():
            self.fill_value(self.dialog.selectedFiles()[0])

    def parse(self):
        return Path(self.edit.text())

    def validate(self, value):
        super().validate(value)
        try:
            exists = value.exists()
        except OSError:
            raise ValidationError('path seems invalid', offender=self.edit)

        if exists:
            if self.exist_cond not in (True, None):
                raise ValidationError("path already exists", offender=self.edit)
            # if the file exists, we don't need to check it
        else:
            if self.exist_cond not in (False, None):
                raise ValidationError("path doesn't exists", offender=self.edit)
            # so checking of a filename is valid is stupid complicated, slow, and fallible,
            # https://stackoverflow.com/questions/9532499/check-whether-a-path-is-valid-in-python-without-creating-a-file-at-the-paths-ta/34102855#34102855
            # we're just gonna check for invalid characters
            if not filename_valid(value):
                raise ValidationError('path seems invalid', offender=self.edit)

        if exists \
                and value.is_dir():
            raise ValidationError('path is a directory', offender=self.edit)

    def fill(self, v: Path):
        self.edit.setText(str(v))

    @inner_plaintext_parser
    @explicit
    @staticmethod
    def glob_search(pattern):
        i = iglob(pattern)
        try:
            ret = next(i)
        except StopIteration as e:
            raise PlaintextParseError('no paths match pattern') from e

        try:
            next(i)
        except StopIteration:
            pass
        else:
            raise PlaintextParseError('multiple paths match pattern')

        return Path(ret)

    @classmethod
    def cls_plaintext_parsers(cls):
        yield Path
        yield from super().cls_plaintext_parsers()

    @classmethod
    def _args_to_filedialog(cls, arg):
        if isinstance(arg, QFileDialog):
            return arg
        if isinstance(arg, dict):
            return cls.DEFAULT_DIALOG_CLS(**arg)
        if callable(arg):
            return arg()
Exemple #5
0
 def get_edit(cls):
     return QLineEdit()
Exemple #6
0
class FidgetFilePaths(Fidget[List[Path]]):
    """
    A Fidget to store a Path to a file
    """

    MAKE_INDICATOR = True
    MAKE_PLAINTEXT = False

    def __init__(self, title: str, dialog: FileDialogArgs = None, **kwargs):
        """
        :param title: the title
        :param exist_cond: whether the file must exist (True), or must not exist (False)
        :param dialog: either a QFileDialog, a constructor, or arguments for a QFileDialog.
        :param kwargs: forwarded to Fidget
        """
        super().__init__(title, **kwargs)

        self.dialog: QFileDialog = None
        self.edit: QLineEdit = None

        self.init_ui(dialog)

    DEFAULT_DIALOG_CLS: Type[QFileDialog] = RememberingFileDialog
    DIALOG: FileDialogArgs = RememberingFileDialog

    def init_ui(self, dialog=None):
        super().init_ui()
        self.dialog = self._args_to_filedialog(
            first_valid(dialog=dialog, DIALOG=self.DIALOG, _self=self))

        layout = QHBoxLayout(self)

        with self.setup_provided(layout):
            self.edit = QLineEdit()
            self.edit.textChanged.connect(self.change_value)
            layout.addWidget(self.edit)

            browse_btn = QPushButton('...')
            browse_btn.pressed.connect(self.browse)
            layout.addWidget(browse_btn)

        self.setFocusProxy(self.edit)

        return layout

    def browse(self, *a):
        if self.dialog.exec():
            self.fill_value(self.dialog.selectedFiles())

    def parse(self):
        return [Path(s) for s in self.edit.text().split(';;')]

    def validate(self, value):
        super().validate(value)
        for p in value:
            try:
                exists = p.exists()
            except OSError:
                raise ValidationError('path seems invalid', offender=self.edit)

            if not exists:
                raise ValidationError("path doesn't exists",
                                      offender=self.edit)

            if exists \
                    and p.is_dir():
                raise ValidationError('path is a directory',
                                      offender=self.edit)

    def fill(self, v: List[Path]):
        self.edit.setText(';;'.join(str(i) for i in v))

    @inner_plaintext_parser
    @explicit
    @staticmethod
    def glob_search(pattern):
        g = iglob(pattern)
        return [Path(i) for i in g]

    @classmethod
    def cls_plaintext_parsers(cls):
        yield Path
        yield from super().cls_plaintext_parsers()

    @classmethod
    def _args_to_filedialog(cls, arg):
        if isinstance(arg, QFileDialog):
            ret = arg
        elif isinstance(arg, dict):
            ret = cls.DEFAULT_DIALOG_CLS(**arg)
        elif callable(arg):
            ret = arg()
        else:
            raise TypeError("can't parse argument as dialog: " + str(arg))
        ret.setFileMode(QFileDialog.ExistingFiles)
        return ret