Alex Sidorov 1 рік тому
коміт
002c88dec1
44 змінених файлів з 3868 додано та 0 видалено
  1. 2 0
      .env
  2. 13 0
      .gitignore
  3. 31 0
      PropuskWidgets/PLineEdit.py
  4. 13 0
      PropuskWidgets/VIdeoPhotoStackedWidgets.py
  5. 61 0
      docs/template_propusk.html
  6. 68 0
      docs/template_propusk_back.html
  7. BIN
      image/no_media.jpg
  8. BIN
      image/no_media_main.jpg
  9. 28 0
      init_var.py
  10. 32 0
      main.py
  11. 37 0
      module/CleanerImage.py
  12. 22 0
      module/ImageTool.py
  13. 71 0
      module/ModelPropusk.py
  14. 13 0
      module/MyMessageBox.py
  15. 3 0
      module/MyMessageBox.pyi
  16. 14 0
      module/Printer.py
  17. 16 0
      module/TemplatePropusk.py
  18. 116 0
      module/WorkWithCam.py
  19. 79 0
      module/WorkWithDB.py
  20. 3 0
      module/__init__.py
  21. 8 0
      module/lang/ru.py
  22. 6 0
      req.txt
  23. 11 0
      window/DialogAbout.py
  24. 42 0
      window/DialogCustomVariables.py
  25. 87 0
      window/DialogHistory.py
  26. 54 0
      window/DialogSettingCam.py
  27. 118 0
      window/ListPersonal.py
  28. 103 0
      window/ListPlace.py
  29. 242 0
      window/MainWindow.py
  30. 120 0
      window/ui/DialogAbout.ui
  31. 104 0
      window/ui/DialogCustomVariables.ui
  32. 39 0
      window/ui/DialogHistory.ui
  33. 193 0
      window/ui/DialogListPersonal.ui
  34. 112 0
      window/ui/DialogListPlace.ui
  35. 87 0
      window/ui/DialogSettingCam.ui
  36. 440 0
      window/ui/MainWindow.ui
  37. 516 0
      window/ui/MainWindow_back.ui
  38. 92 0
      window/ui_py/ui_DialogAbout.py
  39. 92 0
      window/ui_py/ui_DialogCustomVariables.py
  40. 61 0
      window/ui_py/ui_DialogHistory.py
  41. 161 0
      window/ui_py/ui_DialogListPersonal.py
  42. 115 0
      window/ui_py/ui_DialogListPlace.py
  43. 101 0
      window/ui_py/ui_DialogSettingCam.py
  44. 342 0
      window/ui_py/ui_MainWindow.py

+ 2 - 0
.env

@@ -0,0 +1,2 @@
+DB_DIR=/home/asidorov/Документы/propusk_db 
+PHOTO_DIR=/home/asidorov/Изображения/propusk 

+ 13 - 0
.gitignore

@@ -0,0 +1,13 @@
+.venv
+__pycache__
+./test
+test
+test2.py
+test.html
+docx_example.py
+Propusk.spec
+dist
+PySide6
+Propusk_linux/
+.vscode
+build

+ 31 - 0
PropuskWidgets/PLineEdit.py

@@ -0,0 +1,31 @@
+from PySide6.QtWidgets import QLineEdit
+from PySide6.QtGui import QRegularExpressionValidator
+from datetime import datetime
+from PySide6.QtCore import Slot
+
+
+class PLineEdit(QLineEdit):
+    def __init__(self, parent=None):
+        super(PLineEdit, self).__init__(parent)
+        self.setValidator(QRegularExpressionValidator(
+            r"\d{14}", self
+        ))
+        self._create_id()
+        
+        self.textChanged.connect(
+            self._create_id
+        )
+        
+        self.textEdited.connect(
+            self._create_id
+        )
+        
+        self.cursorPositionChanged.connect(
+            self._create_id
+        )
+        
+    def clear(self) -> None:
+        self._create_id()
+
+    def _create_id(self) -> None:
+        self.setText(datetime.now().strftime("%Y%m%d%H%M%S"))

+ 13 - 0
PropuskWidgets/VIdeoPhotoStackedWidgets.py

@@ -0,0 +1,13 @@
+from PySide6.QtWidgets import QStackedWidget, QWidget, QLabel
+
+class StackedWidget(QStackedWidget):
+    def __init__(self, parent=None):
+        super(StackedWidget, self).__init__(parent)
+        
+        self.addWidget()
+    
+    def setup_image_stacked(self) -> None:
+        ...    
+        
+    def setup_video_stacked(self) -> None:
+        ...    

+ 61 - 0
docs/template_propusk.html

@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+</head>
+
+<body style="padding: 0; margin: 0; font-size: 12pt">
+    {% for _ in range(2) %}
+    <table>
+        <tbody>
+            <tr>
+                <td><b>Временный пропуск №:</b> {{ id_propusk }}</td>
+                <td rowspan="12">
+                    <img src="{{ face_photo }}" width="200" height="300"/>
+                </td>
+            </tr>
+            <tr>
+                <td><b>Дата выдачи:</b> {{ date_from }}</td>
+                
+            </tr>
+            <tr>
+                <td><b>Действителен до:</b> {{ date_to }}</td>
+            </tr>
+            <tr>
+                <td><b>Выдал:</b> {{ personal }}</td>
+            </tr>
+            <tr>
+                <td>
+                    <p style="font-size: 12pt;">__________________________________</p>
+                    <p style="font-size: 10pt !important;">&nbsp;&nbsp;Подпись сотрудника бюро пропусков</p>
+                    <p style="font-size: 10pt !important;">&nbsp;&nbsp;Печать</p>
+                </td>
+            </tr>
+            <tr>
+                <td><b>Место выдачи:</b> {{ place }}</td>
+            </tr>
+            <tr>
+                <td><b>Принимающий:</b></td>
+            </tr>
+            <tr>
+                <td>{{ receiving_man }}</td>
+            </tr>
+            <tr>
+                <td><b>Цель визита:</b></td>
+            </tr>
+            <tr> 
+                <td>{{ purpose_visite }}</td></tr>
+            <tr>
+                <td><b>Время выхода: __________________</b></td>
+            </tr>
+        </tbody>
+    </table>
+    <hr>
+    {% endfor %}
+</body>
+
+</html>

+ 68 - 0
docs/template_propusk_back.html

@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+</head>
+
+<body style="padding: 0; margin: 0; font-size: 12pt">
+    {% for _ in range(2) %}
+    <table >
+        <tbody>
+            <tr>
+                <td><b>Временный пропуск №:</b> {{ id_propusk }}</td>
+                <td rowspan="5">
+                    <img id="img_face" src="{{ face_photo }}" height="200" width="300"/>
+                </td>
+            </tr>
+            <tr>
+                <td><b>Дата выдачи:</b> {{ date_from }}</td>
+                <td></td>
+            </tr>
+            <tr>
+                <td><b>Действителен до:</b> {{ date_to }}</td>
+            </tr>
+            <tr>
+                <td><b>Выдал:</b> {{ personal }}</td>
+            </tr>
+            <tr>
+                <td>
+                    <p style="font-size: 12pt;">__________________________________</p>
+                    <p style="font-size: 10pt !important;">&nbsp;&nbsp;Подпись сотрудника бюро пропусков</p>
+                    <p style="font-size: 10pt !important;">&nbsp;&nbsp;Печать</p>
+                </td>
+                <td></td>
+                
+            </tr>
+            <tr height="200" width="300">
+                <td><b>Место выдачи:</b>{{ place }}</td>
+                <td rowspan="6">
+                    <img id="img_pasport" src="{{ pasport_photo }}" height="200" width="300" />
+                </td>
+            </tr>
+            <tr>
+                <td><b>Принимающий:</b></td>
+            </tr>
+            <tr>
+                <td>{{ receiving_man }}</td>
+            </tr>
+            <tr>
+                <td><b>Цель визита:</b></td>
+            </tr>
+            <tr> 
+                <td>{{ purpose_visite }}</td></tr>
+            <tr>
+                <td><b>Время выхода: __________________</b></td>
+            </tr>
+        </tbody>
+    </table>
+    <br>
+    <hr>
+    <br>
+    {% endfor %}
+</body>
+
+</html>

BIN
image/no_media.jpg


BIN
image/no_media_main.jpg


+ 28 - 0
init_var.py

@@ -0,0 +1,28 @@
+import os
+import os
+import appdirs
+from dotenv import load_dotenv
+from window.DialogCustomVariables import DialogCustomVariables
+
+
+__VERSION = "ver 0.1 beta"
+DEFAULT_PATH = os.path.join(appdirs.user_data_dir(), "propusk")
+DEFAULT_PATH_PHOTO = os.path.join(DEFAULT_PATH, "photo")
+
+os.environ['VERSION'] = __VERSION
+# os.environ['DEFAULT_PATH'] = DEFAULT_PATH
+# os.environ['PHOTO_DIR'] = DEFAULT_PATH_PHOTO
+os.environ['ABSOLUTE_PATH'] = os.path.dirname(os.path.abspath(__file__))
+os.environ['NO_MEDIA_IMAGE'] = os.path.join(os.environ.get('ABSOLUTE_PATH'),
+                                            'image', 'no_media_main.jpg')
+os.environ['INDEX_PHOTO'] = '0'
+os.environ['INDEX_CAMERA'] = '1'
+
+def load_variables():
+    # Load variable from .env
+    dotenv_path = os.path.join(os.path.dirname(__file__), '.env')
+
+    if not os.path.exists(dotenv_path):
+        DialogCustomVariables(dotenv_path).exec_()
+    
+    load_dotenv(dotenv_path=dotenv_path)

+ 32 - 0
main.py

@@ -0,0 +1,32 @@
+from init_var import *
+import os
+import sys
+
+from PySide6.QtWidgets import QApplication
+# from appdirs import user_data_dir 
+
+
+
+def main():
+    app = QApplication(sys.argv)
+    
+    load_variables()
+    
+    from module.WorkWithDB import init_db    
+    from module.CleanerImage import CleanerImage
+    from window.MainWindow import MainWindow
+    
+    init_db()
+    
+    CleanerImage(os.environ.get('PHOTO_DIR')) \
+        .clear()
+    
+    
+    window = MainWindow()
+    window.show()
+
+    sys.exit(app.exec())
+
+
+if __name__ == "__main__":
+    main()

+ 37 - 0
module/CleanerImage.py

@@ -0,0 +1,37 @@
+from .WorkWithDB import connect, list_propusk
+from sqlalchemy import select
+from appdirs import user_data_dir
+import os
+
+
+class CleanerImage:
+    def __init__(self, path: str):
+        self._path = path
+        
+        if os.path.exists(path):    
+            self._files_in_db = self._get_list_files_from_db()
+        else:
+            raise ValueError(F"Не корректный путь: {path}")
+
+    def _get_list_files_from_db(self) -> list:
+        with connect() as conn:
+            list_files = select(
+                list_propusk.c.face_photo,
+                list_propusk.c.pasport_photo
+            ).select_from(list_propusk)
+            return sum([[self._only_file(x[0]), self._only_file(x[0])]
+                        for x in conn.execute(list_files).all()], [])
+
+    def _only_file(self, path: str) -> str:
+        if '/' in path:
+            return path.split('/')[-1]
+        else:
+            return path.split('\\')[-1]
+
+    def clear(self) -> None:
+        _, _, files = os.walk(self._path).__next__()
+        for file in files:
+            if file not in self._files_in_db:
+                os.remove(os.path.join(self._path, file))
+                print(F"Удален файл: {os.path.join(self._path, file)}")
+

+ 22 - 0
module/ImageTool.py

@@ -0,0 +1,22 @@
+from PIL import Image, UnidentifiedImageError
+import os
+
+def rotate_image(path_file: str, gradus: int = -90) -> str:
+    try:
+        image = Image.open(path_file, 'r')
+        rotate_path_image = os.path.join(
+            os.path.dirname(image.filename),
+            F"rotate_{os.path.split(image.filename)[1]}"
+        )
+    
+        rotate_img = image.rotate(gradus, expand=True)
+        rotate_img.save(rotate_path_image)
+    
+        return rotate_path_image
+    except FileNotFoundError:
+        print(F"Файл не найден: {path_file=}")
+        return None
+    except UnidentifiedImageError:
+        print(F"Не правильный формат: {path_file=}")
+        return None
+

+ 71 - 0
module/ModelPropusk.py

@@ -0,0 +1,71 @@
+from datetime import datetime
+from dataclasses import dataclass
+
+
+def key_error(func):
+
+    def wrapper(*args, **kwargs):
+        try:
+            return func(*args, **kwargs)
+        except KeyError:
+            print("Ключ не правильный")
+
+    return wrapper
+
+
+@dataclass
+class Personal:
+    id: int
+    name: str
+
+
+@dataclass
+class Place:
+    id: int
+    name: str
+
+
+@dataclass
+class PropuskData:
+    id_propusk: int
+    date_from: datetime
+    date_to: datetime
+    personal: Personal
+    place: Place
+    receiving_man: str
+    purpose_visite: str
+    face_photo: str
+
+
+class PropuskDataMethods:
+    def __init__(self, id_propusk: int = None,
+                 date_from: datetime = None,
+                 date_to: datetime = None,
+                 personal: Personal = None,
+                 place: Place = None,
+                 receiving_man: str = None,
+                 purpose_visite: str = None,
+                 face_photo: str = None):
+
+        self._propusk_data = PropuskData(id_propusk,
+                                         date_from,
+                                         date_to,
+                                         personal,
+                                         place,
+                                         receiving_man,
+                                         purpose_visite,
+                                         face_photo)
+
+    @key_error
+    def set_value(self, key: str, value: str | int | datetime | Personal | Place):
+        #Пустышка если ключа не существует выкенет из функции
+        self._propusk_data.__dict__[key] 
+        self._propusk_data.__dict__[key] = value
+
+    @key_error
+    def get_value(self, key):
+        return self._propusk_data.__dict__[key]
+
+    def checking_empty_values(self) -> bool:
+        return all(self._propusk_data.__dict__.values())
+

+ 13 - 0
module/MyMessageBox.py

@@ -0,0 +1,13 @@
+from PySide6.QtWidgets import QMessageBox
+
+def show_dialog(state: QMessageBox.Icon, title: str, massage: str):
+   msgBox = QMessageBox()
+   msgBox.setIcon(state)
+   msgBox.setText(massage)
+   msgBox.setWindowTitle(title)
+   msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
+#    msgBox.buttonClicked.connect(msgButtonClick)
+
+   returnValue = msgBox.exec()
+   if returnValue == QMessageBox.Ok:
+      print('OK clicked')

+ 3 - 0
module/MyMessageBox.pyi

@@ -0,0 +1,3 @@
+from PySide6.QtWidgets import QMessageBox
+    
+def show_dialog(state: QMessageBox.Icon, title: str, massage: str): ...

+ 14 - 0
module/Printer.py

@@ -0,0 +1,14 @@
+from PySide6.QtWidgets import QTextEdit, QDialog
+from PySide6.QtPrintSupport import QPrintDialog, QPrinter
+
+
+class Printer:
+    def __init__(self, text: str) -> None:
+        self.printer = QPrinter()
+        self.editor = QTextEdit()
+        self.editor.setHtml(text)
+
+    def print(self) -> None:
+        dialog = QPrintDialog(self.printer)
+        if dialog.exec_() == QDialog.Accepted:
+            self.editor.document().print_(dialog.printer())

+ 16 - 0
module/TemplatePropusk.py

@@ -0,0 +1,16 @@
+from jinja2 import Environment, FileSystemLoader
+
+
+class TemplatePropusk:
+    def __init__(self, obj: any, env_dir: str, name_file: str = "template_propusk.html"):
+        self._env = Environment(loader=FileSystemLoader(env_dir))
+        self._obj = obj
+        self._rederer_text = self._env.get_template(name_file).render(
+            self._obj
+        )
+
+    def __str__(self) -> str:
+        return self._rederer_text
+    
+    def get_object(self) -> any:
+        return self._obj

+ 116 - 0
module/WorkWithCam.py

@@ -0,0 +1,116 @@
+import sys
+import os
+
+from PySide6.QtMultimediaWidgets import QVideoWidget
+from PySide6.QtCore import Slot, Qt
+from PySide6.QtGui import QImage, QPixmap
+from PySide6.QtWidgets import QLabel
+from PySide6.QtMultimedia import (
+    QMediaDevices, QCamera, QImageCapture, QMediaCaptureSession)
+from appdirs import user_data_dir
+from datetime import datetime
+from itertools import groupby
+
+if os.environ.get("PHOTO_DIR"):
+    IMAGES_PATH = os.environ.get("PHOTO_DIR")
+else:
+    raise ValueError(
+        "не задана локальная переменная PHOTO_DIR"
+    )
+
+
+class WorkWithCam:
+    def __init__(self, q_Video_Widget: QVideoWidget, name_cam: str) -> None:
+        self._create_dirs()
+
+        self._capture_session = None
+        self._camera = None
+        self._camera_info = None
+        self._image_capture = None
+        self._video_widget = q_Video_Widget
+
+        self._camera_info = get_object_cam_by_name(name_cam)
+        if not self._camera_info:
+            raise IndexError(
+                f"Не нашли камеру QMediaDevices.videoInputs(). убидитесь, что у вас есть камера")
+
+        self._file_name = self.get_filename()
+
+    def start_cam(self):
+        self._camera = QCamera(self._camera_info)
+        self._camera.errorOccurred.connect(self._camera_error)
+        self._image_capture = QImageCapture(self._camera)
+        self._image_capture.imageCaptured.connect(self.image_captured)
+        self._image_capture.imageSaved.connect(self.image_saved)
+        self._image_capture.errorOccurred.connect(self._capture_error)
+        self._capture_session = QMediaCaptureSession()
+        self._capture_session.setCamera(self._camera)
+        self._capture_session.setImageCapture(self._image_capture)
+
+        if self._camera and self._camera.error() == QCamera.NoError:
+            # print()
+            name = self._camera_info.description()
+            self._capture_session.setVideoOutput(self._video_widget)
+            self._camera.start()
+        else:
+            print("Camera unavailable")
+
+    def stop_cam(self) -> None:
+        if self._camera and self._camera.isActive():
+            self._camera.stop()
+
+    def __del__(self) -> None:
+        self.stop_cam()
+
+    def cupture_image(self) -> str:
+        self._current_preview = QImage()
+        self._image_capture.captureToFile(self._file_name)
+        return self._file_name
+
+    @Slot(int, QImageCapture.Error, str)
+    def _capture_error(self, id, error, error_string):
+        print(error_string, file=sys.stderr)
+        self.show_status_message(error_string)
+
+    @Slot(QCamera.Error, str)
+    def _camera_error(self, error, error_string):
+        print(error_string, file=sys.stderr)
+        self.show_status_message(error_string)
+
+    @staticmethod
+    def get_filename() -> str:
+        return F"{IMAGES_PATH}/propusk_{datetime.now().timestamp()}.jpg"
+
+    def _create_dirs(self):
+        if not os.path.exists(IMAGES_PATH):
+            os.mkdir(IMAGES_PATH)
+
+    @Slot(int, QImage)
+    def image_captured(self, id, previewImage):
+        self._current_preview = previewImage
+
+    @Slot(int, str)
+    def image_saved(self, id, fileName):
+        ...
+
+    def show_status_message(self, message):
+        print(message, 5000)
+
+
+def load_image(qlabel: QLabel, path_file: str) -> None:
+    qlabel.setPixmap(QPixmap(QImage(path_file)).scaled(
+        qlabel.width()-4,
+        qlabel.height(),
+        Qt.AspectRatioMode.KeepAspectRatio,
+        Qt.TransformationMode.FastTransformation
+    ))
+
+
+def get_list_name_cam() -> list:
+    return [x for x, _ in groupby(
+        [x.description() for x in QMediaDevices.videoInputs()]
+    )]
+
+def get_object_cam_by_name(name_cam: str) -> QMediaDevices:
+    return [x for x in QMediaDevices.videoInputs() if x.description() == name_cam][0]
+    

+ 79 - 0
module/WorkWithDB.py

@@ -0,0 +1,79 @@
+from sqlalchemy import (MetaData, Table, Column, Integer,
+                        DateTime, String, Text, ForeignKey,
+                        create_engine, func)
+import os
+from module.MyMessageBox import show_dialog
+from PySide6.QtWidgets import QMessageBox
+
+meta = MetaData()
+
+FILE_NAME = None
+if os.environ.get("DB_DIR"):
+    FILE_NAME = os.path.join(os.environ.get("DB_DIR"), "propusk.db")
+else:
+    if os.environ.get("DEFAULT_PATH"):
+        FILE_NAME = os.path.join(os.environ.get("DEFAULT_PATH"), "propusk.db")
+    else:
+        show_dialog(
+            QMessageBox.Icon.Critical,
+            "Путь к бд",
+            "Не правильно указан путь к базе данных, или вообще отсутствует"
+        )
+        raise ValueError(F"Не правильно указан путь к базе данных, или вообще отсутствует")
+    
+print("q", FILE_NAME)
+    
+cam_setting = Table("сam_setting", meta,
+                    Column('id', Integer, primary_key=True),
+                    Column("selected_cam", String, nullable=False),
+                    Column('created', DateTime, default=func.now()),
+                    Column('update', DateTime,
+                           onupdate=func.current_timestamp())
+                    )
+
+list_personal = Table("list_personal", meta,
+                      Column('id', Integer, primary_key=True),
+                      Column('lastname', String, nullable=False),
+                      Column('firstname', String, nullable=False),
+                      Column('middlename', String, nullable=False),
+                      Column('created', DateTime, default=func.now()),
+                      Column('update', DateTime,
+                             onupdate=func.current_timestamp())
+                      )
+
+list_place = Table("list_place", meta,
+                   Column('id', Integer, primary_key=True),
+                   Column('name_place', String, nullable=False),
+                   Column('created', DateTime, default=func.now()),
+                   Column('update', DateTime, onupdate=func.current_timestamp())
+                   )
+
+list_propusk = Table("list_propusk", meta,
+                     Column("id", Integer, primary_key=True),
+                     Column("id_propusk", Integer, nullable=False),
+                     Column("date_from", DateTime, nullable=False),
+                     Column("date_to", DateTime, nullable=False),
+                     Column("personal", Integer, ForeignKey("list_personal.id"), nullable=False),
+                     Column("place", Integer, ForeignKey("list_place.id"), nullable=False),
+                     Column("receiving_man", Text, nullable=False),
+                     Column("purpose_visite", Text, nullable=False),
+                     Column("face_photo", Text, nullable=False),
+                     Column("pasport_photo", Text, nullable=False),
+                     Column("created", DateTime, default=func.now()),
+                     Column("update", DateTime, default=func.now(),
+                            onupdate=func.current_timestamp()))
+
+
+engine = create_engine(F"sqlite:///{FILE_NAME}", echo=True)
+
+
+def init_db():
+    print(FILE_NAME)
+    if not os.path.exists(os.path.dirname(FILE_NAME)):
+        os.mkdir(os.path.dirname(FILE_NAME))
+
+    meta.create_all(engine)
+
+
+def connect():
+    return engine.connect()

+ 3 - 0
module/__init__.py

@@ -0,0 +1,3 @@
+# from .lang.ru import ru
+
+# langu = ru()

+ 8 - 0
module/lang/ru.py

@@ -0,0 +1,8 @@
+
+start_cam = "Запустить камеру"
+stop_cam = "Остановить камеру"
+
+warring_cams = dict(
+    title = "Камеры не настроины",
+    body = "Настройте камеры \nНастройки -> Настройки камеры"
+)

+ 6 - 0
req.txt

@@ -0,0 +1,6 @@
+appdirs==1.4.4
+Jinja2==3.1.2
+PySide6==6.4.1
+SQLAlchemy==1.4.45
+python-dotenv==0.21.0
+Pillow==9.4.0

+ 11 - 0
window/DialogAbout.py

@@ -0,0 +1,11 @@
+from .ui_py.ui_DialogAbout import Ui_DialogAbout
+from PySide6.QtWidgets import QDialog
+from PySide6.QtCore import Qt
+import os
+
+class DialogAbout(QDialog, Ui_DialogAbout):
+    def __init__(self, parent=None):
+        super(DialogAbout, self).__init__(parent)
+        self.setAttribute(Qt.WA_DeleteOnClose)
+        self.setupUi(self)
+        self.version.setText(os.environ.get("VERSION"))

+ 42 - 0
window/DialogCustomVariables.py

@@ -0,0 +1,42 @@
+from .ui_py.ui_DialogCustomVariables import Ui_DialogCustomVariables
+from PySide6.QtWidgets import QDialog, QFileDialog, QMessageBox
+from PySide6.QtCore import Qt
+from module.MyMessageBox import show_dialog
+
+
+class DialogCustomVariables(Ui_DialogCustomVariables, QDialog):
+    def __init__(self, parent: str = None) -> None:
+        self.path_env = parent
+        super(DialogCustomVariables, self).__init__()
+        self.setAttribute(Qt.WA_DeleteOnClose)
+        self.setupUi(self)
+
+        self.btn_show_path_photo.clicked.connect(
+            self._show_path_photo
+        )
+
+        self.btn_show_path_database.clicked.connect(
+            self._show_path_database
+        )
+
+        self.btn_save.clicked.connect(
+            self._save
+        )
+
+    def _show_path_photo(self) -> None:
+        dir = str(QFileDialog.getExistingDirectory(None, "Selected Directory"))
+        self.path_photo.setText(dir)
+
+    def _show_path_database(self) -> None:
+        dir = str(QFileDialog.getExistingDirectory(None, "Selected Directory"))
+        self.path_db.setText(dir)
+
+    def _save(self) -> None:
+        with open(self.path_env, 'w+') as file:
+            file.write(F"DB_DIR={self.path_db.text()} \n")
+            file.write(F"PHOTO_DIR={self.path_photo.text()} \n")
+
+        show_dialog(QMessageBox.Icon.Information,
+                    "Успешно!",
+                    "Сохранения произошло успешно!")
+        self.close()

+ 87 - 0
window/DialogHistory.py

@@ -0,0 +1,87 @@
+from PySide6.QtWidgets import QDialog
+from PySide6.QtCore import Slot
+from .ui_py.ui_DialogHistory import Ui_DialogHistory
+from module.WorkWithDB import connect, list_propusk, list_personal, list_place
+from sqlalchemy import select, func
+from module.ModelPropusk import PropuskDataMethods
+from module.TemplatePropusk import TemplatePropusk
+import os
+from module.ImageTool import rotate_image
+# from PySide6.QtGui import QStandardItemModel
+
+
+class DialogHistory(Ui_DialogHistory, QDialog):
+    def __init__(self, parent=None):
+        super(DialogHistory, self).__init__(parent)
+        self.setupUi(self)
+        self.line_search.textChanged.connect(
+            self.filter_items
+        )
+        self.list_propusk.itemSelectionChanged.connect(
+            self.selected_item
+        )
+
+        self.load_data()
+
+        self.list_propusk.setCurrentRow(0)
+
+    def selected_item(self) -> None:
+        try:
+            id_propusk = self.list_propusk.selectedItems()[0].text()
+            self.load_page(int(id_propusk))
+        except IndexError:
+            self.browser.clear()
+
+    @Slot(str)
+    def filter_items(self, text: str) -> None:
+        for index in range(self.list_propusk.count()):
+            item = self.list_propusk.item(index)
+            if text:
+                item.setHidden(not self.match_text(text, item.text()))
+            else:
+                item.setHidden(False)
+
+    def match_text(self, text, keywords) -> None:
+        return text in keywords
+
+    def load_data(self) -> None:
+        with connect() as conn:
+            rows = conn.execute(
+                list_propusk.select()) \
+                .all()
+
+            for line in rows:
+                self.list_propusk.addItem(str(line.id_propusk))
+
+    def load_page(self, id_propusk: int) -> None:
+        with connect() as conn:
+            row = conn.execute(
+                select(
+                    list_propusk.c.id_propusk,
+                    list_propusk.c.date_from,
+                    list_propusk.c.date_to,
+                    func.format(
+                        list_personal.c.lastname
+                        + " " + list_personal.c.firstname
+                        + " " + list_personal.c.middlename)
+                    .label("personal"),
+                    func.format(list_place.c.name_place).label("place"),
+                    list_propusk.c.receiving_man,
+                    list_propusk.c.purpose_visite,
+                    list_propusk.c.face_photo
+                ).select_from(list_propusk).join(
+                    list_personal, list_propusk.c.personal == list_personal.c.id
+                ).where(list_propusk.c.id_propusk == id_propusk)
+            ).fetchone()
+
+            pdm = PropuskDataMethods(*row)
+            pdm.set_value("face_photo",
+                          rotate_image(pdm.get_value("face_photo"))
+                          )
+            
+            render_text = str(TemplatePropusk(pdm._propusk_data.__dict__,
+                                              os.path.join(os.path.dirname(
+                                                  os.path.abspath(__package__)), 'docs')
+                                              ))
+
+            self.browser.setText(render_text)

+ 54 - 0
window/DialogSettingCam.py

@@ -0,0 +1,54 @@
+from .ui_py.ui_DialogSettingCam import Ui_DialogSettingCam
+from PySide6.QtWidgets import QDialog
+from PySide6.QtCore import Qt, Slot
+from PySide6.QtMultimedia import QMediaDevices
+from module.WorkWithCam import WorkWithCam, get_list_name_cam, load_image
+from module.WorkWithDB import *
+
+class SettingCam(QDialog, Ui_DialogSettingCam):
+    def __init__(self, parent=None) -> None:
+        super(SettingCam, self).__init__(parent)
+        self.setAttribute(Qt.WA_DeleteOnClose)
+        self.setupUi(self)
+        
+        self.load_cams()
+        load_image(self.image, os.environ.get("NO_MEDIA_IMAGE"))      
+        self.chacked_cam_face.clicked.connect(self._open_cam_face)
+        self.stop_cam_face.clicked.connect(self._close_cam_face)
+        self.save_setting_cam.clicked.connect(self._save_setting_cam)
+
+    def load_cams(self) -> None:
+        for name in get_list_name_cam():
+            self.face_list_cam.addItem(name)
+        self.load_cams_from_db()
+
+    def _save_setting_cam(self) -> None:
+        self.save_cams(self.face_list_cam.currentText())
+
+    def _open_cam_face(self) -> None:
+        self.stackedWidget.setCurrentIndex(int(os.environ.get('INDEX_CAMERA')))
+        self._cam_face = WorkWithCam(
+            self.video, self.face_list_cam.currentText())
+        self._cam_face.start_cam()
+
+    def _close_cam_face(self) -> None:
+        if self._cam_face:
+            self.stackedWidget.setCurrentIndex(int(os.environ.get('INDEX_PHOTO')))
+        del self._cam_face
+
+    def load_cams_from_db(self):
+        with connect() as conn:
+            result = conn.execute(cam_setting.select()).fetchone()
+            if result:
+                self.face_list_cam.setCurrentText(result.selected_cam)
+                
+    def save_cams(self, description_cam: str) -> None:
+        query = None
+        with connect() as conn:
+            result = conn.execute(cam_setting.select()).fetchone()
+            if result is None:
+                query = cam_setting.insert().values(selected_cam=description_cam)
+            else:
+                query = cam_setting.update().where(
+                    cam_setting.c.id == 1).values(selected_cam=description_cam)
+            result = conn.execute(query)

+ 118 - 0
window/ListPersonal.py

@@ -0,0 +1,118 @@
+from .ui_py.ui_DialogListPersonal import Ui_DialogListPersonal
+from module.WorkWithDB import connect, list_personal
+from module.MyMessageBox import show_dialog
+
+from PySide6.QtWidgets import QDialog, QListWidgetItem, QMessageBox
+from PySide6.QtCore import Qt, Slot
+
+
+
+class ListPersonal(QDialog, Ui_DialogListPersonal):
+    def __init__(self, update_listbox_func, parent=None) -> None:
+        super(ListPersonal, self).__init__(parent)
+        self.setAttribute(Qt.WA_DeleteOnClose)
+        self.setupUi(self)
+        self.update_listbox_func = update_listbox_func
+        self.btn_save_personal.clicked.connect(self._save)
+        self.btn_update_personal.clicked.connect(self._update)
+        self.btn_delete_personal.clicked.connect(self._delete)
+
+        self.list_personal_widget.itemSelectionChanged.connect(
+            self._selected_item)
+        self._load_data()
+        
+
+    @Slot()
+    def _save(self) -> None:
+        if any([
+            self.lastname.text(),
+            self.firstname.text(),
+            self.middlename.text()]):
+            with connect() as conn:
+                insert_personal = list_personal.insert().values(
+                 lastname=self.lastname.text(),
+                firstname=self.firstname.text(),
+                middlename=self.middlename.text()
+                )
+                conn.execute(insert_personal)
+
+            self._clean_line_edit()
+            self._load_data()
+        else:
+            show_dialog(
+                    QMessageBox.Warning,
+                    title="Пустые поля",
+                    massage="Заполните все поля!"
+                )
+            
+    def _clean_line_edit(self):
+        self.lastname.clear()
+        self.firstname.clear()
+        self.middlename.clear()
+
+    @Slot()
+    def _update(self) -> None:
+        with connect() as conn:
+            update_personal = list_personal.update().where(
+                list_personal.c.id == self.selected_id
+            ).values(
+                lastname=self.lastname.text(),
+                firstname=self.firstname.text(),
+                middlename=self.middlename.text()
+            )
+
+            conn.execute(update_personal)
+        self._clean_line_edit()
+        self._load_data()
+
+    @Slot()
+    def _delete(self) -> None:
+        with connect() as conn:
+            if hasattr(self, 'selected_id'):
+                conn.execute(
+                    list_personal.delete().where(
+                        list_personal.c.id == self.selected_id)
+                )
+            else:
+                show_dialog(
+                    QMessageBox.Warning,
+                    title="Не выбран элемент списка",
+                    massage="Выбирите элемент списка перед тем как удалять!"
+                )
+
+        self._clean_line_edit()
+        self._load_data()
+
+    @Slot()
+    def _selected_item(self) -> None:
+        try:
+            id = self.list_personal_widget.selectedItems()[0].id
+            self.selected_id = int(id)
+            with connect() as conn:
+                personal = list_personal.select().where(
+                    list_personal.c.id == id)
+                personal_from_db = conn.execute(personal).fetchone()
+
+                self.lastname.setText(personal_from_db.lastname)
+                self.firstname.setText(personal_from_db.firstname)
+                self.middlename.setText(personal_from_db.middlename)
+
+        except IndexError:
+            self._clean_line_edit()
+
+    def _load_data(self) -> None:
+        self.list_personal_widget.clear()
+        with connect() as conn:
+            for personal in conn.execute(list_personal.select()).all():
+                self.list_personal_widget.addItem(self._create_item(
+                    id=personal.id,
+                    lastname=personal.lastname,
+                    firstname=personal.firstname,
+                    middlename=personal.middlename
+                ))
+
+    def _create_item(self, id, lastname, firstname, middlename) -> None:
+        item = QListWidgetItem(F"{lastname} {firstname} {middlename}")
+        item.id = id
+        return item
+    

+ 103 - 0
window/ListPlace.py

@@ -0,0 +1,103 @@
+from .ui_py.ui_DialogListPlace import Ui_DialogListPlace
+from PySide6.QtWidgets import QDialog, QListWidgetItem
+from PySide6.QtCore import Qt, Slot
+from module.WorkWithDB import connect, list_place
+
+
+class ListPlace(QDialog, Ui_DialogListPlace):
+    def __init__(self, parent=None) -> None:
+        super(ListPlace, self).__init__(parent)
+        self.setAttribute(Qt.WA_DeleteOnClose)
+        self.setupUi(self)
+    
+        self.btn_save_place.clicked.connect(self._save)
+        self.btn_update_place.clicked.connect(self._update)
+        self.btn_delete_place.clicked.connect(self._delete)
+
+        self.list_place_widget.itemSelectionChanged.connect(
+            self._select_item
+        )
+
+        self._load_data()
+
+    @Slot()
+    def _save(self) -> None:
+        with connect() as conn:
+            insert_place = list_place.insert().values(
+                name_place = self.line_name_place.text()
+            )
+            
+            conn.execute(insert_place)
+        
+        self._clean_line_edit()
+        self._load_data()
+
+    @Slot()
+    def _update(self) -> None:
+        if hasattr(self, "selected_id"):
+            with connect() as conn:
+                update_place = list_place.update().where(
+                    list_place.c.id == self.selected_id
+                ).values(
+                    name_place = self.line_name_place.text()
+                )
+                
+                conn.execute(update_place)
+
+            self._clean_line_edit()
+            self._load_data()
+        
+        
+    @Slot()
+    def _delete(self) -> None:
+        if hasattr(self, "selected_id"):
+            with connect() as conn:
+                conn.execute(
+                    list_place.delete().where(
+                        list_place.c.id == self.selected_id
+                    )
+                )
+        
+            self._clean_line_edit()
+            self._load_data()
+                
+
+    def _clean_line_edit(self) -> None:
+        self.line_name_place.clear()
+        
+        
+    @Slot()
+    def _select_item(self) -> None:
+        try:
+            id = self.list_place_widget.selectedItems()[0].id
+            self.selected_id = int(id)
+            
+            with connect() as conn:
+                place = list_place.select().where(
+                    list_place.c.id == id)
+                
+                place_from_db = conn.execute(place).fetchone()
+                self.line_name_place.setText(place_from_db.name_place)
+                
+        except IndexError:
+            self._clean_line_edit()
+
+    @Slot()
+    def _load_data(self) -> None:
+        self.list_place_widget.clear()
+        
+        with connect() as conn:
+            for place in conn.execute(
+                list_place.select()
+            ).all():
+                self.list_place_widget.addItem(
+                    self._create_item(
+                        id=place.id,
+                        name_place=place.name_place
+                    )
+                )
+
+    def _create_item(self, id: int, name_place: str) -> None:
+        item = QListWidgetItem(name_place)
+        item.id = id
+        return item

+ 242 - 0
window/MainWindow.py

@@ -0,0 +1,242 @@
+from PySide6.QtWidgets import QMainWindow, QMessageBox
+from PySide6.QtCore import Slot, QDate, QDateTime
+
+from module.WorkWithDB import *
+from module.MyMessageBox import show_dialog
+from module.WorkWithCam import WorkWithCam, load_image
+from module.TemplatePropusk import TemplatePropusk
+from module.Printer import Printer
+from module.lang.ru import *
+from module.ImageTool import rotate_image
+# from module.ModelPropusk import *
+
+
+from .ui_py.ui_MainWindow import Ui_MainWindow
+from .ListPersonal import ListPersonal
+from .ListPlace import ListPlace
+from .DialogSettingCam import SettingCam
+from .DialogAbout import DialogAbout
+from .DialogHistory import DialogHistory
+
+
+from time import sleep
+from datetime import datetime
+
+
+class MainWindow(QMainWindow, Ui_MainWindow):
+    def __init__(self, parent=None) -> None:
+        super(MainWindow, self).__init__(parent)
+        self.setupUi(self)
+
+        self.date_from.setDateTime(QDateTime().currentDateTime())
+        self.date_to.setDateTime(QDateTime().currentDateTime())
+
+        self.stacked_widget_photo.currentChanged.connect(
+            self.current_change_photo
+        )
+
+        self._init_menu_btn_action()
+        self._init_push_btn_action()
+        self._update_list_combobox()
+        self._check_setting_cam()
+        self._init_photo()
+
+    def open_history(self) -> None:
+        DialogHistory(self).exec_()
+
+    def current_change_photo(self):
+        if self.stacked_widget_photo.currentIndex() == os.environ.get('INDEX_CAMERA'):
+            self.btn_start_cam_photo.setText(stop_cam)
+        else:
+            self.btn_start_cam_photo.setText(start_cam)
+
+    def _init_menu_btn_action(self) -> None:
+        self.action_open_history.triggered.connect(self.open_history)
+        self.btn_show_personal_window.triggered.connect(
+            self._show_personal_window
+        )
+        self.btn_show_place_window.triggered.connect(
+            self._show_place_window
+        )
+        self.setting_cam.triggered.connect(
+            self._show_setting_cam_window
+        )
+        self.update_list.triggered.connect(
+            self._update_list_combobox
+        )
+
+        self.btn_show_about.triggered.connect(
+            self._show_about_dialog
+        )
+
+    def _show_about_dialog(self):
+        DialogAbout(self).exec_()
+
+    def _check_setting_cam(self) -> None:
+        if not self._get_selected_cam():
+            show_dialog(
+                QMessageBox.Warning,
+                warring_cams.get("title"),
+                warring_cams.get("body")
+            )
+
+    def _init_push_btn_action(self) -> None:
+        self.btn_start_cam_photo.clicked.connect(
+            self._start_cam_photo
+        )
+
+        self.capturePhoto.clicked.connect(
+            self._take_image_face
+        )
+
+        self.btn_save.clicked.connect(self._save)
+        self.btn_clear.clicked.connect(self._clear)
+        self.btn_print.clicked.connect(self._print)
+
+    def _show_personal_window(self) -> None:
+        ListPersonal(self).exec_()
+        self._update_list_combobox()
+
+    @Slot()
+    def _show_place_window(self) -> None:
+        ListPlace(self).exec_()
+        self._update_list_combobox()
+
+    @Slot()
+    def _show_setting_cam_window(self) -> None:
+        SettingCam(self).exec_()
+
+    def _update_list_combobox(self) -> None:
+        self._load_personal()
+        self._load_place()
+
+    def _load_personal(self) -> None:
+        self.personal_combobox.clear()
+
+        with connect() as conn:
+            for personal in conn.execute(
+                list_personal.select()
+            ).all():
+                fio = F"{personal.lastname} {personal.firstname} {personal.middlename}"
+                self.personal_combobox.addItem(
+                    fio,
+                    userData={"id": personal.id}
+                )
+
+    def _load_place(self) -> None:
+        self.place_combobox.clear()
+
+        with connect() as conn:
+            for place in conn.execute(
+                list_place.select()
+            ).all():
+                self.place_combobox.addItem(
+                    place.name_place,
+                    userData={"id": place.id}
+                )
+
+    def _get_selected_cam(self) -> bool | str:
+        with connect() as conn:
+            cam = conn.execute(
+                cam_setting.select()
+            ).fetchone()
+
+            try:
+                return cam.selected_cam
+            except:
+                return False
+
+    def _init_photo(self) -> None:
+        load_image(self.imagePhoto, os.environ.get('NO_MEDIA_IMAGE'))
+
+    @Slot()
+    def _start_cam_photo(self) -> None:
+        if self._get_selected_cam():
+            if self.stacked_widget_photo.currentIndex() == int(os.environ.get('INDEX_PHOTO')):
+                self.stacked_widget_photo.setCurrentIndex(int(os.environ.get('INDEX_CAMERA')))
+                self.face_wwc = WorkWithCam(
+                    q_Video_Widget=self.face_video_widget,
+                    name_cam=self._get_selected_cam()
+                )
+
+                self.face_wwc.start_cam()
+            else:
+                self._del_wwc("face_wwc", 1)
+                self.stacked_widget_photo.setCurrentIndex(int(os.environ.get('INDEX_PHOTO')))
+
+    @Slot()
+    def _take_image_face(self):
+        if hasattr(self, "face_wwc"):
+            self.face_file_name = self.face_wwc.cupture_image()
+            self.stacked_widget_photo.setCurrentIndex(int(os.environ.get('INDEX_PHOTO')))
+            self._del_wwc("face_wwc", 1)
+            load_image(self.imagePhoto, self.face_file_name)
+
+    @Slot()
+    def _print(self) -> None:
+        if not hasattr(self, "data_propusk"):
+            self._save()
+
+        propusk_data = self.data_propusk.copy()
+        propusk_data["personal"] = self.personal_combobox.currentText()
+        propusk_data["place"] = self.place_combobox.currentText()
+        propusk_data["date_from"] = self.date_from.dateTime().toString(
+            'dd.MM.yyyy hh:mm')
+        propusk_data["date_to"] = self.date_to.dateTime().toString(
+            'dd.MM.yyyy hh:mm')
+
+        rotate_img = rotate_image(self.face_file_name, -90)
+        propusk_data["face_photo"] = F"file://{rotate_img}"
+
+        render_text = str(TemplatePropusk(propusk_data,
+                                          os.path.join(os.environ.get('ABSOLUTE_PATH'), 'docs')
+                                          ))
+
+        Printer(
+            render_text
+        ).print()
+
+    @Slot()
+    def _clear(self) -> None:
+        if hasattr(self, "data_propusk"):
+            del self.data_propusk
+
+        self._set_default_data()
+
+    @Slot()
+    def _save(self) -> None:
+        date_from = self.date_from.dateTime().toMSecsSinceEpoch() / 1000
+        date_to = self.date_to.dateTime().toMSecsSinceEpoch() / 1000
+
+        self.data_propusk = {
+            "id_propusk": int(self.number_propusk.text()),
+            "date_from": datetime.fromtimestamp(date_from),
+            "date_to": datetime.fromtimestamp(date_to),
+            "personal": self.personal_combobox.currentData()['id'],
+            "place": self.place_combobox.currentData()['id'],
+            "receiving_man": self.receiving_man.toPlainText(),
+            "purpose_visite": self.purpose_visite.toPlainText(),
+            "face_photo": F"file://{self.face_file_name}",
+            "pasport_photo": F"file://{self.face_file_name}"
+        }
+
+        with connect() as conn:
+            conn.execute(
+                list_propusk.insert().values(**self.data_propusk)
+            )
+
+    def _set_default_data(self):
+        self.number_propusk.clear()
+        self.date_from.setDate(QDate().currentDate())
+        self.date_to.setDate(QDate().currentDate())
+        self._init_photo()
+        self.receiving_man.clear()
+        self.purpose_visite.clear()
+
+        if hasattr(self, "face_wwc"):
+            self._del_wwc("face_wwc", 1)
+            self.stacked_widget_photo.setCurrentIndex(int(os.environ.get('INDEX_PHOTO')))
+
+    def _del_wwc(self, attr, second: int = 0) -> None:
+        sleep(second)
+        delattr(self, attr)

+ 120 - 0
window/ui/DialogAbout.ui

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogAbout</class>
+ <widget class="QDialog" name="DialogAbout">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>456</width>
+    <height>295</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>О Программе</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="font">
+      <font>
+       <pointsize>30</pointsize>
+       <bold>true</bold>
+      </font>
+     </property>
+     <property name="text">
+      <string>Propusk</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="version">
+     <property name="text">
+      <string>TextLabel</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer_2">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>10</width>
+       <height>5</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="label_3">
+       <property name="text">
+        <string>Git:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>10</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QLabel" name="label_4">
+       <property name="minimumSize">
+        <size>
+         <width>400</width>
+         <height>0</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>&lt;a href=&quot;https://tj.kbsu.ru/AlexSidorov/propusk&quot;&gt;https://tj.kbsu.ru/AlexSidorov/propusk&lt;/a&gt;</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>67</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>@ KBSU</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 104 - 0
window/ui/DialogCustomVariables.ui

@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogCustomVariables</class>
+ <widget class="QDialog" name="DialogCustomVariables">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>590</width>
+    <height>228</height>
+   </rect>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>590</width>
+    <height>228</height>
+   </size>
+  </property>
+  <property name="maximumSize">
+   <size>
+    <width>590</width>
+    <height>228</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Изначальные настройки</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Директория с фотографиями</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QLineEdit" name="path_photo"/>
+      </item>
+      <item>
+       <widget class="QPushButton" name="btn_show_path_photo">
+        <property name="text">
+         <string>Открыть путь к директории</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="title">
+      <string>Директория с базой данных</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout_2">
+      <item>
+       <widget class="QLineEdit" name="path_db"/>
+      </item>
+      <item>
+       <widget class="QPushButton" name="btn_show_path_database">
+        <property name="text">
+         <string>Открыть путь к директории</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QPushButton" name="btn_save">
+     <property name="text">
+      <string>Сохранить</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer_2">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 39 - 0
window/ui/DialogHistory.ui

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogHistory</class>
+ <widget class="QDialog" name="DialogHistory">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>935</width>
+    <height>543</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Список</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QLineEdit" name="line_search"/>
+      </item>
+      <item>
+       <widget class="QListWidget" name="list_propusk"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QTextBrowser" name="browser"/>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 193 - 0
window/ui/DialogListPersonal.ui

@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogListPersonal</class>
+ <widget class="QDialog" name="DialogListPersonal">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>640</width>
+    <height>480</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_3">
+   <item row="0" column="0">
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Список сотрудников</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="QListWidget" name="list_personal_widget"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="title">
+      <string>Управление</string>
+     </property>
+     <property name="flat">
+      <bool>false</bool>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0">
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_2">
+          <item>
+           <widget class="QLabel" name="label">
+            <property name="text">
+             <string>Фамилия</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="horizontalSpacer">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="lastname_2">
+            <property name="minimumSize">
+             <size>
+              <width>250</width>
+              <height>0</height>
+             </size>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_3">
+          <item>
+           <widget class="QLabel" name="label_2">
+            <property name="text">
+             <string>Имя</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="horizontalSpacer_2">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>50</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="firstname">
+            <property name="minimumSize">
+             <size>
+              <width>250</width>
+              <height>0</height>
+             </size>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_4">
+          <item>
+           <widget class="QLabel" name="label_3">
+            <property name="text">
+             <string>Отчетво</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="horizontalSpacer_3">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="middlename">
+            <property name="minimumSize">
+             <size>
+              <width>250</width>
+              <height>0</height>
+             </size>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QVBoxLayout" name="verticalLayout">
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout">
+            <item>
+             <widget class="QPushButton" name="btn_save_personal">
+              <property name="text">
+               <string>Сохранить</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="btn_update_personal">
+              <property name="text">
+               <string>Обновить</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <widget class="QPushButton" name="btn_delete_personal">
+            <property name="text">
+             <string>Удалить</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="verticalSpacer">
+            <property name="orientation">
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>40</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 112 - 0
window/ui/DialogListPlace.ui

@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogListPlace</class>
+ <widget class="QDialog" name="DialogListPlace">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>640</width>
+    <height>480</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_3">
+   <item row="0" column="0">
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Список мест выдачи</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="QListWidget" name="list_place_widget"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QGroupBox" name="groupBox_2">
+     <property name="title">
+      <string>Управление</string>
+     </property>
+     <property name="flat">
+      <bool>false</bool>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0">
+       <layout class="QVBoxLayout" name="verticalLayout_2">
+        <item>
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <item>
+           <widget class="QLabel" name="label">
+            <property name="text">
+             <string>Наименование места выдачи:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="line_name_place">
+            <property name="minimumSize">
+             <size>
+              <width>250</width>
+              <height>0</height>
+             </size>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QVBoxLayout" name="verticalLayout">
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout">
+            <item>
+             <widget class="QPushButton" name="btn_save_place">
+              <property name="text">
+               <string>Сохранить</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="btn_update_place">
+              <property name="text">
+               <string>Обновить</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <widget class="QPushButton" name="btn_delete_place">
+            <property name="text">
+             <string>Удалить</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="verticalSpacer">
+            <property name="orientation">
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>40</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 87 - 0
window/ui/DialogSettingCam.ui

@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DialogSettingCam</class>
+ <widget class="QDialog" name="DialogSettingCam">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>640</width>
+    <height>480</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Фото лица</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_3">
+      <item row="0" column="0">
+       <widget class="QComboBox" name="face_list_cam"/>
+      </item>
+      <item row="2" column="0">
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QPushButton" name="chacked_cam_face">
+          <property name="text">
+           <string>Проверить</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="stop_cam_face">
+          <property name="text">
+           <string>Остановить</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item row="1" column="0">
+       <widget class="QStackedWidget" name="stackedWidget">
+        <widget class="QWidget" name="page_3">
+         <layout class="QGridLayout" name="gridLayout_2">
+          <item row="0" column="0">
+           <widget class="QLabel" name="image">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+        <widget class="QWidget" name="page_4">
+         <layout class="QGridLayout" name="gridLayout_4">
+          <item row="0" column="0">
+           <widget class="QVideoWidget" name="video"/>
+          </item>
+         </layout>
+        </widget>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QPushButton" name="save_setting_cam">
+     <property name="text">
+      <string>Сохранить настройки</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QVideoWidget</class>
+   <extends>QLabel</extends>
+   <header>PySide6.QtMultimediaWidgets</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

+ 440 - 0
window/ui/MainWindow.ui

@@ -0,0 +1,440 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="windowModality">
+   <enum>Qt::WindowModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>920</width>
+    <height>511</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="baseSize">
+   <size>
+    <width>864</width>
+    <height>430</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Временный пропуск</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <property name="enabled">
+    <bool>true</bool>
+   </property>
+   <property name="sizePolicy">
+    <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+     <horstretch>0</horstretch>
+     <verstretch>0</verstretch>
+    </sizepolicy>
+   </property>
+   <property name="focusPolicy">
+    <enum>Qt::NoFocus</enum>
+   </property>
+   <property name="autoFillBackground">
+    <bool>false</bool>
+   </property>
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QGroupBox" name="groupBox">
+      <property name="minimumSize">
+       <size>
+        <width>400</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="title">
+       <string>Информация:</string>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <item>
+          <widget class="QLabel" name="label">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="text">
+            <string>Временный пропуск №:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="number_propusk">
+           <property name="inputMask">
+            <string/>
+           </property>
+           <property name="text">
+            <string/>
+           </property>
+           <property name="maxLength">
+            <number>32767</number>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <item>
+          <widget class="QLabel" name="label_2">
+           <property name="text">
+            <string>Дата и время выдачи:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QDateTimeEdit" name="date_from">
+           <property name="dateTime">
+            <datetime>
+             <hour>21</hour>
+             <minute>0</minute>
+             <second>0</second>
+             <year>1999</year>
+             <month>12</month>
+             <day>31</day>
+            </datetime>
+           </property>
+           <property name="timeSpec">
+            <enum>Qt::UTC</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_3">
+         <item>
+          <widget class="QLabel" name="label_4">
+           <property name="text">
+            <string>Действителене до:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QDateTimeEdit" name="date_to"/>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_4">
+         <item>
+          <widget class="QLabel" name="label_3">
+           <property name="text">
+            <string>Выдал:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="personal_combobox"/>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_5">
+         <item>
+          <widget class="QLabel" name="label_5">
+           <property name="text">
+            <string>Место выдачи:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="place_combobox"/>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" name="verticalLayout">
+         <item>
+          <widget class="QLabel" name="label_6">
+           <property name="text">
+            <string>Принимающий:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QTextEdit" name="receiving_man"/>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" name="verticalLayout_2">
+         <item>
+          <widget class="QLabel" name="label_7">
+           <property name="text">
+            <string>Цель визита:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QTextEdit" name="purpose_visite"/>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="0" column="1" colspan="2">
+     <widget class="QGroupBox" name="groupBox_2">
+      <property name="title">
+       <string>Фото</string>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_4">
+       <item>
+        <widget class="QStackedWidget" name="stacked_widget_photo">
+         <property name="enabled">
+          <bool>true</bool>
+         </property>
+         <property name="toolTip">
+          <string notr="true"/>
+         </property>
+         <property name="statusTip">
+          <string/>
+         </property>
+         <widget class="QWidget" name="page">
+          <layout class="QGridLayout" name="gridLayout_2">
+           <item row="0" column="0">
+            <widget class="QLabel" name="imagePhoto">
+             <property name="enabled">
+              <bool>true</bool>
+             </property>
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="frameShape">
+              <enum>QFrame::Box</enum>
+             </property>
+             <property name="frameShadow">
+              <enum>QFrame::Raised</enum>
+             </property>
+             <property name="text">
+              <string/>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+         <widget class="QWidget" name="page_2">
+          <layout class="QGridLayout" name="gridLayout_4">
+           <item row="0" column="0">
+            <widget class="QVideoWidget" name="face_video_widget">
+             <property name="enabled">
+              <bool>false</bool>
+             </property>
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+       </item>
+       <item>
+        <widget class="QSplitter" name="splitter">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <widget class="QPushButton" name="btn_start_cam_photo">
+          <property name="text">
+           <string>Запустить камеру</string>
+          </property>
+         </widget>
+         <widget class="QPushButton" name="capturePhoto">
+          <property name="text">
+           <string>Сфотографировать</string>
+          </property>
+         </widget>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="1" column="0">
+     <widget class="QPushButton" name="btn_clear">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="text">
+       <string>Отчистить</string>
+      </property>
+     </widget>
+    </item>
+    <item row="1" column="1">
+     <widget class="QPushButton" name="btn_save">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="text">
+       <string>Сохранить</string>
+      </property>
+     </widget>
+    </item>
+    <item row="1" column="2">
+     <widget class="QPushButton" name="btn_print">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="text">
+       <string>Печать</string>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>920</width>
+     <height>23</height>
+    </rect>
+   </property>
+   <property name="mouseTracking">
+    <bool>true</bool>
+   </property>
+   <property name="acceptDrops">
+    <bool>true</bool>
+   </property>
+   <property name="nativeMenuBar">
+    <bool>true</bool>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>File</string>
+    </property>
+    <addaction name="separator"/>
+    <addaction name="actionSave"/>
+    <addaction name="actionLoad"/>
+    <addaction name="btn_show_about"/>
+    <addaction name="separator"/>
+    <addaction name="exit"/>
+   </widget>
+   <widget class="QMenu" name="menu">
+    <property name="title">
+     <string>Настроки</string>
+    </property>
+    <widget class="QMenu" name="menu_3">
+     <property name="title">
+      <string>Списки</string>
+     </property>
+     <addaction name="separator"/>
+     <addaction name="separator"/>
+     <addaction name="btn_show_personal_window"/>
+     <addaction name="btn_show_place_window"/>
+     <addaction name="separator"/>
+     <addaction name="update_list"/>
+    </widget>
+    <addaction name="setting_cam"/>
+    <addaction name="menu_3"/>
+   </widget>
+   <widget class="QMenu" name="menu_2">
+    <property name="title">
+     <string>История</string>
+    </property>
+    <addaction name="action_open_history"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menu"/>
+   <addaction name="menu_2"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <action name="actionExit">
+   <property name="text">
+    <string>Exit</string>
+   </property>
+  </action>
+  <action name="actionSave">
+   <property name="text">
+    <string>Save</string>
+   </property>
+  </action>
+  <action name="actionLoad">
+   <property name="text">
+    <string>Load</string>
+   </property>
+  </action>
+  <action name="actionExit_2">
+   <property name="text">
+    <string>Exit</string>
+   </property>
+  </action>
+  <action name="setting_cam">
+   <property name="text">
+    <string>Настроки камеры</string>
+   </property>
+  </action>
+  <action name="btn_show_personal_window">
+   <property name="text">
+    <string>Сотрудники</string>
+   </property>
+  </action>
+  <action name="btn_show_place_window">
+   <property name="text">
+    <string>Место выдочи</string>
+   </property>
+  </action>
+  <action name="update_list">
+   <property name="text">
+    <string>Обновить списки</string>
+   </property>
+  </action>
+  <action name="btn_show_about">
+   <property name="text">
+    <string>О программе</string>
+   </property>
+  </action>
+  <action name="exit">
+   <property name="text">
+    <string>Exit</string>
+   </property>
+  </action>
+  <action name="action_open_history">
+   <property name="text">
+    <string>История пропусков</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QVideoWidget</class>
+   <extends>QLabel</extends>
+   <header>PySide6.QtMultimediaWidgets</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

+ 516 - 0
window/ui/MainWindow_back.ui

@@ -0,0 +1,516 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="windowModality">
+   <enum>Qt::WindowModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1228</width>
+    <height>533</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="baseSize">
+   <size>
+    <width>864</width>
+    <height>430</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Временный пропуск</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <property name="enabled">
+    <bool>true</bool>
+   </property>
+   <property name="sizePolicy">
+    <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+     <horstretch>0</horstretch>
+     <verstretch>0</verstretch>
+    </sizepolicy>
+   </property>
+   <property name="focusPolicy">
+    <enum>Qt::NoFocus</enum>
+   </property>
+   <property name="autoFillBackground">
+    <bool>false</bool>
+   </property>
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="2" rowspan="2">
+     <widget class="QGroupBox" name="groupBox_2">
+      <property name="title">
+       <string>Фото</string>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_4">
+       <item>
+        <widget class="QStackedWidget" name="stacked_widget_photo">
+         <property name="enabled">
+          <bool>true</bool>
+         </property>
+         <property name="toolTip">
+          <string notr="true"/>
+         </property>
+         <property name="statusTip">
+          <string/>
+         </property>
+         <widget class="QWidget" name="page">
+          <layout class="QGridLayout" name="gridLayout_2">
+           <item row="0" column="0">
+            <widget class="QLabel" name="imagePhoto">
+             <property name="enabled">
+              <bool>true</bool>
+             </property>
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="frameShape">
+              <enum>QFrame::Box</enum>
+             </property>
+             <property name="frameShadow">
+              <enum>QFrame::Raised</enum>
+             </property>
+             <property name="text">
+              <string/>
+             </property>
+             <property name="wordWrap">
+              <bool>false</bool>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+         <widget class="QWidget" name="page_2">
+          <layout class="QGridLayout" name="gridLayout_4">
+           <item row="0" column="0">
+            <widget class="QVideoWidget" name="face_video_widget">
+             <property name="enabled">
+              <bool>false</bool>
+             </property>
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+       </item>
+       <item>
+        <widget class="QSplitter" name="splitter">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <widget class="QPushButton" name="btn_start_cam_photo">
+          <property name="text">
+           <string>Запустить камеру</string>
+          </property>
+         </widget>
+         <widget class="QPushButton" name="capturePhoto">
+          <property name="text">
+           <string>Сфотографировать</string>
+          </property>
+         </widget>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="2" column="3">
+     <widget class="QPushButton" name="btn_print">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="text">
+       <string>Печать</string>
+      </property>
+     </widget>
+    </item>
+    <item row="0" column="3" rowspan="2">
+     <widget class="QGroupBox" name="groupBox_3">
+      <property name="title">
+       <string>Фото паспорта</string>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_5">
+       <item>
+        <widget class="QStackedWidget" name="stacked_widget_pasport">
+         <property name="enabled">
+          <bool>true</bool>
+         </property>
+         <property name="currentIndex">
+          <number>0</number>
+         </property>
+         <widget class="QWidget" name="page_3">
+          <layout class="QGridLayout" name="gridLayout_3">
+           <item row="0" column="0">
+            <widget class="QLabel" name="imagePasport">
+             <property name="enabled">
+              <bool>true</bool>
+             </property>
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="frameShape">
+              <enum>QFrame::Box</enum>
+             </property>
+             <property name="frameShadow">
+              <enum>QFrame::Raised</enum>
+             </property>
+             <property name="text">
+              <string/>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+         <widget class="QWidget" name="page_4">
+          <layout class="QGridLayout" name="gridLayout_5">
+           <item row="0" column="0">
+            <widget class="QVideoWidget" name="pasport_video_widget">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+       </item>
+       <item>
+        <widget class="QSplitter" name="splitter_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <widget class="QPushButton" name="btn_start_cam_pasport">
+          <property name="text">
+           <string>Запустить камеру</string>
+          </property>
+         </widget>
+         <widget class="QPushButton" name="capturePasport">
+          <property name="text">
+           <string>Сделать снимок паспорта</string>
+          </property>
+         </widget>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="0" column="0" rowspan="2" colspan="2">
+     <widget class="QGroupBox" name="groupBox">
+      <property name="minimumSize">
+       <size>
+        <width>400</width>
+        <height>0</height>
+       </size>
+      </property>
+      <property name="title">
+       <string>Информация:</string>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <item>
+          <widget class="QLabel" name="label">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="text">
+            <string>Временный пропуск №:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="number_propusk">
+           <property name="inputMask">
+            <string/>
+           </property>
+           <property name="text">
+            <string/>
+           </property>
+           <property name="maxLength">
+            <number>32767</number>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <item>
+          <widget class="QLabel" name="label_2">
+           <property name="text">
+            <string>Дата и время выдачи:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QDateTimeEdit" name="date_from">
+           <property name="dateTime">
+            <datetime>
+             <hour>0</hour>
+             <minute>0</minute>
+             <second>0</second>
+             <year>2000</year>
+             <month>1</month>
+             <day>1</day>
+            </datetime>
+           </property>
+           <property name="timeSpec">
+            <enum>Qt::UTC</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_3">
+         <item>
+          <widget class="QLabel" name="label_4">
+           <property name="text">
+            <string>Действителене до:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QDateTimeEdit" name="date_to"/>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_4">
+         <item>
+          <widget class="QLabel" name="label_3">
+           <property name="text">
+            <string>Выдал:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="personal_combobox"/>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_5">
+         <item>
+          <widget class="QLabel" name="label_5">
+           <property name="text">
+            <string>Место выдачи:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="place_combobox"/>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" name="verticalLayout">
+         <item>
+          <widget class="QLabel" name="label_6">
+           <property name="text">
+            <string>Принимающий:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QTextEdit" name="receiving_man"/>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" name="verticalLayout_2">
+         <item>
+          <widget class="QLabel" name="label_7">
+           <property name="text">
+            <string>Цель визита:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QTextEdit" name="purpose_visite"/>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item row="2" column="2">
+     <widget class="QPushButton" name="btn_save">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="text">
+       <string>Сохранить</string>
+      </property>
+     </widget>
+    </item>
+    <item row="2" column="0">
+     <widget class="QPushButton" name="btn_clear">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="text">
+       <string>Отчистить</string>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>1228</width>
+     <height>23</height>
+    </rect>
+   </property>
+   <property name="mouseTracking">
+    <bool>true</bool>
+   </property>
+   <property name="acceptDrops">
+    <bool>true</bool>
+   </property>
+   <property name="nativeMenuBar">
+    <bool>true</bool>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>File</string>
+    </property>
+    <addaction name="separator"/>
+    <addaction name="actionSave"/>
+    <addaction name="actionLoad"/>
+    <addaction name="btn_show_about"/>
+    <addaction name="separator"/>
+    <addaction name="exit"/>
+   </widget>
+   <widget class="QMenu" name="menu">
+    <property name="title">
+     <string>Настроки</string>
+    </property>
+    <widget class="QMenu" name="menu_3">
+     <property name="title">
+      <string>Списки</string>
+     </property>
+     <addaction name="separator"/>
+     <addaction name="separator"/>
+     <addaction name="btn_show_personal_window"/>
+     <addaction name="btn_show_place_window"/>
+     <addaction name="separator"/>
+     <addaction name="update_list"/>
+    </widget>
+    <addaction name="setting_cam"/>
+    <addaction name="menu_3"/>
+   </widget>
+   <widget class="QMenu" name="menu_2">
+    <property name="title">
+     <string>История</string>
+    </property>
+    <addaction name="action_open_history"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menu"/>
+   <addaction name="menu_2"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <action name="actionExit">
+   <property name="text">
+    <string>Exit</string>
+   </property>
+  </action>
+  <action name="actionSave">
+   <property name="text">
+    <string>Save</string>
+   </property>
+  </action>
+  <action name="actionLoad">
+   <property name="text">
+    <string>Load</string>
+   </property>
+  </action>
+  <action name="actionExit_2">
+   <property name="text">
+    <string>Exit</string>
+   </property>
+  </action>
+  <action name="setting_cam">
+   <property name="text">
+    <string>Настроки камеры</string>
+   </property>
+  </action>
+  <action name="btn_show_personal_window">
+   <property name="text">
+    <string>Сотрудники</string>
+   </property>
+  </action>
+  <action name="btn_show_place_window">
+   <property name="text">
+    <string>Место выдочи</string>
+   </property>
+  </action>
+  <action name="update_list">
+   <property name="text">
+    <string>Обновить списки</string>
+   </property>
+  </action>
+  <action name="btn_show_about">
+   <property name="text">
+    <string>О программе</string>
+   </property>
+  </action>
+  <action name="exit">
+   <property name="text">
+    <string>Exit</string>
+   </property>
+  </action>
+  <action name="action_open_history">
+   <property name="text">
+    <string>История пропусков</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QVideoWidget</class>
+   <extends>QLabel</extends>
+   <header>PySide6.QtMultimediaWidgets</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

+ 92 - 0
window/ui_py/ui_DialogAbout.py

@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'DialogAbout.ui'
+##
+## Created by: Qt User Interface Compiler version 6.4.1
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QDialog, QHBoxLayout, QLabel,
+    QSizePolicy, QSpacerItem, QVBoxLayout, QWidget)
+
+class Ui_DialogAbout(object):
+    def setupUi(self, DialogAbout):
+        if not DialogAbout.objectName():
+            DialogAbout.setObjectName(u"DialogAbout")
+        DialogAbout.resize(456, 295)
+        self.verticalLayout = QVBoxLayout(DialogAbout)
+        self.verticalLayout.setObjectName(u"verticalLayout")
+        self.label = QLabel(DialogAbout)
+        self.label.setObjectName(u"label")
+        font = QFont()
+        font.setPointSize(30)
+        font.setBold(True)
+        self.label.setFont(font)
+        self.label.setAlignment(Qt.AlignCenter)
+
+        self.verticalLayout.addWidget(self.label)
+
+        self.version = QLabel(DialogAbout)
+        self.version.setObjectName(u"version")
+        self.version.setAlignment(Qt.AlignCenter)
+
+        self.verticalLayout.addWidget(self.version)
+
+        self.verticalSpacer_2 = QSpacerItem(10, 5, QSizePolicy.Minimum, QSizePolicy.Expanding)
+
+        self.verticalLayout.addItem(self.verticalSpacer_2)
+
+        self.horizontalLayout = QHBoxLayout()
+        self.horizontalLayout.setObjectName(u"horizontalLayout")
+        self.label_3 = QLabel(DialogAbout)
+        self.label_3.setObjectName(u"label_3")
+
+        self.horizontalLayout.addWidget(self.label_3)
+
+        self.horizontalSpacer = QSpacerItem(10, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+        self.horizontalLayout.addItem(self.horizontalSpacer)
+
+        self.label_4 = QLabel(DialogAbout)
+        self.label_4.setObjectName(u"label_4")
+        self.label_4.setMinimumSize(QSize(400, 0))
+
+        self.horizontalLayout.addWidget(self.label_4)
+
+
+        self.verticalLayout.addLayout(self.horizontalLayout)
+
+        self.verticalSpacer = QSpacerItem(20, 67, QSizePolicy.Minimum, QSizePolicy.Expanding)
+
+        self.verticalLayout.addItem(self.verticalSpacer)
+
+        self.label_2 = QLabel(DialogAbout)
+        self.label_2.setObjectName(u"label_2")
+        self.label_2.setAlignment(Qt.AlignCenter)
+
+        self.verticalLayout.addWidget(self.label_2)
+
+
+        self.retranslateUi(DialogAbout)
+
+        QMetaObject.connectSlotsByName(DialogAbout)
+    # setupUi
+
+    def retranslateUi(self, DialogAbout):
+        DialogAbout.setWindowTitle(QCoreApplication.translate("DialogAbout", u"\u041e \u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435", None))
+        self.label.setText(QCoreApplication.translate("DialogAbout", u"Propusk", None))
+        self.version.setText(QCoreApplication.translate("DialogAbout", u"TextLabel", None))
+        self.label_3.setText(QCoreApplication.translate("DialogAbout", u"Git:", None))
+        self.label_4.setText(QCoreApplication.translate("DialogAbout", u"<a href=\"https://tj.kbsu.ru/AlexSidorov/propusk\">https://tj.kbsu.ru/AlexSidorov/propusk</a>", None))
+        self.label_2.setText(QCoreApplication.translate("DialogAbout", u"@ KBSU", None))
+    # retranslateUi
+

+ 92 - 0
window/ui_py/ui_DialogCustomVariables.py

@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'DialogCustomVariables.ui'
+##
+## Created by: Qt User Interface Compiler version 6.4.1
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QDialog, QGroupBox, QHBoxLayout,
+    QLineEdit, QPushButton, QSizePolicy, QSpacerItem,
+    QVBoxLayout, QWidget)
+
+class Ui_DialogCustomVariables(object):
+    def setupUi(self, DialogCustomVariables):
+        if not DialogCustomVariables.objectName():
+            DialogCustomVariables.setObjectName(u"DialogCustomVariables")
+        DialogCustomVariables.resize(590, 228)
+        DialogCustomVariables.setMinimumSize(QSize(590, 228))
+        DialogCustomVariables.setMaximumSize(QSize(590, 228))
+        self.verticalLayout = QVBoxLayout(DialogCustomVariables)
+        self.verticalLayout.setObjectName(u"verticalLayout")
+        self.groupBox = QGroupBox(DialogCustomVariables)
+        self.groupBox.setObjectName(u"groupBox")
+        self.horizontalLayout = QHBoxLayout(self.groupBox)
+        self.horizontalLayout.setObjectName(u"horizontalLayout")
+        self.path_photo = QLineEdit(self.groupBox)
+        self.path_photo.setObjectName(u"path_photo")
+
+        self.horizontalLayout.addWidget(self.path_photo)
+
+        self.btn_show_path_photo = QPushButton(self.groupBox)
+        self.btn_show_path_photo.setObjectName(u"btn_show_path_photo")
+
+        self.horizontalLayout.addWidget(self.btn_show_path_photo)
+
+
+        self.verticalLayout.addWidget(self.groupBox)
+
+        self.groupBox_2 = QGroupBox(DialogCustomVariables)
+        self.groupBox_2.setObjectName(u"groupBox_2")
+        self.horizontalLayout_2 = QHBoxLayout(self.groupBox_2)
+        self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
+        self.path_db = QLineEdit(self.groupBox_2)
+        self.path_db.setObjectName(u"path_db")
+
+        self.horizontalLayout_2.addWidget(self.path_db)
+
+        self.btn_show_path_database = QPushButton(self.groupBox_2)
+        self.btn_show_path_database.setObjectName(u"btn_show_path_database")
+
+        self.horizontalLayout_2.addWidget(self.btn_show_path_database)
+
+
+        self.verticalLayout.addWidget(self.groupBox_2)
+
+        self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
+
+        self.verticalLayout.addItem(self.verticalSpacer)
+
+        self.btn_save = QPushButton(DialogCustomVariables)
+        self.btn_save.setObjectName(u"btn_save")
+
+        self.verticalLayout.addWidget(self.btn_save)
+
+        self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
+
+        self.verticalLayout.addItem(self.verticalSpacer_2)
+
+
+        self.retranslateUi(DialogCustomVariables)
+
+        QMetaObject.connectSlotsByName(DialogCustomVariables)
+    # setupUi
+
+    def retranslateUi(self, DialogCustomVariables):
+        DialogCustomVariables.setWindowTitle(QCoreApplication.translate("DialogCustomVariables", u"\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438", None))
+        self.groupBox.setTitle(QCoreApplication.translate("DialogCustomVariables", u"\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0441 \u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f\u043c\u0438", None))
+        self.btn_show_path_photo.setText(QCoreApplication.translate("DialogCustomVariables", u"\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438", None))
+        self.groupBox_2.setTitle(QCoreApplication.translate("DialogCustomVariables", u"\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445", None))
+        self.btn_show_path_database.setText(QCoreApplication.translate("DialogCustomVariables", u"\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438", None))
+        self.btn_save.setText(QCoreApplication.translate("DialogCustomVariables", u"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c", None))
+    # retranslateUi
+

+ 61 - 0
window/ui_py/ui_DialogHistory.py

@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'DialogHistory.ui'
+##
+## Created by: Qt User Interface Compiler version 6.4.1
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QDialog, QGroupBox, QHBoxLayout,
+    QLineEdit, QListWidget, QListWidgetItem, QSizePolicy,
+    QTextBrowser, QVBoxLayout, QWidget)
+
+class Ui_DialogHistory(object):
+    def setupUi(self, DialogHistory):
+        if not DialogHistory.objectName():
+            DialogHistory.setObjectName(u"DialogHistory")
+        DialogHistory.resize(935, 543)
+        self.horizontalLayout = QHBoxLayout(DialogHistory)
+        self.horizontalLayout.setObjectName(u"horizontalLayout")
+        self.groupBox = QGroupBox(DialogHistory)
+        self.groupBox.setObjectName(u"groupBox")
+        self.verticalLayout = QVBoxLayout(self.groupBox)
+        self.verticalLayout.setObjectName(u"verticalLayout")
+        self.line_search = QLineEdit(self.groupBox)
+        self.line_search.setObjectName(u"line_search")
+
+        self.verticalLayout.addWidget(self.line_search)
+
+        self.list_propusk = QListWidget(self.groupBox)
+        self.list_propusk.setObjectName(u"list_propusk")
+
+        self.verticalLayout.addWidget(self.list_propusk)
+
+
+        self.horizontalLayout.addWidget(self.groupBox)
+
+        self.browser = QTextBrowser(DialogHistory)
+        self.browser.setObjectName(u"browser")
+
+        self.horizontalLayout.addWidget(self.browser)
+
+
+        self.retranslateUi(DialogHistory)
+
+        QMetaObject.connectSlotsByName(DialogHistory)
+    # setupUi
+
+    def retranslateUi(self, DialogHistory):
+        DialogHistory.setWindowTitle(QCoreApplication.translate("DialogHistory", u"Dialog", None))
+        self.groupBox.setTitle(QCoreApplication.translate("DialogHistory", u"\u0421\u043f\u0438\u0441\u043e\u043a", None))
+    # retranslateUi
+

+ 161 - 0
window/ui_py/ui_DialogListPersonal.py

@@ -0,0 +1,161 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'DialogListPersonal.ui'
+##
+## Created by: Qt User Interface Compiler version 6.4.1
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QDialog, QGridLayout, QGroupBox,
+    QHBoxLayout, QLabel, QLineEdit, QListWidget,
+    QListWidgetItem, QPushButton, QSizePolicy, QSpacerItem,
+    QVBoxLayout, QWidget)
+
+class Ui_DialogListPersonal(object):
+    def setupUi(self, DialogListPersonal):
+        if not DialogListPersonal.objectName():
+            DialogListPersonal.setObjectName(u"DialogListPersonal")
+        DialogListPersonal.resize(640, 480)
+        self.gridLayout_3 = QGridLayout(DialogListPersonal)
+        self.gridLayout_3.setObjectName(u"gridLayout_3")
+        self.groupBox = QGroupBox(DialogListPersonal)
+        self.groupBox.setObjectName(u"groupBox")
+        self.gridLayout = QGridLayout(self.groupBox)
+        self.gridLayout.setObjectName(u"gridLayout")
+        self.list_personal_widget = QListWidget(self.groupBox)
+        self.list_personal_widget.setObjectName(u"list_personal_widget")
+
+        self.gridLayout.addWidget(self.list_personal_widget, 0, 0, 1, 1)
+
+
+        self.gridLayout_3.addWidget(self.groupBox, 0, 0, 1, 1)
+
+        self.groupBox_2 = QGroupBox(DialogListPersonal)
+        self.groupBox_2.setObjectName(u"groupBox_2")
+        self.groupBox_2.setFlat(False)
+        self.gridLayout_2 = QGridLayout(self.groupBox_2)
+        self.gridLayout_2.setObjectName(u"gridLayout_2")
+        self.verticalLayout_2 = QVBoxLayout()
+        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
+        self.horizontalLayout_2 = QHBoxLayout()
+        self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
+        self.label = QLabel(self.groupBox_2)
+        self.label.setObjectName(u"label")
+
+        self.horizontalLayout_2.addWidget(self.label)
+
+        self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+        self.horizontalLayout_2.addItem(self.horizontalSpacer)
+
+        self.lastname = QLineEdit(self.groupBox_2)
+        self.lastname.setObjectName(u"lastname")
+        self.lastname.setMinimumSize(QSize(250, 0))
+
+        self.horizontalLayout_2.addWidget(self.lastname)
+
+
+        self.verticalLayout_2.addLayout(self.horizontalLayout_2)
+
+        self.horizontalLayout_3 = QHBoxLayout()
+        self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
+        self.label_2 = QLabel(self.groupBox_2)
+        self.label_2.setObjectName(u"label_2")
+
+        self.horizontalLayout_3.addWidget(self.label_2)
+
+        self.horizontalSpacer_2 = QSpacerItem(50, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+        self.horizontalLayout_3.addItem(self.horizontalSpacer_2)
+
+        self.firstname = QLineEdit(self.groupBox_2)
+        self.firstname.setObjectName(u"firstname")
+        self.firstname.setMinimumSize(QSize(250, 0))
+
+        self.horizontalLayout_3.addWidget(self.firstname)
+
+
+        self.verticalLayout_2.addLayout(self.horizontalLayout_3)
+
+        self.horizontalLayout_4 = QHBoxLayout()
+        self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
+        self.label_3 = QLabel(self.groupBox_2)
+        self.label_3.setObjectName(u"label_3")
+
+        self.horizontalLayout_4.addWidget(self.label_3)
+
+        self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+        self.horizontalLayout_4.addItem(self.horizontalSpacer_3)
+
+        self.middlename = QLineEdit(self.groupBox_2)
+        self.middlename.setObjectName(u"middlename")
+        self.middlename.setMinimumSize(QSize(250, 0))
+
+        self.horizontalLayout_4.addWidget(self.middlename)
+
+
+        self.verticalLayout_2.addLayout(self.horizontalLayout_4)
+
+        self.verticalLayout = QVBoxLayout()
+        self.verticalLayout.setObjectName(u"verticalLayout")
+        self.horizontalLayout = QHBoxLayout()
+        self.horizontalLayout.setObjectName(u"horizontalLayout")
+        self.btn_save_personal = QPushButton(self.groupBox_2)
+        self.btn_save_personal.setObjectName(u"btn_save_personal")
+
+        self.horizontalLayout.addWidget(self.btn_save_personal)
+
+        self.btn_update_personal = QPushButton(self.groupBox_2)
+        self.btn_update_personal.setObjectName(u"btn_update_personal")
+
+        self.horizontalLayout.addWidget(self.btn_update_personal)
+
+
+        self.verticalLayout.addLayout(self.horizontalLayout)
+
+        self.btn_delete_personal = QPushButton(self.groupBox_2)
+        self.btn_delete_personal.setObjectName(u"btn_delete_personal")
+
+        self.verticalLayout.addWidget(self.btn_delete_personal)
+
+        self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
+
+        self.verticalLayout.addItem(self.verticalSpacer)
+
+
+        self.verticalLayout_2.addLayout(self.verticalLayout)
+
+
+        self.gridLayout_2.addLayout(self.verticalLayout_2, 0, 0, 1, 1)
+
+
+        self.gridLayout_3.addWidget(self.groupBox_2, 0, 1, 1, 1)
+
+
+        self.retranslateUi(DialogListPersonal)
+
+        QMetaObject.connectSlotsByName(DialogListPersonal)
+    # setupUi
+
+    def retranslateUi(self, DialogListPersonal):
+        DialogListPersonal.setWindowTitle(QCoreApplication.translate("DialogListPersonal", u"Dialog", None))
+        self.groupBox.setTitle(QCoreApplication.translate("DialogListPersonal", u"\u0421\u043f\u0438\u0441\u043e\u043a \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432", None))
+        self.groupBox_2.setTitle(QCoreApplication.translate("DialogListPersonal", u"\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435", None))
+        self.label.setText(QCoreApplication.translate("DialogListPersonal", u"\u0424\u0430\u043c\u0438\u043b\u0438\u044f", None))
+        self.label_2.setText(QCoreApplication.translate("DialogListPersonal", u"\u0418\u043c\u044f", None))
+        self.label_3.setText(QCoreApplication.translate("DialogListPersonal", u"\u041e\u0442\u0447\u0435\u0442\u0432\u043e", None))
+        self.btn_save_personal.setText(QCoreApplication.translate("DialogListPersonal", u"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c", None))
+        self.btn_update_personal.setText(QCoreApplication.translate("DialogListPersonal", u"\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c", None))
+        self.btn_delete_personal.setText(QCoreApplication.translate("DialogListPersonal", u"\u0423\u0434\u0430\u043b\u0438\u0442\u044c", None))
+    # retranslateUi
+

+ 115 - 0
window/ui_py/ui_DialogListPlace.py

@@ -0,0 +1,115 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'DialogListPlace.ui'
+##
+## Created by: Qt User Interface Compiler version 6.4.1
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QDialog, QGridLayout, QGroupBox,
+    QHBoxLayout, QLabel, QLineEdit, QListWidget,
+    QListWidgetItem, QPushButton, QSizePolicy, QSpacerItem,
+    QVBoxLayout, QWidget)
+
+class Ui_DialogListPlace(object):
+    def setupUi(self, DialogListPlace):
+        if not DialogListPlace.objectName():
+            DialogListPlace.setObjectName(u"DialogListPlace")
+        DialogListPlace.resize(640, 480)
+        self.gridLayout_3 = QGridLayout(DialogListPlace)
+        self.gridLayout_3.setObjectName(u"gridLayout_3")
+        self.groupBox = QGroupBox(DialogListPlace)
+        self.groupBox.setObjectName(u"groupBox")
+        self.gridLayout = QGridLayout(self.groupBox)
+        self.gridLayout.setObjectName(u"gridLayout")
+        self.list_place_widget = QListWidget(self.groupBox)
+        self.list_place_widget.setObjectName(u"list_place_widget")
+
+        self.gridLayout.addWidget(self.list_place_widget, 0, 0, 1, 1)
+
+
+        self.gridLayout_3.addWidget(self.groupBox, 0, 0, 1, 1)
+
+        self.groupBox_2 = QGroupBox(DialogListPlace)
+        self.groupBox_2.setObjectName(u"groupBox_2")
+        self.groupBox_2.setFlat(False)
+        self.gridLayout_2 = QGridLayout(self.groupBox_2)
+        self.gridLayout_2.setObjectName(u"gridLayout_2")
+        self.verticalLayout_2 = QVBoxLayout()
+        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
+        self.verticalLayout_3 = QVBoxLayout()
+        self.verticalLayout_3.setObjectName(u"verticalLayout_3")
+        self.label = QLabel(self.groupBox_2)
+        self.label.setObjectName(u"label")
+
+        self.verticalLayout_3.addWidget(self.label)
+
+        self.line_name_place = QLineEdit(self.groupBox_2)
+        self.line_name_place.setObjectName(u"line_name_place")
+        self.line_name_place.setMinimumSize(QSize(250, 0))
+
+        self.verticalLayout_3.addWidget(self.line_name_place)
+
+
+        self.verticalLayout_2.addLayout(self.verticalLayout_3)
+
+        self.verticalLayout = QVBoxLayout()
+        self.verticalLayout.setObjectName(u"verticalLayout")
+        self.horizontalLayout = QHBoxLayout()
+        self.horizontalLayout.setObjectName(u"horizontalLayout")
+        self.btn_save_place = QPushButton(self.groupBox_2)
+        self.btn_save_place.setObjectName(u"btn_save_place")
+
+        self.horizontalLayout.addWidget(self.btn_save_place)
+
+        self.btn_update_place = QPushButton(self.groupBox_2)
+        self.btn_update_place.setObjectName(u"btn_update_place")
+
+        self.horizontalLayout.addWidget(self.btn_update_place)
+
+
+        self.verticalLayout.addLayout(self.horizontalLayout)
+
+        self.btn_delete_place = QPushButton(self.groupBox_2)
+        self.btn_delete_place.setObjectName(u"btn_delete_place")
+
+        self.verticalLayout.addWidget(self.btn_delete_place)
+
+        self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
+
+        self.verticalLayout.addItem(self.verticalSpacer)
+
+
+        self.verticalLayout_2.addLayout(self.verticalLayout)
+
+
+        self.gridLayout_2.addLayout(self.verticalLayout_2, 0, 0, 1, 1)
+
+
+        self.gridLayout_3.addWidget(self.groupBox_2, 0, 1, 1, 1)
+
+
+        self.retranslateUi(DialogListPlace)
+
+        QMetaObject.connectSlotsByName(DialogListPlace)
+    # setupUi
+
+    def retranslateUi(self, DialogListPlace):
+        DialogListPlace.setWindowTitle(QCoreApplication.translate("DialogListPlace", u"Dialog", None))
+        self.groupBox.setTitle(QCoreApplication.translate("DialogListPlace", u"\u0421\u043f\u0438\u0441\u043e\u043a \u043c\u0435\u0441\u0442 \u0432\u044b\u0434\u0430\u0447\u0438", None))
+        self.groupBox_2.setTitle(QCoreApplication.translate("DialogListPlace", u"\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435", None))
+        self.label.setText(QCoreApplication.translate("DialogListPlace", u"\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0441\u0442\u0430 \u0432\u044b\u0434\u0430\u0447\u0438:", None))
+        self.btn_save_place.setText(QCoreApplication.translate("DialogListPlace", u"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c", None))
+        self.btn_update_place.setText(QCoreApplication.translate("DialogListPlace", u"\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c", None))
+        self.btn_delete_place.setText(QCoreApplication.translate("DialogListPlace", u"\u0423\u0434\u0430\u043b\u0438\u0442\u044c", None))
+    # retranslateUi
+

+ 101 - 0
window/ui_py/ui_DialogSettingCam.py

@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'DialogSettingCam.ui'
+##
+## Created by: Qt User Interface Compiler version 6.4.1
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+    QFont, QFontDatabase, QGradient, QIcon,
+    QImage, QKeySequence, QLinearGradient, QPainter,
+    QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtMultimediaWidgets import QVideoWidget
+from PySide6.QtWidgets import (QApplication, QComboBox, QDialog, QGridLayout,
+    QGroupBox, QHBoxLayout, QLabel, QPushButton,
+    QSizePolicy, QStackedWidget, QWidget)
+
+class Ui_DialogSettingCam(object):
+    def setupUi(self, DialogSettingCam):
+        if not DialogSettingCam.objectName():
+            DialogSettingCam.setObjectName(u"DialogSettingCam")
+        DialogSettingCam.resize(640, 480)
+        self.gridLayout = QGridLayout(DialogSettingCam)
+        self.gridLayout.setObjectName(u"gridLayout")
+        self.groupBox = QGroupBox(DialogSettingCam)
+        self.groupBox.setObjectName(u"groupBox")
+        self.gridLayout_3 = QGridLayout(self.groupBox)
+        self.gridLayout_3.setObjectName(u"gridLayout_3")
+        self.face_list_cam = QComboBox(self.groupBox)
+        self.face_list_cam.setObjectName(u"face_list_cam")
+
+        self.gridLayout_3.addWidget(self.face_list_cam, 0, 0, 1, 1)
+
+        self.horizontalLayout = QHBoxLayout()
+        self.horizontalLayout.setObjectName(u"horizontalLayout")
+        self.chacked_cam_face = QPushButton(self.groupBox)
+        self.chacked_cam_face.setObjectName(u"chacked_cam_face")
+
+        self.horizontalLayout.addWidget(self.chacked_cam_face)
+
+        self.stop_cam_face = QPushButton(self.groupBox)
+        self.stop_cam_face.setObjectName(u"stop_cam_face")
+
+        self.horizontalLayout.addWidget(self.stop_cam_face)
+
+
+        self.gridLayout_3.addLayout(self.horizontalLayout, 2, 0, 1, 1)
+
+        self.stackedWidget = QStackedWidget(self.groupBox)
+        self.stackedWidget.setObjectName(u"stackedWidget")
+        self.page_3 = QWidget()
+        self.page_3.setObjectName(u"page_3")
+        self.gridLayout_2 = QGridLayout(self.page_3)
+        self.gridLayout_2.setObjectName(u"gridLayout_2")
+        self.image = QLabel(self.page_3)
+        self.image.setObjectName(u"image")
+
+        self.gridLayout_2.addWidget(self.image, 0, 0, 1, 1)
+
+        self.stackedWidget.addWidget(self.page_3)
+        self.page_4 = QWidget()
+        self.page_4.setObjectName(u"page_4")
+        self.gridLayout_4 = QGridLayout(self.page_4)
+        self.gridLayout_4.setObjectName(u"gridLayout_4")
+        self.video = QVideoWidget(self.page_4)
+        self.video.setObjectName(u"video")
+
+        self.gridLayout_4.addWidget(self.video, 0, 0, 1, 1)
+
+        self.stackedWidget.addWidget(self.page_4)
+
+        self.gridLayout_3.addWidget(self.stackedWidget, 1, 0, 1, 1)
+
+
+        self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 1)
+
+        self.save_setting_cam = QPushButton(DialogSettingCam)
+        self.save_setting_cam.setObjectName(u"save_setting_cam")
+
+        self.gridLayout.addWidget(self.save_setting_cam, 1, 0, 1, 1)
+
+
+        self.retranslateUi(DialogSettingCam)
+
+        QMetaObject.connectSlotsByName(DialogSettingCam)
+    # setupUi
+
+    def retranslateUi(self, DialogSettingCam):
+        DialogSettingCam.setWindowTitle(QCoreApplication.translate("DialogSettingCam", u"Dialog", None))
+        self.groupBox.setTitle(QCoreApplication.translate("DialogSettingCam", u"\u0424\u043e\u0442\u043e \u043b\u0438\u0446\u0430", None))
+        self.chacked_cam_face.setText(QCoreApplication.translate("DialogSettingCam", u"\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c", None))
+        self.stop_cam_face.setText(QCoreApplication.translate("DialogSettingCam", u"\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c", None))
+        self.image.setText(QCoreApplication.translate("DialogSettingCam", u"TextLabel", None))
+        self.save_setting_cam.setText(QCoreApplication.translate("DialogSettingCam", u"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438", None))
+    # retranslateUi
+

+ 342 - 0
window/ui_py/ui_MainWindow.py

@@ -0,0 +1,342 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'MainWindow.ui'
+##
+## Created by: Qt User Interface Compiler version 6.4.1
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+    QMetaObject, QObject, QPoint, QRect,
+    QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QAction)
+from PySide6.QtMultimediaWidgets import QVideoWidget
+from PySide6.QtWidgets import (QApplication, QComboBox, QDateTimeEdit, QFrame,
+    QGridLayout, QGroupBox, QHBoxLayout, QLabel,
+    QLineEdit, QMainWindow, QMenu, QMenuBar,
+    QPushButton, QSizePolicy, QSplitter, QStackedWidget,
+    QStatusBar, QTextEdit, QVBoxLayout, QWidget)
+from PropuskWidgets.PLineEdit import PLineEdit
+
+class Ui_MainWindow(object):
+    def setupUi(self, MainWindow):
+        if not MainWindow.objectName():
+            MainWindow.setObjectName(u"MainWindow")
+        MainWindow.setWindowModality(Qt.WindowModal)
+        MainWindow.resize(920, 511)
+        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
+        MainWindow.setSizePolicy(sizePolicy)
+        MainWindow.setBaseSize(QSize(864, 430))
+        self.actionExit = QAction(MainWindow)
+        self.actionExit.setObjectName(u"actionExit")
+        self.actionSave = QAction(MainWindow)
+        self.actionSave.setObjectName(u"actionSave")
+        self.actionLoad = QAction(MainWindow)
+        self.actionLoad.setObjectName(u"actionLoad")
+        self.actionExit_2 = QAction(MainWindow)
+        self.actionExit_2.setObjectName(u"actionExit_2")
+        self.setting_cam = QAction(MainWindow)
+        self.setting_cam.setObjectName(u"setting_cam")
+        self.btn_show_personal_window = QAction(MainWindow)
+        self.btn_show_personal_window.setObjectName(u"btn_show_personal_window")
+        self.btn_show_place_window = QAction(MainWindow)
+        self.btn_show_place_window.setObjectName(u"btn_show_place_window")
+        self.update_list = QAction(MainWindow)
+        self.update_list.setObjectName(u"update_list")
+        self.btn_show_about = QAction(MainWindow)
+        self.btn_show_about.setObjectName(u"btn_show_about")
+        self.exit = QAction(MainWindow)
+        self.exit.setObjectName(u"exit")
+        self.action_open_history = QAction(MainWindow)
+        self.action_open_history.setObjectName(u"action_open_history")
+        self.centralwidget = QWidget(MainWindow)
+        self.centralwidget.setObjectName(u"centralwidget")
+        self.centralwidget.setEnabled(True)
+        sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
+        self.centralwidget.setSizePolicy(sizePolicy)
+        self.centralwidget.setFocusPolicy(Qt.NoFocus)
+        self.centralwidget.setAutoFillBackground(False)
+        self.gridLayout = QGridLayout(self.centralwidget)
+        self.gridLayout.setObjectName(u"gridLayout")
+        self.groupBox = QGroupBox(self.centralwidget)
+        self.groupBox.setObjectName(u"groupBox")
+        self.groupBox.setMinimumSize(QSize(400, 0))
+        self.verticalLayout_3 = QVBoxLayout(self.groupBox)
+        self.verticalLayout_3.setObjectName(u"verticalLayout_3")
+        self.horizontalLayout = QHBoxLayout()
+        self.horizontalLayout.setObjectName(u"horizontalLayout")
+        self.label = QLabel(self.groupBox)
+        self.label.setObjectName(u"label")
+        sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
+        self.label.setSizePolicy(sizePolicy)
+
+        self.horizontalLayout.addWidget(self.label)
+
+        self.number_propusk = PLineEdit(self.groupBox)
+        self.number_propusk.setObjectName(u"number_propusk")
+        self.number_propusk.setMaxLength(32767)
+
+        self.horizontalLayout.addWidget(self.number_propusk)
+
+
+        self.verticalLayout_3.addLayout(self.horizontalLayout)
+
+        self.horizontalLayout_2 = QHBoxLayout()
+        self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
+        self.label_2 = QLabel(self.groupBox)
+        self.label_2.setObjectName(u"label_2")
+
+        self.horizontalLayout_2.addWidget(self.label_2)
+
+        self.date_from = QDateTimeEdit(self.groupBox)
+        self.date_from.setObjectName(u"date_from")
+        self.date_from.setDateTime(QDateTime(QDate(1999, 12, 31), QTime(21, 0, 0)))
+        self.date_from.setTimeSpec(Qt.UTC)
+
+        self.horizontalLayout_2.addWidget(self.date_from)
+
+
+        self.verticalLayout_3.addLayout(self.horizontalLayout_2)
+
+        self.horizontalLayout_3 = QHBoxLayout()
+        self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
+        self.label_4 = QLabel(self.groupBox)
+        self.label_4.setObjectName(u"label_4")
+
+        self.horizontalLayout_3.addWidget(self.label_4)
+
+        self.date_to = QDateTimeEdit(self.groupBox)
+        self.date_to.setObjectName(u"date_to")
+
+        self.horizontalLayout_3.addWidget(self.date_to)
+
+
+        self.verticalLayout_3.addLayout(self.horizontalLayout_3)
+
+        self.horizontalLayout_4 = QHBoxLayout()
+        self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
+        self.label_3 = QLabel(self.groupBox)
+        self.label_3.setObjectName(u"label_3")
+
+        self.horizontalLayout_4.addWidget(self.label_3)
+
+        self.personal_combobox = QComboBox(self.groupBox)
+        self.personal_combobox.setObjectName(u"personal_combobox")
+
+        self.horizontalLayout_4.addWidget(self.personal_combobox)
+
+
+        self.verticalLayout_3.addLayout(self.horizontalLayout_4)
+
+        self.horizontalLayout_5 = QHBoxLayout()
+        self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
+        self.label_5 = QLabel(self.groupBox)
+        self.label_5.setObjectName(u"label_5")
+
+        self.horizontalLayout_5.addWidget(self.label_5)
+
+        self.place_combobox = QComboBox(self.groupBox)
+        self.place_combobox.setObjectName(u"place_combobox")
+
+        self.horizontalLayout_5.addWidget(self.place_combobox)
+
+
+        self.verticalLayout_3.addLayout(self.horizontalLayout_5)
+
+        self.verticalLayout = QVBoxLayout()
+        self.verticalLayout.setObjectName(u"verticalLayout")
+        self.label_6 = QLabel(self.groupBox)
+        self.label_6.setObjectName(u"label_6")
+
+        self.verticalLayout.addWidget(self.label_6)
+
+        self.receiving_man = QTextEdit(self.groupBox)
+        self.receiving_man.setObjectName(u"receiving_man")
+
+        self.verticalLayout.addWidget(self.receiving_man)
+
+
+        self.verticalLayout_3.addLayout(self.verticalLayout)
+
+        self.verticalLayout_2 = QVBoxLayout()
+        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
+        self.label_7 = QLabel(self.groupBox)
+        self.label_7.setObjectName(u"label_7")
+
+        self.verticalLayout_2.addWidget(self.label_7)
+
+        self.purpose_visite = QTextEdit(self.groupBox)
+        self.purpose_visite.setObjectName(u"purpose_visite")
+
+        self.verticalLayout_2.addWidget(self.purpose_visite)
+
+
+        self.verticalLayout_3.addLayout(self.verticalLayout_2)
+
+
+        self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 1)
+
+        self.groupBox_2 = QGroupBox(self.centralwidget)
+        self.groupBox_2.setObjectName(u"groupBox_2")
+        self.verticalLayout_4 = QVBoxLayout(self.groupBox_2)
+        self.verticalLayout_4.setObjectName(u"verticalLayout_4")
+        self.stacked_widget_photo = QStackedWidget(self.groupBox_2)
+        self.stacked_widget_photo.setObjectName(u"stacked_widget_photo")
+        self.stacked_widget_photo.setEnabled(True)
+#if QT_CONFIG(tooltip)
+        self.stacked_widget_photo.setToolTip(u"")
+#endif // QT_CONFIG(tooltip)
+        self.page = QWidget()
+        self.page.setObjectName(u"page")
+        self.gridLayout_2 = QGridLayout(self.page)
+        self.gridLayout_2.setObjectName(u"gridLayout_2")
+        self.imagePhoto = QLabel(self.page)
+        self.imagePhoto.setObjectName(u"imagePhoto")
+        self.imagePhoto.setEnabled(True)
+        sizePolicy.setHeightForWidth(self.imagePhoto.sizePolicy().hasHeightForWidth())
+        self.imagePhoto.setSizePolicy(sizePolicy)
+        self.imagePhoto.setFrameShape(QFrame.Box)
+        self.imagePhoto.setFrameShadow(QFrame.Raised)
+        self.imagePhoto.setWordWrap(False)
+
+        self.gridLayout_2.addWidget(self.imagePhoto, 0, 0, 1, 1)
+
+        self.stacked_widget_photo.addWidget(self.page)
+        self.page_2 = QWidget()
+        self.page_2.setObjectName(u"page_2")
+        self.gridLayout_4 = QGridLayout(self.page_2)
+        self.gridLayout_4.setObjectName(u"gridLayout_4")
+        self.face_video_widget = QVideoWidget(self.page_2)
+        self.face_video_widget.setObjectName(u"face_video_widget")
+        self.face_video_widget.setEnabled(False)
+        sizePolicy.setHeightForWidth(self.face_video_widget.sizePolicy().hasHeightForWidth())
+        self.face_video_widget.setSizePolicy(sizePolicy)
+
+        self.gridLayout_4.addWidget(self.face_video_widget, 0, 0, 1, 1)
+
+        self.stacked_widget_photo.addWidget(self.page_2)
+
+        self.verticalLayout_4.addWidget(self.stacked_widget_photo)
+
+        self.splitter = QSplitter(self.groupBox_2)
+        self.splitter.setObjectName(u"splitter")
+        self.splitter.setOrientation(Qt.Horizontal)
+        self.btn_start_cam_photo = QPushButton(self.splitter)
+        self.btn_start_cam_photo.setObjectName(u"btn_start_cam_photo")
+        self.splitter.addWidget(self.btn_start_cam_photo)
+        self.capturePhoto = QPushButton(self.splitter)
+        self.capturePhoto.setObjectName(u"capturePhoto")
+        self.splitter.addWidget(self.capturePhoto)
+
+        self.verticalLayout_4.addWidget(self.splitter)
+
+
+        self.gridLayout.addWidget(self.groupBox_2, 0, 1, 1, 2)
+
+        self.btn_clear = QPushButton(self.centralwidget)
+        self.btn_clear.setObjectName(u"btn_clear")
+        sizePolicy.setHeightForWidth(self.btn_clear.sizePolicy().hasHeightForWidth())
+        self.btn_clear.setSizePolicy(sizePolicy)
+
+        self.gridLayout.addWidget(self.btn_clear, 1, 0, 1, 1)
+
+        self.btn_save = QPushButton(self.centralwidget)
+        self.btn_save.setObjectName(u"btn_save")
+        sizePolicy.setHeightForWidth(self.btn_save.sizePolicy().hasHeightForWidth())
+        self.btn_save.setSizePolicy(sizePolicy)
+
+        self.gridLayout.addWidget(self.btn_save, 1, 1, 1, 1)
+
+        self.btn_print = QPushButton(self.centralwidget)
+        self.btn_print.setObjectName(u"btn_print")
+        sizePolicy.setHeightForWidth(self.btn_print.sizePolicy().hasHeightForWidth())
+        self.btn_print.setSizePolicy(sizePolicy)
+
+        self.gridLayout.addWidget(self.btn_print, 1, 2, 1, 1)
+
+        MainWindow.setCentralWidget(self.centralwidget)
+        self.menubar = QMenuBar(MainWindow)
+        self.menubar.setObjectName(u"menubar")
+        self.menubar.setGeometry(QRect(0, 0, 920, 23))
+        self.menubar.setMouseTracking(True)
+        self.menubar.setAcceptDrops(True)
+        self.menubar.setNativeMenuBar(True)
+        self.menuFile = QMenu(self.menubar)
+        self.menuFile.setObjectName(u"menuFile")
+        self.menu = QMenu(self.menubar)
+        self.menu.setObjectName(u"menu")
+        self.menu_3 = QMenu(self.menu)
+        self.menu_3.setObjectName(u"menu_3")
+        self.menu_2 = QMenu(self.menubar)
+        self.menu_2.setObjectName(u"menu_2")
+        MainWindow.setMenuBar(self.menubar)
+        self.statusbar = QStatusBar(MainWindow)
+        self.statusbar.setObjectName(u"statusbar")
+        MainWindow.setStatusBar(self.statusbar)
+
+        self.menubar.addAction(self.menuFile.menuAction())
+        self.menubar.addAction(self.menu.menuAction())
+        self.menubar.addAction(self.menu_2.menuAction())
+        self.menuFile.addSeparator()
+        self.menuFile.addAction(self.actionSave)
+        self.menuFile.addAction(self.actionLoad)
+        self.menuFile.addAction(self.btn_show_about)
+        self.menuFile.addSeparator()
+        self.menuFile.addAction(self.exit)
+        self.menu.addAction(self.setting_cam)
+        self.menu.addAction(self.menu_3.menuAction())
+        self.menu_3.addSeparator()
+        self.menu_3.addSeparator()
+        self.menu_3.addAction(self.btn_show_personal_window)
+        self.menu_3.addAction(self.btn_show_place_window)
+        self.menu_3.addSeparator()
+        self.menu_3.addAction(self.update_list)
+        self.menu_2.addAction(self.action_open_history)
+
+        self.retranslateUi(MainWindow)
+
+        QMetaObject.connectSlotsByName(MainWindow)
+    # setupUi
+
+    def retranslateUi(self, MainWindow):
+        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"\u0412\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u043f\u0443\u0441\u043a", None))
+        self.actionExit.setText(QCoreApplication.translate("MainWindow", u"Exit", None))
+        self.actionSave.setText(QCoreApplication.translate("MainWindow", u"Save", None))
+        self.actionLoad.setText(QCoreApplication.translate("MainWindow", u"Load", None))
+        self.actionExit_2.setText(QCoreApplication.translate("MainWindow", u"Exit", None))
+        self.setting_cam.setText(QCoreApplication.translate("MainWindow", u"\u041d\u0430\u0441\u0442\u0440\u043e\u043a\u0438 \u043a\u0430\u043c\u0435\u0440\u044b", None))
+        self.btn_show_personal_window.setText(QCoreApplication.translate("MainWindow", u"\u0421\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u0438", None))
+        self.btn_show_place_window.setText(QCoreApplication.translate("MainWindow", u"\u041c\u0435\u0441\u0442\u043e \u0432\u044b\u0434\u043e\u0447\u0438", None))
+        self.update_list.setText(QCoreApplication.translate("MainWindow", u"\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043a\u0438", None))
+        self.btn_show_about.setText(QCoreApplication.translate("MainWindow", u"\u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435", None))
+        self.exit.setText(QCoreApplication.translate("MainWindow", u"Exit", None))
+        self.action_open_history.setText(QCoreApplication.translate("MainWindow", u"\u0418\u0441\u0442\u043e\u0440\u0438\u044f \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043e\u0432", None))
+        self.groupBox.setTitle(QCoreApplication.translate("MainWindow", u"\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f:", None))
+        self.label.setText(QCoreApplication.translate("MainWindow", u"\u0412\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u043f\u0443\u0441\u043a \u2116:", None))
+        self.label_2.setText(QCoreApplication.translate("MainWindow", u"\u0414\u0430\u0442\u0430 \u0438 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u0434\u0430\u0447\u0438:", None))
+        self.label_4.setText(QCoreApplication.translate("MainWindow", u"\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u0435\u043d\u0435 \u0434\u043e:", None))
+        self.label_3.setText(QCoreApplication.translate("MainWindow", u"\u0412\u044b\u0434\u0430\u043b:", None))
+        self.label_5.setText(QCoreApplication.translate("MainWindow", u"\u041c\u0435\u0441\u0442\u043e \u0432\u044b\u0434\u0430\u0447\u0438:", None))
+        self.label_6.setText(QCoreApplication.translate("MainWindow", u"\u041f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439:", None))
+        self.label_7.setText(QCoreApplication.translate("MainWindow", u"\u0426\u0435\u043b\u044c \u0432\u0438\u0437\u0438\u0442\u0430:", None))
+        self.groupBox_2.setTitle(QCoreApplication.translate("MainWindow", u"\u0424\u043e\u0442\u043e", None))
+#if QT_CONFIG(statustip)
+        self.stacked_widget_photo.setStatusTip("")
+#endif // QT_CONFIG(statustip)
+        self.imagePhoto.setText("")
+        self.btn_start_cam_photo.setText(QCoreApplication.translate("MainWindow", u"\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043a\u0430\u043c\u0435\u0440\u0443", None))
+        self.capturePhoto.setText(QCoreApplication.translate("MainWindow", u"\u0421\u0444\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0440\u043e\u0432\u0430\u0442\u044c", None))
+        self.btn_clear.setText(QCoreApplication.translate("MainWindow", u"\u041e\u0442\u0447\u0438\u0441\u0442\u0438\u0442\u044c", None))
+        self.btn_save.setText(QCoreApplication.translate("MainWindow", u"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c", None))
+        self.btn_print.setText(QCoreApplication.translate("MainWindow", u"\u041f\u0435\u0447\u0430\u0442\u044c", None))
+        self.menuFile.setTitle(QCoreApplication.translate("MainWindow", u"File", None))
+        self.menu.setTitle(QCoreApplication.translate("MainWindow", u"\u041d\u0430\u0441\u0442\u0440\u043e\u043a\u0438", None))
+        self.menu_3.setTitle(QCoreApplication.translate("MainWindow", u"\u0421\u043f\u0438\u0441\u043a\u0438", None))
+        self.menu_2.setTitle(QCoreApplication.translate("MainWindow", u"\u0418\u0441\u0442\u043e\u0440\u0438\u044f", None))
+    # retranslateUi
+