278 lines
11 KiB
Python
278 lines
11 KiB
Python
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
|
||
match sound_type:
|
||
case 0: self.first_bell_file_text .setText(file_name)
|
||
case 1: self.second_bell_file_text.setText(file_name)
|
||
case 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
|