SUAI-TaskPlanner-Contest / TaskPlanner

Client application for working with todos and syncing with CalDAV servers
MIT License
3 stars 2 forks source link

Создать класс-обработчик сигналов главного окна #84

Closed astronik00 closed 1 year ago

astronik00 commented 1 year ago

Developing Task

Требования: программист

Краткое описание

Создать класс Python, функции которого обрабатывали бы сигналы, приходящие с окна "Список задач" QML

Функциональные требования или документация

Пример создания классов-репозиториев:

from Code.repositories.task_repo import TaskRepository, ServerRepository
# объект session необходимо создать и импортировать

task_repo = TaskRepository[Task](session)
server_repo = ServerRepository[Server](session)

Пример создания сервиса caldav для сервера s, который является текущим элементом в ComboBox:

from Code.services.caldav_service import CalDavService

caldav_service = CalDavService(s)
Пример кода для выполнения задания Класс модели: ```python from PyQt6.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot from PyQt6.QtQml import QQmlListProperty from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from entities.db_entities import Server, Base from repositories.server_repo import ServerRepository engine = create_engine('sqlite:///./database/taskplanner.db', echo=False) # path to .db Base.metadata.create_all(engine) # create tables session = sessionmaker(bind=engine)() server_repo = ServerRepository(session) class ServerItem(QObject): nameChanged = pyqtSignal() def __init__(self, server, parent=None): QObject.__init__(self, parent) self.server = server @pyqtProperty('QString', notify=nameChanged) def server_name(self): return self.server.server_name class ServerComboBoxModel(QObject): itemChanged = pyqtSignal() itemsChanged = pyqtSignal() # list(map(lambda server: server.server_name, server_list)) def __init__(self, parent=None): QObject.__init__(self, parent) server_list = server_repo.get_all() self._items = list(map(lambda server: ServerItem(server), server_list)) self._item = self._items[0] @pyqtProperty(ServerItem, notify=itemChanged) def item(self): print("item_shit") return self._item @pyqtProperty(QQmlListProperty, notify=itemsChanged) def items(self): print("items_shit") return QQmlListProperty(ServerItem, self, self._items) ``` Окно QML: ```QML import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Controls.Material 2.15 import QtQuick.Layouts ApplicationWindow { // function getCurrentIndex(list, element) { // if (list && element) { // for (var i = 0; i < list.length; i++) { // if (list[i].name === element.name) { // console.log('Found item at pos: ' + i) // return i // } // } // } // return -1 // } visible: true width: 800 height: 400 title: "Date Picker Example" flags: Qt.FramelessWindowHint maximumHeight: height; maximumWidth: width minimumHeight: height; minimumWidth: width Rectangle { function getCurrentIndex(list, item) { console.log('Found item at pos: ' + i) for (var i = 0; i < list.length; i++) { if (list[i].server_name === item.server_name) { console.log('Found item at pos: ' + i) return i } } return -1 } id: tab width: parent.width height: parent.height visible: true ComboBox { id: combo width: parent.width * 0.5 model: server_model.items currentIndex: getCurrentIndex(server_model.items, server_model.item) onCurrentIndexChanged: server_model.item = model[currentIndex] textRole: 'server_name' } } } ```

Сигналы главного окна:

Смена элемента ComboBox
ComboBox необходимо наполнить списком серверов, в котором отображались бы лишь названия: ```python server_list = server_repo.get_all() # возвращает list[Server] ``` 1. Получить текущий сервер s из ComboBox 2. Считать все задачи, которые соответствуют этому серверу: ```python tasks_list = task_repo.get_all_by_server_id(s.server_id) # возвращает list[Task] на сервере s # или tasks_list = server_repo.get_tasks(s.server_id) # возвращает list[Task] на сервере s ``` 3. Загрузить новый список задач в отображение
Нажать кнопку "Плюс" сверху
![Image](https://user-images.githubusercontent.com/61901459/241247605-288578b4-a497-4a3c-a2d1-ad8dafb50af3.png) 1. Открытие пустой формы добавления задачи, у которой нет родителя, передать на форму текущий сервер s из Combobox серверов на панели сверху 2. Загрузить в combobox-ы "Статус", "Размер", "Тип", "Приоритет" данные из БД ```python priorities_list = server_repo.get_priorities(s.id) # возвращает list[Priority] status_list = server_repo.get_statuses(s.id) # возвращает list[Status] types_list = server_repo.get_types(s.id) # возвращает list[Type] sizes_list = server_repo.get_sizes(s.id) # возвращает list[Size] ``` 4. По кнопке "добавить" считать поля с формы 5. Создать объект task с полем task.parent=None 6. Добавить задачу в БД ```python task_repo.add(task) ``` 5. Обновить список задач в отображении
Нажать кнопку "Добавить" в троеточии
![Image](https://user-images.githubusercontent.com/61901459/241247987-dae867aa-e509-420b-97e4-e13a37aedc47.png) ![Image](https://user-images.githubusercontent.com/61901459/241248369-903f7297-3451-4cc1-9034-8d695928b75f.png) 1. Открытие пустой формы добавления задачи task, где была передана родительская задача parent_task, в строке которой была нажата кнопка добавления 2. По кнопке "добавить" считать поля с формы 3. Создать объект task с полем task.parent=parent_task 4. Добавить задачу в БД ```python task_repo.add(task) ``` 5. Обновить список задач в отображении
Нажать кнопку "Редактировать" в троеточии ![Image](https://user-images.githubusercontent.com/61901459/241247987-dae867aa-e509-420b-97e4-e13a37aedc47.png) ![Image](https://user-images.githubusercontent.com/61901459/241248852-13797d4a-244d-466a-a3ab-d62f8646e3a3.png) 1. Получить редактируемую задачу task (задача, у которой было нажато троеточие) 2. Открыть форму редактирования, загрузив на нее всю информацию о задаче 3. По нажатии на кнопку "Добавить", вызвать функции БД для сохранения результатов ```python task_repo.edit(task) ``` 4. Обновить список задач в отображении
Нажать кнопку "Удалить" в троеточии
![Image](https://user-images.githubusercontent.com/61901459/241247987-dae867aa-e509-420b-97e4-e13a37aedc47.png) ![Image](https://user-images.githubusercontent.com/61901459/241248772-7461e6bc-1c3b-4f91-95b5-5c363ddc1070.png) 1. Получить удаляемую задачу task. 2. Проверить, если у нее подзадачи ```python if len(task_repo.get_task_children_by_id(task.id)) != 0: # вызвать окно предупреждения # перейти в класс-обработчик сигналов с окна предупреждения # если нажать Продолжить, то удалить задачу, закрыть окно # если отмена, то ничего не делать, закрыть окно ``` Удаление задачи: ```python task_repo.delete(task) # или task_repo.delete_by_id(task.id) ```
Нажать кнопку "Синхронизация"
![Image](https://user-images.githubusercontent.com/61901459/241252392-e77da35c-3ec3-4c76-a775-3f3b3c1d0f8a.png) 1. Получить из отображения список задач task_list 2. В цикле попытаться отправить каждую задачу на сервер ```python conflicted_tasks = [] for task in task_list: conflicted_tasks.append(caldav_service.publish(task)) ``` 4. Сформировать список конфликтных задач conflicted_tasks 5. Пока len(conflicted_tasks) >0, для каждой задачи вызвать окно "Решения конфликтов", на которое передать этот список 6. Перейти в класс-обработчик Решения конфликтов 7. Решить конфликты


ВАЖНО

При изменении серверов из окна "Настройки", необходимо, чтобы обновлялся ComboBox на главном экране. Либо прямо из класса-обработчика окна "Настройки" как-то вызывать изменение содержимого ComboBox с "Списка задач", либо придумать какую-то функцию обновления содержимого, если БД изменилась. Например, при открытии главного окна каждый раз читались бы заново данные, ведь изменения могут происходить только при переходу между "Настройки" <-> "Список задач"

Обобщенное решение

Выходной результат

Класс-обработчик сигналов .py

Lailes commented 1 year ago

@slavakyrlan В этой ветке нет ресуров, что содержат иконки для кнопок. Добавь их пожалуйста

Lailes commented 1 year ago

@astronik00 Эта задача прям больша. В частности добавление и редактирование. Предлагаю разделить эту задачу на две, во второй будет добавление и редактирование. @aleksandra-shchegoleva А у тебя будет возможность подключиться к этой задаче (та что вторая половинка)?

aleksandra-shchegoleva commented 1 year ago

@Lailes Да, думаю. что с четверга-пятницы будет возможность подключиться к задаче

Lailes commented 1 year ago

@slavakyrlan Скинь пожалуйста ресурсы, ты не закоммитил и я не могу работать без них

slavakyrlan commented 1 year ago

Они находятся в папке QmlWindows/Resources 67 ветка Как ты написал сразу выложил туда