Note that for compatability with Win7SP1, Pyside 6.1.3 and playsound 1.2.2 will be needed(instead of the latest versions).
277 lines
11 KiB
Python
277 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
|
||
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
|