def __init__(self, professor, session, flags=None, *args, **kwargs): super().__init__(flags, *args, **kwargs) main_layout = QVBoxLayout() group = QMComboBox(Group) discipline = QMComboBox(Discipline) main_layout.addWidget(QMSelector([discipline, group], professor), alignment=Qt.AlignTop) def on_group_select(lessons: List[Lesson], group): self.first_lesson = sorted(lessons, key=lambda lesson: lesson.date)[0] self.revoke_step.emit(self.steps[2]) self.file_name = None start_button.setEnabled(False) group.current_changed.connect(on_group_select) group.current_changed.connect( lambda x, y: self.step.emit(self.steps[0])) discipline.current_changed.connect( lambda x, y: self.step.emit(self.steps[1])) button = QPushButton('Выбрать файл') def on_button_click(): file, status = QFileDialog().getOpenFileName( self, 'Выберите файл', '', 'Sheet (*.xls *.xlsx)') if status: self.file_name = file self.step.emit(self.steps[2]) start_button.setEnabled(True) start_button.setText(f'Считать из файла {Path(file).name}') button.clicked.connect(on_button_click) def start(): self.reader = VisitationExcelLoader( file_name=self.file_name, group=list(group.current()), discipline=discipline.current(), session=session) start_button = QPushButton('Считать из файла') start_button.setEnabled(False) start_button.clicked.connect(start) main_layout.addWidget(button, alignment=Qt.AlignHCenter | Qt.AlignVCenter) main_layout.addWidget(start_button, alignment=Qt.AlignHCenter | Qt.AlignTop) self.setLayout(main_layout)
def __init__(self, lesson: Lesson, student: Student): super().__init__() self.lesson = lesson self.student = student self.remove_file_on_close: List[Path] = [] self.setWindowModality(Qt.ApplicationModal) self.setMinimumSize(450, 250) self.r = VisitationLossReason.get(lesson.session(), lesson_id=lesson.id, student_id=student.id) self.grid = QGridLayout() self.setWindowTitle("Добавить причину пропуска") self.grid.addWidget(QLabel('Студент'), 0, 0, 1, 2) student_name_label = QLabel(student.short_name()) student_name_label.setObjectName('InfoLabel') self.grid.addWidget(student_name_label, 0, 2, 1, 2) self.grid.addWidget(QLabel('Занятие'), 1, 0, 1, 2) lesson_name_label = QLabel(name(lesson)) lesson_name_label.setObjectName('InfoLabel') self.grid.addWidget(lesson_name_label, 1, 2, 1, 2) self.reason = QMComboBox(LossReason) self.grid.addWidget(QLabel('Причина'), 2, 0, 1, 2) self.grid.addWidget(self.reason, 2, 2, 1, 2) self.file_attach = QAttachFile('rb', ('pdf', 'docx', 'img')) self.grid.addWidget(self.file_attach, 3, 0, 2, 4) self.grid.addWidget(QAccentCancelButtons(self._accept, self.close), 5, 0, 1, 4) self.setLayout(self.grid) if self.r is not None: self.reason.setCurrent(self.r.reason) if self.r.file is not None: file_path = writeTempFile(self.r.file, self.r.file_ext) self.file_attach.set_file(file_path) self.remove_file_on_close.append(file_path)
def __init__(self, students: List[Student], parent=None): super().__init__(parent) self.setWindowModality(Qt.ApplicationModal) def fill_combo(with_card): self.combo.clear() self.combo.addItems(list(filter(lambda student: with_card or student.card_id is None, students))) self.label = QLabel("Для введенной карты не обнаружен студент.\n" "Выберите студента для введеной карты из списка ниже.") self.combo = QMComboBox(Student) self.combo.formatter = lambda student: f'{Group.names(student.groups)} | {student.full_name()}' self.show_all_students = QCheckBox("Показать всех студентов") self.show_all_students.toggled.connect(fill_combo) self.ok_button = QPushButton("Подтвердить") self.ok_button.clicked.connect(lambda: self.select.emit(self.combo.current())) self.cancel_button = QPushButton("Отмена") self.cancel_button.clicked.connect(self.cancel) main_layout = QVBoxLayout() main_layout.addWidget(self.label) main_layout.addWidget(self.show_all_students) main_layout.addWidget(self.combo) button_layout = QHBoxLayout() button_layout.addWidget(self.ok_button) button_layout.addWidget(self.cancel_button) main_layout.addLayout(button_layout) self.setLayout(main_layout) fill_combo(self.show_all_students.isChecked()) self.select.connect(self.close) self.cancel.connect(self.close)
class QAddLossReason(BisitorWidget): def __init__(self, lesson: Lesson, student: Student): super().__init__() self.lesson = lesson self.student = student self.remove_file_on_close: List[Path] = [] self.setWindowModality(Qt.ApplicationModal) self.setMinimumSize(450, 250) self.r = VisitationLossReason.get(lesson.session(), lesson_id=lesson.id, student_id=student.id) self.grid = QGridLayout() self.setWindowTitle("Добавить причину пропуска") self.grid.addWidget(QLabel('Студент'), 0, 0, 1, 2) student_name_label = QLabel(student.short_name()) student_name_label.setObjectName('InfoLabel') self.grid.addWidget(student_name_label, 0, 2, 1, 2) self.grid.addWidget(QLabel('Занятие'), 1, 0, 1, 2) lesson_name_label = QLabel(name(lesson)) lesson_name_label.setObjectName('InfoLabel') self.grid.addWidget(lesson_name_label, 1, 2, 1, 2) self.reason = QMComboBox(LossReason) self.grid.addWidget(QLabel('Причина'), 2, 0, 1, 2) self.grid.addWidget(self.reason, 2, 2, 1, 2) self.file_attach = QAttachFile('rb', ('pdf', 'docx', 'img')) self.grid.addWidget(self.file_attach, 3, 0, 2, 4) self.grid.addWidget(QAccentCancelButtons(self._accept, self.close), 5, 0, 1, 4) self.setLayout(self.grid) if self.r is not None: self.reason.setCurrent(self.r.reason) if self.r.file is not None: file_path = writeTempFile(self.r.file, self.r.file_ext) self.file_attach.set_file(file_path) self.remove_file_on_close.append(file_path) def _accept(self): file = self.file_attach.get_file() if self.r is None: res = QMessageBox().question( self, "Подтвердите действие", f"Будет добавлена запись для {self.student.short_name()} о пропуске занятия " + f"из-за {inflect(self.reason.current().value, {'gent'})} " + (f"без подтверждения" if file is None else f"с подтверждением")) if res == QMessageBox.Yes: self.r = VisitationLossReason(lesson_id=self.lesson.id, student_id=self.student.id, reason=self.reason.current()) if file is not None: self.r.set_file(self.file_attach.get_path()) self.lesson.session().add(self.r) self.r.session().commit() QMessageBox().information( self, "Успешно добавлено", "Успешно добавлена информация о пропуске") self.close() else: msg = f"В записи для {self.student.short_name()} о пропуске занятия будет изменено" changed = False if self.reason.current() != self.r.reason: msg += f'\n Причина: с {self.r.reason} на {self.reason.current()}' changed = True if file != self.r.file: if self.r.file is None: msg += f'\n Добавлен файл подтверждения' else: msg += f'\n Выбран другой файл' changed = True if changed: res = QMessageBox().question(self, "Подтвердите изменения", msg) if res: self.r.reason = self.reason.current() self.r.set_file(self.file_attach.get_path()) self.r.session().commit() QMessageBox().information( self, "Успешно изменено", "Успешно изменена информация о пропуске") self.close() else: self.close() def close(self): for file_path in self.remove_file_on_close: file_path.unlink() super().close()
def __init__(self, user: _DBObject, *args, **kwargs): from Client.MyQt.Widgets.ComboBox import QMCheckedComboBox, QMComboBox super().__init__(*args, **kwargs) data_groups: List[Type[_DBRoot or _DBObject]] = sorted(_DBRoot.__subclasses__(), key=lambda x: x.__type_name__) plot_types = { "Посещения по неделям": ('bar_week', "Показывает уровень посещений на каждой неделе"), 'Распределение': ('distribution', "Показывает итоговый уровень посещений на дату"), "Посещения по дням недели": ("bar_weekday", "Показывает уровень посещений по дням недели"), "Посещения по занятиям": ("bar_lesson", "Показывает уровень посещения по времени начала начала занятия"), "Гистограма": ('hist', "Показывает частоту каждого уровня посещений"), "Итоговое (по алфавиту)": ('total_alphabetic', "Итоговое посещений на данный момент, отсортированное в алфавитном пордке"), "Итоговое (по возрастанию)": ('total_rated', "Итоговое посещений на данный момент, отсортированное в порядке возрастания процента посещений"), "Общий тренд": ('scatter', "Показывает итоговое посещение на данный момент и график тренда"), "Отклонения по дням": ("deviation", "Показывает изменение процента посещений относительно предыдущего дня") } self.items = [] main_layout = QGridLayout() data_selector = QMComboBox(_DBRoot) main_layout.addWidget(QLabel('Данные по'), 0, 0) main_layout.addWidget(data_selector, 0, 1, 1, 2) item_selector = QMCheckedComboBox(self, with_all=True, type_=Student) item_selector_label = QLabel() # selector_layout.addWidget(item_selector_label, alignment=Qt.AlignVCenter | Qt.AlignRight) main_layout.addWidget(QLabel('Выбор'), 0, 3) main_layout.addWidget(item_selector, 0, 4, 1, 2) semester_selector = QMCheckedComboBox(self, False, Semester) main_layout.addWidget(QLabel('за'), 1, 0) main_layout.addWidget(semester_selector, 1, 1, 1, 2) semester_selector.loads(user) group_by_selector = QMComboBox(_DBRoot) group_by_selector.setEnabled(False) main_layout.addWidget(QLabel('Группировать'), 2, 0) group_by_checkbox = QCheckBox('включить') group_by_checkbox.stateChanged.connect(group_by_selector.setEnabled) main_layout.addWidget(group_by_checkbox, 2, 1, 1, 2) main_layout.addWidget(QLabel('по'), 2, 3) main_layout.addWidget(group_by_selector, 2, 4, 1, 2) plot_type_selector = QComboBox() main_layout.addWidget(QLabel('Тип'), 3, 0) main_layout.addWidget(plot_type_selector, 3, 1, 1, 2) description = QLabel() description.setWordWrap(True) main_layout.addWidget(QLabel('Описание'), 3, 3) main_layout.addWidget(description, 3, 4, 3, 2, Qt.AlignTop) plot_type_selector.currentTextChanged.connect(lambda x: description.setText(plot_types[x][1])) for i in range(6): main_layout.setRowStretch(i, 1) show_btn = QPushButton('Построить') show_btn.setEnabled(False) main_layout.addWidget(show_btn, 5, 2, 1, 2) def update_item_selector(index): item_selector.setEngine(data_selector.current()) item_selector.clear() self.items = data_groups[index].of(user, sort=lambda x: x.full_name()) item_selector.set_items(self.items) item_selector_label.setText(data_groups[index].__name__) show_btn.setEnabled(True) def update_semester_selector(items): semester_selector.clear() semester_selector.loads(items) def update_group_by_slector(index): group_by_selector.clear() group_by_selector.addItems([s for i, s in enumerate(data_groups) if i != index]) data_selector.currentIndexChanged.connect(update_item_selector) item_selector.currentChanged.connect(update_semester_selector) data_selector.currentIndexChanged.connect(update_group_by_slector) data_selector.addItems([s for s in data_groups]) def show(): self.accept.emit( item_selector.current(), group_by_selector.current() if group_by_checkbox.isChecked() else data_selector.current(), plot_types[plot_type_selector.currentText()][0], semester_selector.current() ) show_btn.clicked.connect(show) self.setLayout(main_layout) plot_type_selector.addItems(plot_types.keys())
def __init__(self, professor: Professor): super().__init__() self.setObjectName("Selector") self.professor = professor main_layout = QVBoxLayout() self.tabs = QTabWidget() self.table = VisitTableWidget(self) self.tabs.addTab(self.table, "Таблица посещений") self.tabs.addTab(QWidget(), 'Задания (TODO)') selector_layout = QHBoxLayout() main_layout.addLayout(selector_layout, stretch=1) main_layout.addWidget(self.tabs, stretch=95) # semester self.semester = QMComboBox(parent=self, type_=Semester) sem_label = QLabel('Семестр') sem_label.setAlignment(Qt.AlignRight) selector_layout.addWidget(sem_label, 1, alignment=Qt.AlignCenter | Qt.AlignRight) selector_layout.addWidget(self.semester, 2) # discipline self.discipline = QMComboBox(parent=self, type_=Discipline) disc_label = QLabel("Дисциплина") disc_label.setAlignment(Qt.AlignRight) selector_layout.addWidget(disc_label, 1, alignment=Qt.AlignCenter | Qt.AlignRight) selector_layout.addWidget(self.discipline, 2) # group self.group = QMMultipleComboBox(parent=self, type_=Group) group_label = QLabel("Группа") group_label.setAlignment(Qt.AlignRight) selector_layout.addWidget(group_label, 1, alignment=Qt.AlignCenter | Qt.AlignRight) selector_layout.addWidget(self.group, 2) # lesson self.lesson = QMComboBox(parent=self, type_=Lesson) lesson_label = QLabel("Занятие") lesson_label.setAlignment(Qt.AlignRight) selector_layout.addWidget(lesson_label, 1, alignment=Qt.AlignCenter | Qt.AlignRight) selector_layout.addWidget(self.lesson, 2) self.start_button = QPushButton() self.start_button.setText("Начать занятие") self.end_button = QPushButton() self.end_button.setText("Завершить занятие") self.end_button.setVisible(False) selector_layout.addWidget(self.end_button, 2) selector_layout.addWidget(self.start_button, 2) self.setLayout(main_layout) selector_layout.setContentsMargins(0, 0, 0, 0) self.last_lesson = 0 self.connect() self.semester.loads(self.professor)
class Selector(QWidget): reader_required = pyqtSignal('PyQt_PyObject') set_up = pyqtSignal('PyQt_PyObject') semester_changed = pyqtSignal('PyQt_PyObject') discipline_changed = pyqtSignal( 'PyQt_PyObject') # actual Signature (Discipline) group_changed = pyqtSignal( 'PyQt_PyObject') # actual signature (List[Group]) lesson_changed = pyqtSignal('PyQt_PyObject') # actual signature (Lesson) data_changed = pyqtSignal() lesson_started = pyqtSignal('PyQt_PyObject') lesson_finished = pyqtSignal() view_show_color_rate = pyqtSignal( bool) # управляет цветовой подсветкой результатов студентов professor: Professor = None visitMarker: MarkVisitProcess = None def __init__(self, professor: Professor): super().__init__() self.setObjectName("Selector") self.professor = professor main_layout = QVBoxLayout() self.tabs = QTabWidget() self.table = VisitTableWidget(self) self.tabs.addTab(self.table, "Таблица посещений") self.tabs.addTab(QWidget(), 'Задания (TODO)') selector_layout = QHBoxLayout() main_layout.addLayout(selector_layout, stretch=1) main_layout.addWidget(self.tabs, stretch=95) # semester self.semester = QMComboBox(parent=self, type_=Semester) sem_label = QLabel('Семестр') sem_label.setAlignment(Qt.AlignRight) selector_layout.addWidget(sem_label, 1, alignment=Qt.AlignCenter | Qt.AlignRight) selector_layout.addWidget(self.semester, 2) # discipline self.discipline = QMComboBox(parent=self, type_=Discipline) disc_label = QLabel("Дисциплина") disc_label.setAlignment(Qt.AlignRight) selector_layout.addWidget(disc_label, 1, alignment=Qt.AlignCenter | Qt.AlignRight) selector_layout.addWidget(self.discipline, 2) # group self.group = QMMultipleComboBox(parent=self, type_=Group) group_label = QLabel("Группа") group_label.setAlignment(Qt.AlignRight) selector_layout.addWidget(group_label, 1, alignment=Qt.AlignCenter | Qt.AlignRight) selector_layout.addWidget(self.group, 2) # lesson self.lesson = QMComboBox(parent=self, type_=Lesson) lesson_label = QLabel("Занятие") lesson_label.setAlignment(Qt.AlignRight) selector_layout.addWidget(lesson_label, 1, alignment=Qt.AlignCenter | Qt.AlignRight) selector_layout.addWidget(self.lesson, 2) self.start_button = QPushButton() self.start_button.setText("Начать занятие") self.end_button = QPushButton() self.end_button.setText("Завершить занятие") self.end_button.setVisible(False) selector_layout.addWidget(self.end_button, 2) selector_layout.addWidget(self.start_button, 2) self.setLayout(main_layout) selector_layout.setContentsMargins(0, 0, 0, 0) self.last_lesson = 0 self.connect() self.semester.loads(self.professor) def connect(self): self.semester.current_changed.connect(self.discipline.on_parent_change) self.discipline.current_changed.connect(self.group.on_parent_change) self.group.current_changed.connect(self.lesson.on_parent_change) self.group.current_changed.connect(self.table.setData) self.lesson.current_changed.connect(self.table.set_current_lesson) self.table.select_current_lesson.connect(self.lesson.setCurrent) self.start_button.clicked.connect(self.user_start_lesson) self.lesson_started.connect(self.start_lesson) self.lesson_started.connect(self.table.lesson_start) self.end_button.clicked.connect(self.user_stop_lesson) self.lesson_finished.connect(self.end_lesson) self.lesson_finished.connect(self.table.lesson_finish) self.view_show_color_rate.connect(self.table.view_show_color_rate) @pyqtSlot(bool, name='user_start_lesson') def user_start_lesson(self, status): students = Student.of(self.group.current()) lesson = self.lesson.current() self.visit_marker = MarkVisitProcess( students, lesson, error_callback=self.lesson_finished.emit) self.visit_marker.new_visit.connect(self.table.new_visit) self.lesson_started.emit(lesson) @pyqtSlot(name='user_stop_lesson') def user_stop_lesson(self): self.lesson_finished.emit() def start_lesson(self): self.start_button.setVisible(False) self.end_button.setVisible(True) self.setEnabledControl(False) self._is_lesson_started = True def end_lesson(self): self.visit_marker.stop() self.start_button.setVisible(True) self.end_button.setVisible(False) self.setEnabledControl(True) self._is_lesson_started = False def setEnabledControl(self, b: bool): self.lesson.setEnabled(b) self.group.setEnabled(b) self.discipline.setEnabled(b)