sbc/widgets.py
2o 90b6c969e8 Backport to Python 3.7.6
Note that for compatability with Win7SP1, Pyside 6.1.3 and playsound 1.2.2 will be needed(instead of the latest versions).
2024-10-18 11:44:18 +03:00

277 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from PySide6 import QtWidgets, QtGui, QtCore
import time
DAYS_OF_WEEK = "Понеділок Вівторок Середа Четвер П'ятниця Субота Неділя".split()
class BasicBox(QtWidgets.QScrollArea):
def __init__(self, title):
super().__init__()
self.widget = QtWidgets.QWidget()
self.setWidgetResizable(True)
self.setWidget(self.widget)
self.layout = QtWidgets.QVBoxLayout(self.widget)
font = QtGui.QFont()
font.setPointSize(16)
title = QtWidgets.QLabel(title)
title.setFont(font)
self.layout.addWidget(title)
class WidgetArray(QtWidgets.QWidget):
def __init__(self, deleted_item_callback, edit_button=False):
super().__init__()
self.deleted_item_callback = deleted_item_callback
self.main_layout = QtWidgets.QVBoxLayout(self)
self.control_widget = QtWidgets.QWidget()
self.control_layout = QtWidgets.QHBoxLayout(self.control_widget)
self.add_button = QtWidgets.QPushButton()
self.add_button.setIcon(QtGui.QIcon("add.png"))
self.add_button.setFixedSize(22, 22)
self.delete_button = QtWidgets.QPushButton()
self.delete_button.setIcon(QtGui.QIcon("delete.png"))
self.delete_button.setFixedSize(22, 22)
self.delete_button.clicked.connect(self.delete_items)
self.control_layout.addWidget(self.add_button)
self.control_layout.addWidget(self.delete_button)
if edit_button:
self.edit_button = QtWidgets.QPushButton()
self.edit_button.setIcon(QtGui.QIcon("edit.png"))
self.edit_button.setFixedSize(22, 22)
self.control_layout.addWidget(self.edit_button)
self.control_layout.addStretch(1)
self.widget_list = QtWidgets.QListWidget()
self.main_layout.addWidget(self.control_widget)
self.main_layout.addWidget(self.widget_list)
def add_item(self, widget):
item = QtWidgets.QListWidgetItem()
self.widget_list.addItem(item)
self.widget_list.setItemWidget(item, widget)
def get_items(self):
for i in range(self.widget_list.count()):
yield self.widget_list.itemWidget(self.widget_list.item(i))
def delete_items(self):
selected_items = self.widget_list.selectedItems()
if not selected_items: return
# if multiple items are selected, and the parent of this widget list keeps track of the widgets somehow,
# this makes so they are deleted in the correct order
selected_items.sort(reverse=True, key=lambda item: self.widget_list.row(item))
for item in selected_items:
row = self.widget_list.row(item)
self.widget_list.takeItem(row)
self.deleted_item_callback(row)
class BellStatusBox(BasicBox):
def __init__(self):
super().__init__("Розклад дзвінків")
self.bells_list = QtWidgets.QListWidget()
self.layout.addWidget(self.bells_list)
class ScheduleBox(BasicBox):
def __init__(self):
super().__init__("Налаштування розкладу")
self.grid_widget = QtWidgets.QWidget()
self.grid_layout = QtWidgets.QGridLayout(self.grid_widget)
self.grid_widget.setLayout(self.grid_layout)
self.first_lesson_input = QtWidgets.QTimeEdit()
self.lesson_length_input = QtWidgets.QSpinBox()
self.break_length_input = QtWidgets.QSpinBox()
self.first_bell_input = QtWidgets.QSpinBox()
self.num_lessons_input = QtWidgets.QSpinBox()
self.lesson_length_input.setRange(20, 90)
self.break_length_input.setRange(2, 59)
self.first_bell_input.setRange(1, 4)
self.num_lessons_input.setRange(1, 20)
self.break_length_input.valueChanged.connect(self.update_limits)
self.grid_layout.addWidget(QtWidgets.QLabel("Перший урок о"), 0, 0)
self.grid_layout.addWidget(QtWidgets.QLabel("Тривалість уроку:"), 1, 0)
self.grid_layout.addWidget(QtWidgets.QLabel("Перерва"), 2, 0)
self.grid_layout.addWidget(QtWidgets.QLabel("Перший дзвоник за"), 3, 0)
self.grid_layout.addWidget(QtWidgets.QLabel("Кількість уроків:"), 4, 0)
self.grid_layout.addWidget(QtWidgets.QLabel("хвилин"), 1, 2)
self.grid_layout.addWidget(QtWidgets.QLabel("хвилин"), 2, 2)
self.grid_layout.addWidget(QtWidgets.QLabel("хвилин до уроку"), 3, 2)
self.grid_layout.addWidget(self.first_lesson_input, 0, 1)
self.grid_layout.addWidget(self.lesson_length_input, 1, 1)
self.grid_layout.addWidget(self.break_length_input, 2, 1)
self.grid_layout.addWidget(self.first_bell_input, 3, 1)
self.grid_layout.addWidget(self.num_lessons_input, 4, 1)
self.first_bell_before_first_lesson_checkbox = QtWidgets.QCheckBox("Перший дзвоник перед першим уроком")
self.layout.addWidget(self.grid_widget)
self.layout.addWidget(self.first_bell_before_first_lesson_checkbox)
self.layout.addStretch(1)
def update_limits(self, value):
self.first_bell_input.setRange(1, value - 1)
class DaysSelectBox(BasicBox):
def __init__(self):
super().__init__("Робочі дні")
self.days_checkboxes = []
for day_name in DAYS_OF_WEEK:
self.days_checkboxes.append(QtWidgets.QCheckBox(day_name))
self.layout.addWidget(self.days_checkboxes[-1])
self.layout.addStretch(1)
class AdditionalSoundsBox(BasicBox):
def __init__(self, show_sound_diag):
super().__init__("Додаткові звуки")
self.show_sound_diag = show_sound_diag
self.sound_list = WidgetArray(self.deleted_item, True)
self.sound_list.add_button.clicked.connect(lambda: self.show_sound_diag())
self.sound_list.edit_button.clicked.connect(self.edit_sound)
self.layout.addWidget(self.sound_list)
self.sounds = []
self.editing_sound = 0
def add_sound(self, name, times, sound_file, edit_n=None):
if edit_n is None:
self.sounds.append([name, times, sound_file])
self.sound_list.add_item(QtWidgets.QLabel(name))
else:
self.sounds[edit_n] = [name, times, sound_file]
self.sound_list.widget_list.itemWidget(self.sound_list.widget_list.item(edit_n)).setText(name)
def deleted_item(self, n):
del self.sounds[n]
def edit_sound(self):
edit_n = self.sound_list.widget_list.currentRow()
sound = self.sounds[edit_n]
self.show_sound_diag(edit_n, *sound)
class StatusBox(BasicBox):
def __init__(self):
super().__init__("Стан")
self.grid_widget = QtWidgets.QWidget()
self.grid_layout = QtWidgets.QGridLayout(self.grid_widget)
self.grid_widget.setLayout(self.grid_layout)
self.day_of_week_widget = QtWidgets.QLabel()
self.current_time_widget = QtWidgets.QLabel()
self.uptime_widget = QtWidgets.QLabel()
self.grid_layout.addWidget(QtWidgets.QLabel("День тижня:"), 0, 0)
self.grid_layout.addWidget(self.day_of_week_widget, 0, 1)
self.grid_layout.addWidget(QtWidgets.QLabel("Поточний час:"), 1, 0)
self.grid_layout.addWidget(self.current_time_widget, 1, 1)
self.grid_layout.addWidget(QtWidgets.QLabel("Зі запуску:"), 2, 0)
self.grid_layout.addWidget(self.uptime_widget, 2, 1)
self.layout.addWidget(self.grid_widget)
self.layout.addStretch(1)
self.uptime_timer = QtCore.QElapsedTimer()
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.update)
self.uptime_timer.start()
self.timer.start(1000)
self.update()
def update(self):
t = time.localtime()
self.day_of_week_widget.setText(DAYS_OF_WEEK[t.tm_wday])
self.current_time_widget.setText(f"{t.tm_hour:02}:{t.tm_min:02}:{t.tm_sec:02}")
seconds = self.uptime_timer.elapsed() / 1000
minutes = seconds / 60
hours = minutes / 60
days = hours / 24
self.uptime_widget.setText(f"{int(days)} днів, {int(hours % 24):02}:{int(minutes % 60):02}:{int(seconds % 60):02}")
class SoundFilesBox(BasicBox):
def __init__(self):
super().__init__("Звуки")
self.grid_widget = QtWidgets.QWidget()
self.grid_layout = QtWidgets.QGridLayout(self.grid_widget)
self.grid_widget.setLayout(self.grid_layout)
self.first_bell_file_text = QtWidgets.QLabel()
self.second_bell_file_text = QtWidgets.QLabel()
self.break_file_text = QtWidgets.QLabel()
self.first_bell_file_button = QtWidgets.QPushButton("Огляд")
self.second_bell_file_button = QtWidgets.QPushButton("Огляд")
self.break_file_button = QtWidgets.QPushButton("Огляд")
self.first_bell_file_button .clicked.connect(lambda: self.file_select_diag(0))
self.second_bell_file_button.clicked.connect(lambda: self.file_select_diag(1))
self.break_file_button .clicked.connect(lambda: self.file_select_diag(2))
self.grid_layout.addWidget(QtWidgets.QLabel("Перший дзвоник:"), 0, 0)
self.grid_layout.addWidget(QtWidgets.QLabel("Другий дзвоник:"), 1, 0)
self.grid_layout.addWidget(QtWidgets.QLabel("Перерва:"), 2, 0)
self.grid_layout.addWidget(self.first_bell_file_text, 0, 1)
self.grid_layout.addWidget(self.second_bell_file_text, 1, 1)
self.grid_layout.addWidget(self.break_file_text, 2, 1)
self.grid_layout.addWidget(self.first_bell_file_button, 0, 2)
self.grid_layout.addWidget(self.second_bell_file_button, 1, 2)
self.grid_layout.addWidget(self.break_file_button, 2, 2)
self.layout.addWidget(self.grid_widget)
self.layout.addStretch(1)
def file_select_diag(self, sound_type):
file_name, _ = QtWidgets.QFileDialog.getOpenFileName(self.grid_widget, "SBC - Відкрити файл", "", "Підтримувані файли (*.wav *.mp3 *.flac)")
if file_name is None:
return
if sound_type == 0: self.first_bell_file_text .setText(file_name)
elif sound_type == 1: self.second_bell_file_text.setText(file_name)
elif sound_type == 2: self.break_file_text .setText(file_name)
class SoundEditorBox(BasicBox):
def __init__(self, add_sound_callback, quit_callback):
super().__init__("Редактор звуку")
self.add_sound_callback = add_sound_callback
self.quit_callback = quit_callback
self.time_select_widget = WidgetArray(lambda _: None)
self.sound_name_input = QtWidgets.QLineEdit()
self.save_button = QtWidgets.QPushButton("Зберегти")
self.time_select_widget.add_button.clicked.connect(lambda: self.time_select_widget.add_item(QtWidgets.QTimeEdit()))
self.save_button.clicked.connect(self.save)
self.file_select_widget = QtWidgets.QWidget()
self.file_select_layout = QtWidgets.QHBoxLayout(self.file_select_widget)
self.file_name_select_text = QtWidgets.QLabel()
self.file_name_select_button = QtWidgets.QPushButton("Огляд")
self.file_name_select_button.clicked.connect(self.file_select_diag)
self.file_select_layout.addWidget(self.file_name_select_text)
self.file_select_layout.addWidget(self.file_name_select_button)
self.file_select_layout.addStretch(1)
self.layout.addWidget(self.sound_name_input)
self.layout.addWidget(self.time_select_widget)
self.layout.addWidget(self.file_select_widget)
self.layout.addStretch(1)
self.layout.addWidget(self.save_button)
self.edit_n = None
def file_select_diag(self):
file_name, _ = QtWidgets.QFileDialog.getOpenFileName(self.file_select_widget, "SBC - Відкрити файл", "", "Підтримувані файли (*.wav *.mp3 *.flac)")
if file_name is None:
return
self.file_name_select_text.setText(file_name)
def save(self):
self.add_sound_callback(
self.sound_name_input.text(),
[[item.time().hour(), item.time().minute()] for item in self.time_select_widget.get_items()],
self.file_name_select_text.text(),
self.edit_n
)
self.clear_edit()
self.quit_callback()
def clear_edit(self):
self.sound_name_input.setText("")
for i in range(self.time_select_widget.widget_list.count()):
self.time_select_widget.widget_list.takeItem(0)
self.edit_n = None