Академический Документы
Профессиональный Документы
Культура Документы
_____________________________________________
(наименование высшей школы / филиала / института / колледжа)
КУРСОВАЯ РАБОТА
Выполнил обучающийся:
Квашнин Александр Юрьевич
(Ф.И.О.)
Курс: 4
Группа: 353817
Руководитель:
Деменкова Е.А, доцент, к.т.н
(Ф.И.О. руководителя, должность / уч. степень / звание)
Архангельск 2022
МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ
федеральное государственное автономное образовательное учреждение
высшего образования
«Северный (Арктический) федеральный университет имени М.В. Ломоносова»
по Шаблонное программирование
(наименование дисциплины)
студенту ВШИТАС 4 курса 353817 группы
Квашнину Александру Юрьевичу
(фамилия, имя, отчество студента)
09.03.02 Информационные системы и технологии
(код и наименование направления подготовки/специальности)
ТЕМА: Использование паттернов при решении
задач профессиональной деятельности
4
1 ОБЗОР ПРЕДМЕТНОЙ ОБЛАСТИ
5
Также, как было написано ранее, оператор не имеет возможности пользоваться
функциями администратора, поэтому каждые функции необходимо разграничить по
ролям в системе.
6
2 ПРОЕКТИРОВАНИЕ И РЕАЛИЗАЦИЯ ШАБЛОНА
ПРОЕКТИРОВАНИЯ
7
Рассмотрим Диаграмму последовательности для добавления нового подразделения
в систему в соответствии с рисунком А.2.
В начале оператор открывает окно со всеми подразделениями в системе, после чего
вводит информацию о подразделении в соответствующие поля и нажимает кнопку
«Добавить». Система также учитывает, чтобы необходимые поля были заполнены верно,
например, в поле номер комнаты не может быть строка с текстом. После проверки на
валидность данных – данный кортеж загружается в модель данных. После чего в списке
подразделений появляется новое с введенными ранее данными.
Диаграмма классов представлена на рисунке А.3.
Диаграмма схемы данных представлена на рисунке А.4.
8
отличие от класса модели данных для SQL баз данных (например QSqlTableModel).
Поэтому для уведомления представлений об изменениях используется данный паттерн.
Воспользуемся паттернами «Memento» и «Action» - которые в совместном
использовании позволяют реализовать хранение снимков состояний модели данных и
отмену последних действий пользователем путем возвращения к предыдущему снимку
состояния.
3 РЕАЛИЗАЦИЯ ПРОГРАММНОГО ПРОДУКТА
9
Модели для хранения данных, которая также инициирует события изменения
самой себя;
Совмещенном контроллере и представлении, позволяющем пользователю
осуществлять взаимодействие с системой, а также реагировать на изменения в модели.
Приступим к реализации данных шаблонов.
Для этого, для начала - в VS Code создадим соответствующие модули – model.py и
view.py.
Приступим к созданию «Model» в шаблоне «MVC». Для этого в программном
модуле «model.py» создадим необходимые нам классы.
Создадим класс Subdivision. Класс Subdivision представляет собой описание
подразделения. Данный класс унаследован от object и содержит в себе:
- приватные атрибуты, такие как: «number_of_subdivision»,
«fullname_of_subdivision», «shortname_of_subdivision», «number_of_chamber», « supervisor
» , «financially_responsible»- номер, полное наименование, краткое наименование, номер
комнаты, руководитель и материально ответственное лицо соответственно;
- методы, возвращающие приватные атрибуты (геттеры) с декоратором
«@property».
Исходный код данного класса представлен на листинге 1.
Листинг 1 – Класс Subdivision
class Subdivision(object):
def __init__(self, number_of_subdivision,
fullname_of_subdivision,
shortname_of_subdivision,
number_of_chamber, supervisor,
financially_responsible):
self.__number_of_subdivision = number_of_subdivision
self.__fullname_of_subdivision = fullname_of_subdivision
self.__shortname_of_subdivision =
shortname_of_subdivision
self.__number_of_chamber = number_of_chamber
self.__supervisor = supervisor
self.__financially_responsible = financially_responsible
@property
def number_of_subdivision(self):
return self.__number_of_subdivision
@property
def fullname_of_subdivision(self):
return self.__fullname_of_subdivision
@property
def shortname_of_subdivision(self):
10
return self.__shortname_of_subdivision
@property
def number_of_chamber(self):
return self.__number_of_chamber
@property
def supervisor(self):
return self.__supervisor
@property
def financially_responsible(self):
return self.__financially_responsible
После чего создадим класс AbstractModel – реализующий паттерн «Observer».
Класс AbstractModel предназначен для извещения представлений об изменениях в
модели данных. Данный класс унаследован от object и содержит в себе:
- атрибут listeners – список вызываемых объектов;
- методы «addListener» и «removeListener» - добавление и удаление вызываемого
объекта соответственно;
- метод «update» - отвечает за извещение об изменениях.
Исходный код данного класса представлен на листинге 2.
Листинг 2 – Класс AbstractModel
class AbstractModel(object):
def __init__(self):
self.listeners = []
def update(self):
for eachFunc in self.listeners:
eachFunc(self)
После чего создадим класс Model.
Класс Model представляет собой описание модели данных. Данный класс отвечает
за хранение экземпляров классов и их обработку. Класс унаследован от класса
AbstractModel, описание и предназначение которого указано выше. Model в рамках
рассмотрения функции учета подразделений содержит в себе:
- приватные атрибуты, такие как: «listSubdivision» - список для хранения
экземпляров класса Subdivision;
- методы для добавления, изменения, удаления экземпляров классов из
соответствующих списков;
11
- методы для получения списков экземпляров классов;
- методы open_database и save_database, использующиеся для десериализации и
сериализации списков экземпляров классов с помощью модуля pickle.
Исходный код данного класса представлен в листинге 3.
Листинг 3 – Класс Model
class Model(AbstractModel):
"""Класс Model представляет собой описание модели данных"""
def __init__(self):
super(Model,self).__init__()
self.__listSubdivision=[]
self.queue = []
try:
self.open_database()
except:
self.save_database()
def open_database(self):
cort=ModelSerialize.deserialize()
self.__listEquipment = cort[0]
self.__listMove = cort[1]
self.__listStuff = cort[2]
self.__listSubdivision=cort[3]
self.__listMove = cort[4]
def newSubdivision(self,number_of_subdivision,
fullname_of_subdivision,
shortname_of_subdivision,
number_of_chamber, supervisor,
financially_responsible):
subdivision = Subdivision(number_of_subdivision,
fullname_of_subdivision,
shortname_of_subdivision,
number_of_chamber, supervisor,
financially_responsible)
self.__listSubdivision.append(subdivision)
self.update()
self.save_database()
12
self.__listSubdivision[index] = new
self.update()
self.save_database()
def deleteSubdivison(self,numb):
for item in self.__listEquipment:
if item.get_subdivision().number_of_subdivision ==
numb:
return False
def getAllSubdivision(self):
return self.__listSubdivision
После разработки программного модуля модели данных приступаем к
программному модулю представления. Для этого необходимо, в соответствии с
диаграммой классов, разработать пользовательский интерфейс для класса учета
подразделений. Разработанный интерфейс для учета подразделений представлен на
рисунке 1.
13
Рисунок 1 – Интерфейс представления учета подразделений
14
uic.loadUi("UI/view_subdivision.ui", self)
m.addListener(self.update)
self.update(m)
self.twSubdivision.setHorizontalHeaderLabels(("Номер;Полное
описание;Краткое описание;Номер
комнаты;Руководитель;МОЛ").split(";"))
self.btnAdd.clicked.connect(self.btn_Add_clicked)
self.btnEdit.clicked.connect(self.btn_Edit_clicked)
self.btnDel.clicked.connect(self.btnDelclicked)
self.twSubdivision.clicked.connect(self.on_tw_clicked)
def on_tw_clicked(self):
self.leFull.setText(self.twSubdivision.item(self.twSubdivision.c
urrentItem().row(),1).text())
self.leShDescr.setText(self.twSubdivision.item(self.twSubdivisio
n.currentItem().row(),2).text())
self.leNumberRoom.setText(self.twSubdivision.item(self.twSubdivi
sion.currentItem().row(),3).text())
self.leSupervisor.setText(self.twSubdivision.item(self.twSubdivi
sion.currentItem().row(),4).text())
self.leFin.setText(self.twSubdivision.item(self.twSubdivision.cu
rrentItem().row(),5).text())
def btn_Edit_clicked(self):
sh_descr = self.leShDescr.text()
f_descr = self.leFull.text()
numb_room= self.leNumberRoom.text()
sup = self.leSupervisor.text()
fin = self.leFin.text()
caretaker.backup()
m.updateSubdivision(int(self.twSubdivision.item(self.twSubdivisi
on.currentItem().row(),0).text()),f_descr,sh_descr,numb_room,sup
,fin)
def btnDelclicked(self):
caretaker.backup()
if
m.deleteSubdivison(int(self.twSubdivision.item(self.twSubdivisio
n.currentItem().row(),0).text()))==False:
15
QtWidgets.QMessageBox.warning(self,"Ошибка
удаления","Для того что бы удалить данное подазделение - сначала
удалитевсю связанную с ним вычислителью технику")
def btn_Add_clicked(self):
caretaker.backup()
sh_descr = self.leShDescr.text()
f_descr = self.leFull.text()
numb_room= self.leNumberRoom.text()
sup = self.leSupervisor.text()
fin = self.leFin.text()
twnumcols = len(m.getAllSubdivision())
if twnumcols == 0:
k=1
else:
k = int(self.twSubdivision.item(twnumcols-
1,0).text())+1
m.newSubdivision(k,f_descr,sh_descr, numb_room,sup,fin)
self.twSubdivision.setItem(index,0,QtWidgets.QTableWidgetItem(st
r(data[index].number_of_subdivision)))
self.twSubdivision.setItem(index,1,QtWidgets.QTableWidgetItem(st
r(data[index].fullname_of_subdivision)))
self.twSubdivision.setItem(index,2,QtWidgets.QTableWidgetItem(st
r(data[index].shortname_of_subdivision)))
self.twSubdivision.setItem(index,3,QtWidgets.QTableWidgetItem(st
r(data[index].number_of_chamber)))
self.twSubdivision.setItem(index,4,QtWidgets.QTableWidgetItem(st
r(data[index].supervisor)))
self.twSubdivision.setItem(index,5,QtWidgets.QTableWidgetItem(st
r(data[index].financially_responsible)))
16
Совместная реализация данных шаблонов позволяет хранить резервные копии
сложного состояния информационной системы и восстанавливать его, если потребуется.
Объекты команд выступают в роли опекунов и запрашивают снимки у
информационной системы перед тем, как выполнить своё действие. Если потребуется
отменить операцию, команда сможет восстановить состояние информационной системы,
используя сохранённый снимок.
При этом снимок не имеет публичных полей, поэтому другие объекты не имеют
доступа к его внутренним данным.
Для реализации данного паттерна нам необходимо доработать ранее созданные
«model.py» и «view.py».
В программном модуле модели данных создадим и опишем классы:
- Snapshot и DoSnapshot – интерфейс для снимка и класс снимка соответсвенно;
- CareTaker – опекун и реализация паттерна команда.
Исходный код данных классов представлен на листинге 5.
Листинг 5 – Классы Snapshot и Caretaker
class Snapshot(ABC):
@abstractmethod
def get_name(self) -> str:
pass
@abstractmethod
def get_date(self) -> str:
pass
class DoSnapshot(Snapshot):
def __init__(self, stateSubdivision) -> None:
self._stateSubdivision = stateSubdivision
self._date = str(datetime.now())[:19]
def get_state(self):
return self._stateSubdivision
class CareTaker():
def __init__(self, model: Model) -> None:
self._snapshots = []
self._model = model
17
def backup(self) -> None:
self._snapshots.append(self._model.save())
snapshot = self._snapshots.pop()
try:
self._model.restore(snapshot)
except Exception:
self.undo()
18
Перейдем к тестированию разработанных модулей. Запустим наш проект,
авторизуемся под учетной записью оператора и перейдем во вкладку «Подразделения».
Добавим несколько записей подразделений в систему. Результат отображен на рисунке 2.
19
Рисунок 3 – Проверка отмены предыдущего действия
20
ЗАКЛЮЧЕНИЕ
21
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1 BOUML [Electronic resource] / BOUML – Electronic text data – [Paris]: Pages Bruno,
2012. – Mode of access: https://www.bouml.fr/documentation.html, free access (02.10.2022). –
Title from screen
22
ПРИЛОЖЕНИЕ А
(обязательное)
UML - диаграммы
23
ПРИЛОЖЕНИЕ Б
(обязательное)
Исходный код разработанных программных модулей
class Stuff(object):
def __init__(self,id,login,password,position,name,surname) -> None:
self.__id = id
self.__login = login
self.__password = password
self.__position = position
self.__name = name
self.__surname = surname
@property
def get_id(self):
return self.__id
@property
def get_login(self):
return self.__login
@property
def get_password(self):
return self.__password
@property
def get_position(self):
return self.__position
@property
def get_name(self):
return self.__name
@property
def get_surname(self):
return self.__surname
class Subdivision(object):
def __init__(self, number_of_subdivision, fullname_of_subdivision,
shortname_of_subdivision,
number_of_chamber, supervisor,
financially_responsible):
self.__number_of_subdivision = number_of_subdivision
self.__fullname_of_subdivision = fullname_of_subdivision
self.__shortname_of_subdivision = shortname_of_subdivision
self.__number_of_chamber = number_of_chamber
self.__supervisor = supervisor
self.__financially_responsible = financially_responsible
@property
24
def number_of_subdivision(self):
return self.__number_of_subdivision
@property
def fullname_of_subdivision(self):
return self.__fullname_of_subdivision
@property
def shortname_of_subdivision(self):
return self.__shortname_of_subdivision
@property
def number_of_chamber(self):
return self.__number_of_chamber
@property
def supervisor(self):
return self.__supervisor
@property
def financially_responsible(self):
return self.__financially_responsible
class Equipment():
'''
Класс представляет собой описание вычислительной техники
'''
def __init__(self, subdivision:Subdivision, name_of_equipment='',
model_of_equipment='',
date_of_purchase=date.today(), inventory_number=0,
price_of_equipment=0):
self.__sub = subdivision
self.__name_of_equipment = name_of_equipment
self.__model_of_equipment = model_of_equipment
self.__date_of_purchase = date_of_purchase
self.__inventory_number = inventory_number
self.__price_of_equipment = price_of_equipment
def get_subdivision(self):
return self.__sub
def set_subdivion(self,val):
self.__sub = val
def get_inventory_number(self):
return self.__inventory_number
def get_name_of_equipment(self):
return self.__name_of_equipment
def get_model_of_equipment(self):
return self.__model_of_equipment
def get_date_of_purchase(self):
return self.__date_of_purchase
def get_price_of_equipment(self):
return self.__price_of_equipment
25
class move_equipment():
'''
Класс представления перемещения техники
'''
def __init__(self,equip, to_subdivision:Subdivision,
financially_responsible:Subdivision,to_chamber:Subdivision,from_subdivision:S
ubdivision,from_of_chamber:Subdivision, date_of_move=date.today()):
self.__eqip = equip
self.__to_subdivision = to_subdivision
self.__from_subdivision = from_subdivision
self.__from_of_chamber = from_of_chamber
self.__financially_responsible = financially_responsible
self.__to_chamber = to_chamber
self.__date_of_move = date_of_move
@property
def from_of_chamber(self):
return self.__from_of_chamber
@property
def to_chamber(self):
return self.__to_chamber
def get_equip(self):
return self.__eqip
def get_to_subdivision(self):
return self.__to_subdivision
def get_from_subdivision(self):
return self.__from_subdivision
def get_from_of_chamber(self):
return self.__from_of_chamber
def get_financially_responsible(self):
return self.__financially_responsible
def get_to_chamber(self):
return self.__to_chamber
def get_date_of_move(self):
return self.__date_of_move
class AbstractModel(object):
def __init__(self):
self.listeners = []
def update(self):
for eachFunc in self.listeners:
eachFunc(self)
class Snapshot(ABC):
26
@abstractmethod
def get_name(self) -> str:
pass
@abstractmethod
def get_date(self) -> str:
pass
class ModelSerialize(object):
"""Класс ModelSerialize предназначен для сериализации и десериалезации
модели данных"""
@staticmethod
def serialize(model):
with open('model.pkl', 'wb') as f:
pickle.dump(model,f)
f.closed
@staticmethod
def deserialize():
with open('model.pkl', 'rb') as f:
model = pickle.load(f)
f.closed
return model
class Model(AbstractModel):
def __init__(self):
super(Model,self).__init__()
self.__listStuff=[]
self.__listSubdivision=[]
self.__listEquipment=[]
self.__listMove=[]
self.queue = []
try:
self.open_database()
except:
self.save_database()
def open_database(self):
cort=ModelSerialize.deserialize()
self.__listEquipment = cort[0]
self.__listMove = cort[1]
self.__listStuff = cort[2]
self.__listSubdivision=cort[3]
self.__listMove = cort[4]
def save_database(self):
mod =
self.__listEquipment,self.__listMove,self.__listStuff,self.__listSubdivision,
self.__listMove;
ModelSerialize.serialize(mod)
27
if login == "root" and password == "root":
return "Success:Admin"
for item in self.__listStuff:
if item.get_login == login and item.get_password == password:
k = k + 1
if k==1:
return "Success:Operator"
if k == 0:
return "Error!"
def getAllStuff(self):
return self.__listStuff
self.queue.append(ModelTransaction(newstaff.__class__.__name__, id,
"upd").write())
break
self.update()
self.save_database()
28
if item.number_of_subdivision == old:
new = Subdivision(old, fullname_of_subdivision,
shortname_of_subdivision,
number_of_chamber, supervisor,
financially_responsible)
self.__listSubdivision[index] = new
self.update()
self.save_database()
def deleteSubdivison(self,numb):
for item in self.__listEquipment:
if item.get_subdivision().number_of_subdivision == numb:
return False
def getAllSubdivision(self):
return self.__listSubdivision
def newEquipment(self,sub,name_of_equipment,
model_of_equipment,date_of_purchase, inventory_number, price_of_equipment):
equipment = Equipment(sub,name_of_equipment,
model_of_equipment,date_of_purchase, inventory_number, price_of_equipment)
self.__listEquipment.append(equipment)
self.update()
self.save_database()
def getAllEquipment(self):
return self.__listEquipment
def getAllMove(self):
return self.__listMove
def save(self):
ls = self.__listStuff[:]
lsu = self.__listSubdivision[:]
leq = self.__listEquipment[:]
lm = self.__listMove[:]
self.update()
return DoSnapshot(ls,lsu,leq,lm)
29
self.__listStuff = cort[0]
self.__listSubdivision = cort[1]
self.__listEquipment = cort[2]
self.__listMove = cort[3]
self.update()
class ModelTransaction(object):
"""Класс ModelTransaction предназначен для учета транзакций в модели
данных"""
def __init__(self, obj, objid, do):
self.obj=obj
self.objid = objid
self.do = do
self.when = datetime.now()
def write(self):
f = open('modeltransaction.txt', 'a')
if self.do=="rem":
f.write('Когда: {0} : Удален экземпляр класса {1} - ID:{2} из
модели данных\n'.format(self.when, self.obj, self.objid))
f.closed
if self.do=="add":
f.write('Когда: {0} : Добавлен экземпляр класса {1} - ID:{2} из
модели данных \n'.format(self.when, self.obj, self.objid))
f.closed
if self.do=="upd":
f.write('Когда: {0} : Изменен экземпляр класса {1} - ID:{2} из
модели данных \n'.format(self.when, self.obj, self.objid))
f.closed
class DoSnapshot(Snapshot):
def __init__(self, stateStuff,stateSubdivision,stateEquipment,stateMove)
-> None:
self._stateStuff = stateStuff
self._stateSubdivision = stateSubdivision
self._stateEquipment = stateEquipment
self._stateMove = stateMove
self._date = str(datetime.now())[:19]
def get_state(self):
return
self._stateStuff,self._stateSubdivision,self._stateEquipment,self._stateMove;
class CareTaker():
30
def backup(self) -> None:
self._snapshots.append(self._model.save())
snapshot = self._snapshots.pop()
print(f"Caretaker: Restoring state to: {snapshot.get_name()}")
try:
self._model.restore(snapshot)
except Exception:
self.undo()
class loginView(QtWidgets.QDialog):
def __init__(self):
super(loginView, self).__init__()
uic.loadUi("UI/loginview.ui", self)
self.lePassword.setEchoMode(QtWidgets.QLineEdit.EchoMode.Password)
self.btnLogin.clicked.connect(self.btn_Login_clicked)
def btn_Login_clicked(self):
login = self.leLogin.text()
password = self.lePassword.text()
aut= m.authorization(login,password)
print(aut)
if aut == "Success:Admin":
self.adminpanel = adminView()
self.adminpanel.show()
if aut == "Success:Operator":
self.opreatorpanel = operatorView()
self.opreatorpanel.show()
if aut == "Error!":
msg = QtWidgets.QMessageBox(self)
msg.setText("В доступе отказано! Проверьте правильность вводимых
вами логина и пароля!")
msg.setWindowTitle("Ошибка вход")
msg.show()
class adminView(QtWidgets.QWidget):
31
def __init__(self):
super(adminView, self).__init__()
uic.loadUi("UI/adminview.ui", self)
m.addListener(self.update)
self.update(m)
self.twUsers.setHorizontalHeaderLabels(("Номер;Логин;Пароль;Должность;Имя;Фам
илия").split(";"))
self.btnAddUser.clicked.connect(self.btn_AddUser_clicked)
self.btnDeleteUser.clicked.connect(self.btn_DelUser_clicked)
self.btnUpdateUser.clicked.connect(self.btn_UpdateUser_clicked)
self.twUsers.clicked.connect(self.on_twUsers_clicked)
def btn_AddUser_clicked(self):
login = self.leLogin.text()
password = self.lePassword.text()
role = self.cbRole.currentText()
pozition = self.lePosition.text()
name = self.leName.text()
surname = self.leSurname.text()
twnumcols = len(m.getAllStuff())
if twnumcols == 0:
k=1
else:
k = int(self.twUsers.item(twnumcols-1,0).text())+1
m.newStuff(k,login,password,pozition,name,surname)
def btn_UpdateUser_clicked(self):
login = self.leLogin.text()
password = self.lePassword.text()
role = self.cbRole.currentText()
m.updateUser(int(self.twUsers.item(self.twUsers.currentItem().row(),0).text()
),login,password,role)
def btn_DelUser_clicked(self):
m.deleteUser(int(self.twUsers.item(self.twUsers.currentItem().row(),0).text()
))
def on_twUsers_clicked(self):
self.leLogin.setText(self.twUsers.item(self.twUsers.currentItem().row(),1).te
xt())
self.lePassword.setText(self.twUsers.item(self.twUsers.currentItem().row(),2)
.text())
self.lePosition.setText(self.twUsers.item(self.twUsers.currentItem().row(),3)
.text())
self.leName.setText(self.twUsers.item(self.twUsers.currentItem().row(),4).tex
t())
self.leSurname.setText(self.twUsers.item(self.twUsers.currentItem().row(),5).
text())
#self.cbRole.setCurrentText(self.twUsers.item(self.twUsers.currentItem().row(
),3).text())
32
def update(self, m):
data = m.getAllStuff()
numrows = len(data)
numcols = 6
self.twUsers.setColumnCount(numcols)
self.twUsers.setRowCount(numrows)
for index, item in enumerate(data):
self.twUsers.setItem(index,0,QtWidgets.QTableWidgetItem(str(data[index].get_i
d)))
self.twUsers.setItem(index,1,QtWidgets.QTableWidgetItem(str(data[index].get_l
ogin)))
self.twUsers.setItem(index,2,QtWidgets.QTableWidgetItem(str(data[index].get_p
assword)))
self.twUsers.setItem(index,3,QtWidgets.QTableWidgetItem(str(data[index].get_p
osition)))
self.twUsers.setItem(index,4,QtWidgets.QTableWidgetItem(str(data[index].get_n
ame)))
self.twUsers.setItem(index,5,QtWidgets.QTableWidgetItem(str(data[index].get_s
urname)))
class View_Subdivision(QtWidgets.QWidget):
def __init__(self):
super(View_Subdivision, self).__init__()
uic.loadUi("UI/view_subdivision.ui", self)
m.addListener(self.update)
self.update(m)
self.twSubdivision.setHorizontalHeaderLabels(("Номер;Полное
описание;Краткое описание;Номер комнаты;Руководитель;МОЛ").split(";"))
self.btnAdd.clicked.connect(self.btn_Add_clicked)
self.btnEdit.clicked.connect(self.btn_Edit_clicked)
self.btnDel.clicked.connect(self.btnDelclicked)
self.twSubdivision.clicked.connect(self.on_tw_clicked)
def on_tw_clicked(self):
self.leFull.setText(self.twSubdivision.item(self.twSubdivision.currentItem().
row(),1).text())
self.leShDescr.setText(self.twSubdivision.item(self.twSubdivision.currentItem
().row(),2).text())
self.leNumberRoom.setText(self.twSubdivision.item(self.twSubdivision.currentI
tem().row(),3).text())
self.leSupervisor.setText(self.twSubdivision.item(self.twSubdivision.currentI
tem().row(),4).text())
self.leFin.setText(self.twSubdivision.item(self.twSubdivision.currentItem().r
ow(),5).text())
33
def btn_Edit_clicked(self):
sh_descr = self.leShDescr.text()
f_descr = self.leFull.text()
numb_room= self.leNumberRoom.text()
sup = self.leSupervisor.text()
fin = self.leFin.text()
caretaker.backup()
m.updateSubdivision(int(self.twSubdivision.item(self.twSubdivision.currentIte
m().row(),0).text()),f_descr,sh_descr,numb_room,sup,fin)
def btnDelclicked(self):
caretaker.backup()
if
m.deleteSubdivison(int(self.twSubdivision.item(self.twSubdivision.currentItem
().row(),0).text()))==False:
QtWidgets.QMessageBox.warning(self,"Ошибка удаления","Для того
что бы удалить данное подазделение - сначала удалитевсю связанную с ним
вычислителью технику")
def btn_Add_clicked(self):
caretaker.backup()
sh_descr = self.leShDescr.text()
f_descr = self.leFull.text()
numb_room= self.leNumberRoom.text()
sup = self.leSupervisor.text()
fin = self.leFin.text()
twnumcols = len(m.getAllSubdivision())
if twnumcols == 0:
k=1
else:
k = int(self.twSubdivision.item(twnumcols-1,0).text())+1
m.newSubdivision(k,f_descr,sh_descr, numb_room,sup,fin)
self.twSubdivision.setItem(index,0,QtWidgets.QTableWidgetItem(str(data[index]
.number_of_subdivision)))
self.twSubdivision.setItem(index,1,QtWidgets.QTableWidgetItem(str(data[index]
.fullname_of_subdivision)))
self.twSubdivision.setItem(index,2,QtWidgets.QTableWidgetItem(str(data[index]
.shortname_of_subdivision)))
self.twSubdivision.setItem(index,3,QtWidgets.QTableWidgetItem(str(data[index]
.number_of_chamber)))
self.twSubdivision.setItem(index,4,QtWidgets.QTableWidgetItem(str(data[index]
.supervisor)))
34
self.twSubdivision.setItem(index,5,QtWidgets.QTableWidgetItem(str(data[index]
.financially_responsible)))
class View_Equipment(QtWidgets.QWidget):
def __init__(self):
super(View_Equipment, self).__init__()
uic.loadUi("UI/view_equipment.ui", self)
m.addListener(self.update)
self.update(m)
self.twEquip.setHorizontalHeaderLabels(("Инв.номер;Название;Модель;Дата
покупки;Цена;Кабинет").split(";"))
self.bAdd.clicked.connect(self.btn_Add_clicked)
def btn_Add_clicked(self):
sub = self.cbSub.currentText()
inv = self.leInv.text()
model = self.leModel.text()
name = self.leName.text()
d = self.deDate.date().toPyDate()
price = self.lePrice.text()
caretaker.backup()
for item in m.getAllSubdivision():
if str(item.number_of_subdivision)==sub:
tr_sub=item
m.newEquipment(tr_sub,name,model,d,inv,price)
self.twEquip.setItem(index,0,QtWidgets.QTableWidgetItem(str(data[index].get_i
nventory_number())))
self.twEquip.setItem(index,1,QtWidgets.QTableWidgetItem(str(data[index].get_n
ame_of_equipment())))
self.twEquip.setItem(index,2,QtWidgets.QTableWidgetItem(str(data[index].get_m
odel_of_equipment())))
self.twEquip.setItem(index,3,QtWidgets.QTableWidgetItem(str(data[index].get_d
ate_of_purchase())))
35
self.twEquip.setItem(index,4,QtWidgets.QTableWidgetItem(str(data[index].get_p
rice_of_equipment())))
self.twEquip.setItem(index,5,QtWidgets.QTableWidgetItem(str(data[index].get_s
ubdivision().number_of_chamber)))
class View_Move(QtWidgets.QWidget):
def __init__(self):
super(View_Move, self).__init__()
uic.loadUi("UI/view_move.ui", self)
m.addListener(self.update)
self.update(m)
self.twMove.setHorizontalHeaderLabels(("Дата;Инв.номер;Из
подразделения;Из кабинета;В подразделение;В кабинет;Новый МОЛ").split(";"))
self.bAdd.clicked.connect(self.btn_Add_clicked)
self.cbEquip.currentIndexChanged[str].connect(self.cb_Equip_Index_changed)
def cb_Equip_Index_changed(self,item_selected):
subs = m.getAllSubdivision()
inv = self.cbEquip.currentText()
eq = ""
for item in m.getAllEquipment():
if str(item.get_inventory_number()) == item_selected:
eq = item.get_subdivision().number_of_subdivision
self.cbTo.clear()
def btn_Add_clicked(self):
eq = self.cbEquip.currentText()
to_s = self.cbTo.currentText()
caretaker.backup()
m.newMoveEquipment(equip,to_sub,fin,to_ch,from_s,from_ch)
36
equip = m.getAllEquipment()
self.twMove.setItem(index,0,QtWidgets.QTableWidgetItem(str(data[index].get_da
te_of_move())))
self.twMove.setItem(index,1,QtWidgets.QTableWidgetItem(str(data[index].get_eq
uip().get_inventory_number())))
self.twMove.setItem(index,2,QtWidgets.QTableWidgetItem(str(data[index].get_fr
om_subdivision().number_of_subdivision)))
self.twMove.setItem(index,3,QtWidgets.QTableWidgetItem(str(data[index].get_fr
om_of_chamber().number_of_chamber)))
self.twMove.setItem(index,4,QtWidgets.QTableWidgetItem(str(data[index].get_to
_subdivision().number_of_subdivision)))
self.twMove.setItem(index,5,QtWidgets.QTableWidgetItem(str(data[index].get_to
_chamber().number_of_chamber)))
self.twMove.setItem(index,6,QtWidgets.QTableWidgetItem(str(data[index].get_fi
nancially_responsible().financially_responsible)))
class operatorView(QtWidgets.QWidget):
def __init__(self):
super(operatorView, self).__init__()
uic.loadUi("UI/operatorview.ui", self)
self.sub_v = View_Subdivision()
self.eq_v = View_Equipment()
self.m_v = View_Move()
self.btnRestore.clicked.connect(self.btnRestore_clicked)
def btnRestore_clicked(self):
caretaker.undo()
if __name__ == '__main__':
m = Model()
caretaker = CareTaker(m)
app = QtWidgets.QApplication(sys.argv)
window = loginView()
37
window.show()
app.exec()
38