gui.dialogs.new_course_dialog
1# Copyright (C) 2026 David Vaquero <pepesan@gmail.com> 2# 3# This program is free software: you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation, either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <https://www.gnu.org/licenses/>. 15 16import re 17 18from PySide6.QtWidgets import ( 19 QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, 20 QPushButton, QDialogButtonBox, 21) 22from PySide6.QtCore import Qt 23 24 25_NAME_RE = re.compile(r'^[a-z0-9][a-z0-9_-]*$') 26 27 28class NewCourseDialog(QDialog): 29 def __init__(self, parent=None): 30 super().__init__(parent) 31 self.setWindowTitle('Nuevo curso') 32 self.setMinimumWidth(340) 33 self._build_ui() 34 35 def _build_ui(self) -> None: 36 layout = QVBoxLayout(self) 37 layout.setSpacing(12) 38 39 layout.addWidget(QLabel('Nombre del curso (minúsculas, guiones, sin espacios):')) 40 41 self._input = QLineEdit() 42 self._input.setPlaceholderText('mi-curso') 43 self._input.textChanged.connect(self._validate) 44 layout.addWidget(self._input) 45 46 self._error = QLabel('') 47 self._error.setStyleSheet('color:#c0392b; font-size:11px;') 48 layout.addWidget(self._error) 49 50 btns = QDialogButtonBox( 51 QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel 52 ) 53 btns.accepted.connect(self._on_accept) 54 btns.rejected.connect(self.reject) 55 self._ok_btn = btns.button(QDialogButtonBox.StandardButton.Ok) 56 self._ok_btn.setEnabled(False) 57 layout.addWidget(btns) 58 59 def _validate(self, text: str) -> None: 60 if not text: 61 self._error.setText('') 62 self._ok_btn.setEnabled(False) 63 elif not _NAME_RE.match(text): 64 self._error.setText('Solo minúsculas, dígitos, guión y guión-bajo.') 65 self._ok_btn.setEnabled(False) 66 else: 67 self._error.setText('') 68 self._ok_btn.setEnabled(True) 69 70 def _on_accept(self) -> None: 71 if _NAME_RE.match(self._input.text()): 72 self.accept() 73 74 def course_name(self) -> str: 75 return self._input.text().strip()
class
NewCourseDialog(PySide6.QtWidgets.QDialog):
29class NewCourseDialog(QDialog): 30 def __init__(self, parent=None): 31 super().__init__(parent) 32 self.setWindowTitle('Nuevo curso') 33 self.setMinimumWidth(340) 34 self._build_ui() 35 36 def _build_ui(self) -> None: 37 layout = QVBoxLayout(self) 38 layout.setSpacing(12) 39 40 layout.addWidget(QLabel('Nombre del curso (minúsculas, guiones, sin espacios):')) 41 42 self._input = QLineEdit() 43 self._input.setPlaceholderText('mi-curso') 44 self._input.textChanged.connect(self._validate) 45 layout.addWidget(self._input) 46 47 self._error = QLabel('') 48 self._error.setStyleSheet('color:#c0392b; font-size:11px;') 49 layout.addWidget(self._error) 50 51 btns = QDialogButtonBox( 52 QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel 53 ) 54 btns.accepted.connect(self._on_accept) 55 btns.rejected.connect(self.reject) 56 self._ok_btn = btns.button(QDialogButtonBox.StandardButton.Ok) 57 self._ok_btn.setEnabled(False) 58 layout.addWidget(btns) 59 60 def _validate(self, text: str) -> None: 61 if not text: 62 self._error.setText('') 63 self._ok_btn.setEnabled(False) 64 elif not _NAME_RE.match(text): 65 self._error.setText('Solo minúsculas, dígitos, guión y guión-bajo.') 66 self._ok_btn.setEnabled(False) 67 else: 68 self._error.setText('') 69 self._ok_btn.setEnabled(True) 70 71 def _on_accept(self) -> None: 72 if _NAME_RE.match(self._input.text()): 73 self.accept() 74 75 def course_name(self) -> str: 76 return self._input.text().strip()
QDialog(self, /, parent: PySide6.QtWidgets.QWidget | None = None, f: PySide6.QtCore.Qt.WindowType = Default(Qt.WindowFlags), *, sizeGripEnabled: bool | None = None, modal: bool | None = None) -> None