Как сделать так чтобы класс Archiver не был связан с отрисовкой и формой

Как сделать так чтобы класс Archiver не был связан с отрисовкой и формой?

В данный момент они связаны тем, что в классе Archiver есть вызовы функций из controller - а именно self.progress() ( то есть я классом Archiver управляю классом controller, а нужно четкое разделение модели(archiver) и представления(controller и view)) вызывается функция изменения значения progress bar в зависимости от событий архиватора.

Мне нужно сделать так чтобы класс Archiver в зависимости от того что в нем происходит изменял значения прогресс бара не ссылаясь на функцию из controller.(как я понял в arhiver должен вызываться метод, который ему передали извне - что то на подобие аналога делегатов в питоне, но как это реализовать, пока не могу)

Проект состоит из 3-х файлов:

Аrchiver:

import controller


class Archiver(controller.Controller):
    # метод архиватор
    def pack(self):
        self.res = bytearray()
        self.step = 0
        with open(self.lineEdit.text(), 'rb') as f:
            byte_arr = f.read()
        count = 1

        self.remember_file()
        self.move = (50 / (len(byte_arr) - 1))

        if len(byte_arr) == 0:
            return (self.res)

        for i in range(len(byte_arr) - 1):
            if byte_arr[i] == byte_arr[i + 1]:
                count += 1

            if byte_arr[i] != byte_arr[i + 1]:
                self.res.append(count)
                self.res.append(byte_arr[i])
                count = 1

            if count == 256:
                self.res.append(255)
                self.res.append(byte_arr[i])
                count = 1

            self.progress()

        self.res.append(count)
        self.res.append(byte_arr[-1])
        count = 0
        count_2 = 0
        self.res_2 = bytearray()
        flag = True
        self.move = 50 / (len(self.res) / 2)
        for i in range(0, len(self.res), 2):
            if self.res[i] == 1:
                count += 1
                if flag:
                    count_2 = i + 1
                    flag = False
                    self.res_2.append(0)
                if count == 255:
                    self.res_2.append(255)
                    for i in range(count):
                        self.res_2.append(self.res[count_2])
                        count_2 += 2
                    flag = True
                    count = 0
            if self.res[i] != 1:
                if flag == False:
                    self.res_2.append(count)
                    for j in range(count):
                        self.res_2.append(self.res[count_2])
                        count_2 += 2
                    flag = True
                    count = 0
                    self.res_2.append(self.res[i])
                    self.res_2.append(self.res[i + 1])
                    count_2 += 2
                else:
                    self.res_2.append(self.res[i])
                    self.res_2.append(self.res[i + 1])
                    count_2 += 2
            if i == len(self.res) - 2 and flag == False:
                self.res_2.append(count)
                for i in range(count):
                    self.res_2.append(self.res[count_2])
                    count_2 += 2
            self.progress()
        with open(self.lineEdit_2.text(), 'wb') as p:
            p.write(self.res_2)

    # метод разархиватор
    def unpack(self):
        self.step = 0
        with open(self.lineEdit.text(), 'rb') as f:
            byte_arr = f.read()
        self.remember_file()
        self.res_3 = bytearray()
        i = 0
        self.move = 100 / len(byte_arr)
        try:
            while i != len(byte_arr):
                if byte_arr[i] == 0:
                    i += 1
                    self.progress()
                    for j in range(byte_arr[i]):
                        i += 1
                        self.res_3.append(byte_arr[i])
                        self.progress()
                    i += 1
                    self.progress()

                else:
                    i += 1
                    self.progress()
                    for j in range(byte_arr[i - 1]):
                        self.res_3.append(byte_arr[i])
                        self.progress()
                    i += 1
                    self.progress()
        except IndexError:
            pass
        with open(self.lineEdit_2.text(), 'wb') as p:
            p.write(self.res_3)

Controller:

import sys
import os
from PyQt5.QtCore import Qt
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QFileDialog, QMessageBox
import view
import model

class Controller(QtWidgets.QMainWindow, view.Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.input_path = ''
        self.output_path = ''

        # функции обратного вызова
        self.btn_1.clicked.connect(self.launch_clicked)
        self.btn_2.clicked.connect(self.launch_clicked)
        self.btn_3.clicked.connect(self.choice_clicked)
        self.btn_4.clicked.connect(self.choice_clicked)
        self.btn_5.setEnabled(False)
        self.btn_5.clicked.connect(self.stop_action)
        self.lineEdit.textChanged.connect(self.nullify_progress)
        self.lineEdit_2.textChanged.connect(self.nullify_progress)

    # сохранение файла
    def remember_file(self):
        self.res_4 = bytearray()
        with open(self.lineEdit_2.text(), 'rb') as f:
            self.byte_arr = f.read()
        for i in range(len(self.byte_arr)):
            self.res_4.append(self.byte_arr[i])

    # выбор входного файла
    def input_file_selection(self):
        self.input_path, _ = QFileDialog.getOpenFileName(self, 'Выберите файл', '')
        self.lineEdit.setText(self.input_path)

    # выбор результирующего файла
    def output_file_selection(self):
        self.output_path, _ = QFileDialog.getOpenFileName(self, 'Выберите файл', '')
        self.lineEdit_2.setText(self.output_path)

    # увеличение значения progressBar
    def progress(self):
        self.step += self.move
        self.progressBar.setValue(round(self.step))

    # вызов окошка с сообщением об ошибке
    def message_box(self, text):
        msg = QMessageBox()
        msg.setWindowTitle('Error!')
        msg.setText(text)
        msg.setIcon(QMessageBox.Information)
        msg.exec_()

    # обнуление progressBar
    def nullify_progress(self):
        self.progressBar.setValue(0)

    # выборка по кнопке
    def choice_clicked(self):
        sender = self.sender()
        self.progressBar.setValue(0)
        if (sender.text() == "Выбрать \n"" исходный \n"" файл"):
            self.input_file_selection()
        else:
            self.output_file_selection()

    # запуск архиватора. в т.ч. проверка на ошибки
    def launch_clicked(self):
        sender = self.sender()
        if self.lineEdit.text() == '':
            self.message_box('Нет исходного файла.\nЗаполните пустые поля')
        elif self.lineEdit_2.text() == '':
            self.message_box('Нет результирующего файла.\nЗаполните пустые поля')
        elif (not os.path.isfile(self.lineEdit.text())):
            self.message_box('Неправильный путь исходного файла \nили такого файла не существует.')
        elif (not os.path.isfile(self.lineEdit_2.text())):
            self.message_box('Неправильный путь результирующего файла \nили такого файла не существует')
        else:
            self.btn_5.setEnabled(True)
            if (sender.text() == "Добавить\n" " в архив"):
                model.Archiver.pack(self)
            else:
                model.Archiver.unpack(self)

    # остановка действия
    def stop_action(self):
        self.btn_5.setEnabled(False)
        sender = self.sender()
        if (sender.text() == 'Отмена'):
            with open(self.lineEdit_2.text(), 'wb') as p:
                p.write(self.res_4)
            self.progressBar.setValue(0)
            self.message_box('Прервано! \nРезультирующий файл не изменился.')

#метод запуска программы
def main():
    app = QtWidgets.QApplication(sys.argv)
    window = Controller()
    window.show()
    app.exec_()

#запуск программы
if __name__ == '__main__':
    main()

И окошко(view):

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'C:/Archiv.ui'
#
# Created by: PyQt5 UI code generator 5.14.2
#
# WARNING! All changes made in this file will be lost!


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QIcon


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(342, 240)
        MainWindow.setMinimumSize(QtCore.QSize(342, 240))
        MainWindow.setMaximumSize(QtCore.QSize(342, 240))
        MainWindow.setStyleSheet("background-color: rgb(52, 61, 70);\n"
                                 "")
        self.setWindowTitle('Icon')
        self.setWindowIcon(QIcon('1486395874-settings_80622.ico'))
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(20, 150, 216, 21))
        self.progressBar.setMinimumSize(QtCore.QSize(216, 21))
        self.progressBar.setMaximumSize(QtCore.QSize(216, 21))
        self.progressBar.setStyleSheet("color: rgb(255, 255, 255);\n"
                                       "background-color: rgb(181, 181, 181);\n"
                                       "")
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.btn_2 = QtWidgets.QPushButton(self.centralwidget)
        self.btn_2.setGeometry(QtCore.QRect(90, 180, 61, 31))
        self.btn_2.setStyleSheet("background-color: rgb(255, 255, 255);\n"
                                 "color: rgb(0, 0, 0);")
        self.btn_2.setObjectName("btn_2")
        self.btn_1 = QtWidgets.QPushButton(self.centralwidget)
        self.btn_1.setGeometry(QtCore.QRect(20, 180, 61, 31))
        self.btn_1.setStyleSheet("background-color: rgb(255, 255, 255);\n"
                                 "color: rgb(0, 0, 0);")
        self.btn_1.setObjectName("btn_1")
        self.btn_3 = QtWidgets.QPushButton(self.centralwidget)
        self.btn_3.setGeometry(QtCore.QRect(210, 50, 101, 41))
        self.btn_3.setStyleSheet("background-color: rgb(255, 255, 255);\n"
                                 "color: rgb(0, 0, 0);")
        self.btn_3.setObjectName("btn_3")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(10, 10, 211, 21))
        font = QtGui.QFont()
        font.setPointSize(14)
        self.label.setFont(font)
        self.label.setStyleSheet("color: rgb(255, 255, 255);")
        self.label.setObjectName("label")
        self.btn_4 = QtWidgets.QPushButton(self.centralwidget)
        self.btn_4.setGeometry(QtCore.QRect(210, 100, 101, 41))
        self.btn_4.setStyleSheet("background-color: rgb(255, 255, 255);\n"
                                 "color: rgb(0, 0, 0);")
        self.btn_4.setObjectName("btn_4")
        self.btn_5 = QtWidgets.QPushButton(self.centralwidget)
        self.btn_5.setGeometry(QtCore.QRect(160, 180, 41, 31))
        self.btn_5.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.btn_5.setObjectName("btn_5")
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(20, 50, 181, 31))
        self.lineEdit.setMinimumSize(QtCore.QSize(181, 31))
        self.lineEdit.setMaximumSize(QtCore.QSize(181, 31))
        self.lineEdit.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit_2.setGeometry(QtCore.QRect(20, 100, 181, 31))
        self.lineEdit_2.setMinimumSize(QtCore.QSize(181, 31))
        self.lineEdit_2.setMaximumSize(QtCore.QSize(181, 31))
        self.lineEdit_2.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.lineEdit_2.setObjectName("lineEdit_2")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)



    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Archiver"))
        self.btn_2.setText(_translate("MainWindow", "Извлечь \n"
                                                    " из архива"))
        self.btn_1.setText(_translate("MainWindow", "Добавить\n"
                                                    " в архив"))
        self.btn_3.setText(_translate("MainWindow", "Выбрать \n"
                                                    " исходный \n"
                                                    " файл"))
        self.label.setText(_translate("MainWindow", "Архиватор на RLE"))
        self.btn_4.setText(_translate("MainWindow", "Выбрать \n"
                                                    " результирующий \n"
                                                    " файл"))
        self.btn_5.setText(_translate("MainWindow", "Отмена"))
        self.lineEdit.setToolTip(_translate("MainWindow",
                                            "<html><head/><body><p>Введите путь к файлу.\n(Пример: folder/file.txt)</p></body></html>"))
        self.lineEdit_2.setToolTip(_translate("MainWindow",
                                              "<html><head/><body><p>Введите путь к файлу.\n(Пример: folder/file.txt)</p></body></html>"))

Ответы (1 шт):

Автор решения: S. Nick

Signals & Slots:

Сигналы и слоты используются для связи между объектами. Механизм сигналов и слотов является центральной особенностью Qt и, вероятно, той частью, которая больше всего отличается от функций, предоставляемых другими платформами. Сигналы и слоты становятся возможными благодаря мета-объектной системе Qt.

Я отметил для вас строки, в которые внес изменения.

import sys
import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog, QMessageBox
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt

#import view
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(342, 240)
        MainWindow.setMinimumSize(QtCore.QSize(342, 240))
        MainWindow.setMaximumSize(QtCore.QSize(342, 240))
        MainWindow.setStyleSheet("background-color: rgb(52, 61, 70);\n"
                                 "")
        self.setWindowTitle('Icon')
        self.setWindowIcon(QIcon('1486395874-settings_80622.ico'))
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
        self.progressBar.setGeometry(QtCore.QRect(20, 150, 216, 21))
        self.progressBar.setMinimumSize(QtCore.QSize(216, 21))
        self.progressBar.setMaximumSize(QtCore.QSize(216, 21))
        self.progressBar.setStyleSheet("color: rgb(255, 255, 255);\n"
                                       "background-color: rgb(181, 181, 181);\n"
                                       "")
        self.progressBar.setProperty("value", 0)
        self.progressBar.setObjectName("progressBar")
        self.btn_2 = QtWidgets.QPushButton(self.centralwidget)
        self.btn_2.setGeometry(QtCore.QRect(90, 180, 61, 31))
        self.btn_2.setStyleSheet("background-color: rgb(255, 255, 255);\n"
                                 "color: rgb(0, 0, 0);")
        self.btn_2.setObjectName("btn_2")
        self.btn_1 = QtWidgets.QPushButton(self.centralwidget)
        self.btn_1.setGeometry(QtCore.QRect(20, 180, 61, 31))
        self.btn_1.setStyleSheet("background-color: rgb(255, 255, 255);\n"
                                 "color: rgb(0, 0, 0);")
        self.btn_1.setObjectName("btn_1")
        self.btn_3 = QtWidgets.QPushButton(self.centralwidget)
        self.btn_3.setGeometry(QtCore.QRect(210, 50, 101, 41))
        self.btn_3.setStyleSheet("background-color: rgb(255, 255, 255);\n"
                                 "color: rgb(0, 0, 0);")
        self.btn_3.setObjectName("btn_3")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(10, 10, 211, 21))
        font = QtGui.QFont()
        font.setPointSize(14)
        self.label.setFont(font)
        self.label.setStyleSheet("color: rgb(255, 255, 255);")
        self.label.setObjectName("label")
        self.btn_4 = QtWidgets.QPushButton(self.centralwidget)
        self.btn_4.setGeometry(QtCore.QRect(210, 100, 101, 41))
        self.btn_4.setStyleSheet("background-color: rgb(255, 255, 255);\n"
                                 "color: rgb(0, 0, 0);")
        self.btn_4.setObjectName("btn_4")
        self.btn_5 = QtWidgets.QPushButton(self.centralwidget)
        self.btn_5.setGeometry(QtCore.QRect(160, 180, 41, 31))
        self.btn_5.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.btn_5.setObjectName("btn_5")
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(20, 50, 181, 31))
        self.lineEdit.setMinimumSize(QtCore.QSize(181, 31))
        self.lineEdit.setMaximumSize(QtCore.QSize(181, 31))
        self.lineEdit.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit_2.setGeometry(QtCore.QRect(20, 100, 181, 31))
        self.lineEdit_2.setMinimumSize(QtCore.QSize(181, 31))
        self.lineEdit_2.setMaximumSize(QtCore.QSize(181, 31))
        self.lineEdit_2.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.lineEdit_2.setObjectName("lineEdit_2")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Archiver"))
        self.btn_2.setText(_translate("MainWindow", "Извлечь \n"
                                                    " из архива"))
        self.btn_1.setText(_translate("MainWindow", "Добавить\n"
                                                    " в архив"))
        self.btn_3.setText(_translate("MainWindow", "Выбрать \n"
                                                    " исходный \n"
                                                    " файл"))
        self.label.setText(_translate("MainWindow", "Архиватор на RLE"))
        self.btn_4.setText(_translate("MainWindow", "Выбрать \n"
                                                    " результирующий \n"
                                                    " файл"))
        self.btn_5.setText(_translate("MainWindow", "Отмена"))
        self.lineEdit.setToolTip(_translate("MainWindow",
                                            "<html><head/><body><p>Введите путь к файлу.\n(Пример: folder/file.txt)</p></body></html>"))
        self.lineEdit_2.setToolTip(_translate("MainWindow",
                                              "<html><head/><body><p>Введите путь к файлу.\n(Пример: folder/file.txt)</p></body></html>"))



# import model
class Archiver(QtCore.QObject):                                  # QObject
    mySignal = QtCore.pyqtSignal(int)                            # +++ mySignal

    def __init__(self):                         # +++
        super(Archiver, self).__init__()        # +++
        self.path_in = ''                       # +++
        self.path_out = ''                      # +++
        self.res_4 = bytearray()                # +++

    # метод архиватор
    def pack(self, path_in, path_out):                            # + path_in, path_out
        self.path_in = path_in
        self.path_out = path_out

        self.res = bytearray()
#        self.step = 0
        with open(self.path_in, 'rb') as f:                       # -self.lineEdit.text()
            byte_arr = f.read()
        count = 1

        self.remember_file()                     # >>>

        self.move = (50 / (len(byte_arr) - 1))

        if len(byte_arr) == 0:
            return (self.res)

        for i in range(len(byte_arr) - 1):
            if byte_arr[i] == byte_arr[i + 1]:
                count += 1
            if byte_arr[i] != byte_arr[i + 1]:
                self.res.append(count)
                self.res.append(byte_arr[i])
                count = 1
            if count == 256:
                self.res.append(255)
                self.res.append(byte_arr[i])
                count = 1

#--            self.progress()
            self.mySignal.emit(self.move)                            # +++ mySignal

        self.res.append(count)
        self.res.append(byte_arr[-1])
        count = 0
        count_2 = 0
        self.res_2 = bytearray()
        flag = True
        self.move = 50 / (len(self.res) / 2)
        for i in range(0, len(self.res), 2):
            if self.res[i] == 1:
                count += 1
                if flag:
                    count_2 = i + 1
                    flag = False
                    self.res_2.append(0)
                if count == 255:
                    self.res_2.append(255)
                    for i in range(count):
                        self.res_2.append(self.res[count_2])
                        count_2 += 2
                    flag = True
                    count = 0
            if self.res[i] != 1:
                if flag == False:
                    self.res_2.append(count)
                    for j in range(count):
                        self.res_2.append(self.res[count_2])
                        count_2 += 2
                    flag = True
                    count = 0
                    self.res_2.append(self.res[i])
                    self.res_2.append(self.res[i + 1])
                    count_2 += 2
                else:
                    self.res_2.append(self.res[i])
                    self.res_2.append(self.res[i + 1])
                    count_2 += 2
            if i == len(self.res) - 2 and flag == False:
                self.res_2.append(count)
                for i in range(count):
                    self.res_2.append(self.res[count_2])
                    count_2 += 2

#--            self.progress()
            self.mySignal.emit(self.move)                            # +++ mySignal

        with open(self.path_out, 'wb') as p:                         # - self.lineEdit_2.text()
            p.write(self.res_2)
        self.mySignal.emit(self.move)                                # +++

    # метод разархиватор
    def unpack(self, path_in, path_out):                             # , path_in, path_out
#        self.step = 0
        with open(self.path_in, 'rb') as f:                          # self.lineEdit.text()
            byte_arr = f.read()
        self.remember_file()
        self.res_3 = bytearray()
        i = 0
        self.move = 100 / len(byte_arr)
        try:
            while i != len(byte_arr):
                if byte_arr[i] == 0:
                    i += 1
#                    self.progress()
#                    self.mySignal.emit(i)                            

                    for j in range(byte_arr[i]):
                        i += 1
                        self.res_3.append(byte_arr[i])
#                        self.progress()
#                        self.mySignal.emit(i)                         
                    i += 1

#                    self.progress()
#                    self.mySignal.emit(i)                   

                else:
                    i += 1
#                    self.progress()
#                    self.mySignal.emit(i)                
                    for j in range(byte_arr[i - 1]):
                        self.res_3.append(byte_arr[i])
#                        self.progress()
#                        self.mySignal.emit(i)             
                    i += 1
#                    self.progress()
#                    self.mySignal.emit(i)             

                self.mySignal.emit(self.move)     

        except IndexError:
            pass
            print('Что-то пошло не так ???')

        with open(self.path_out, 'wb') as p:                        # lineEdit_2.text()
            p.write(self.res_3)
        self.mySignal.emit(100)

    # сохранение файла
    def remember_file(self):
        self.res_4 = bytearray()
        with open(self.path_out, 'rb') as f:                        # self.lineEdit_2.text()
            byte_arr = f.read()                                     # - self.
        for i in range(len(byte_arr)):
            self.res_4.append(byte_arr[i])    
        print('# сохранение файла')


class Controller(QtWidgets.QMainWindow, Ui_MainWindow):   # view.
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.input_path = ''                                                # +
        self.output_path = ''                                               # +

        # функции обратного вызова
        self.btn_1.clicked.connect(self.launch_clicked)
        self.btn_2.clicked.connect(self.launch_clicked)
        self.btn_3.clicked.connect(self.choice_clicked)
        self.btn_4.clicked.connect(self.choice_clicked)
        self.btn_5.setEnabled(False)
        self.btn_5.clicked.connect(self.stop_action)
        self.lineEdit.textChanged.connect(self.nullify_progress)
        self.lineEdit_2.textChanged.connect(self.nullify_progress)


        self.archiver = Archiver()                                           # !!!
        self.archiver.mySignal.connect(self.progress)                        # !!! mySignal
        self.step = 0                                                        # +++

    '''
    # сохранение файла
    def remember_file(self):
        self.res_4 = bytearray()
        with open(self.lineEdit_2.text(), 'rb') as f:
            self.byte_arr = f.read()
        for i in range(len(self.byte_arr)):
            self.res_4.append(self.byte_arr[i])
    '''

    # выбор входного файла
    def input_file_selection(self):
        self.input_path, _ = QFileDialog.getOpenFileName(self, 'Выберите файл', '')
        self.lineEdit.setText(self.input_path)

    # выбор результирующего файла
    def output_file_selection(self):
        self.output_path, _ = QFileDialog.getOpenFileName(self, 'Выберите файл', '')
        self.lineEdit_2.setText(self.output_path)

    # увеличение значения progressBar
    def progress(self, move):                                                     ### + move mySignal
        self.step += move                                                         # move
#        self.progressBar.setValue(round(self.step))
        self.progressBar.setValue(self.step if self.step < 100 else 100)          # +

    # вызов окошка с сообщением об ошибке
    def message_box(self, text):
        msg = QMessageBox()
        msg.setWindowTitle('Error!')
        msg.setText(text)
        msg.setIcon(QMessageBox.Information)
        msg.exec_()

    # обнуление progressBar
    def nullify_progress(self):
        self.progressBar.setValue(0)

    # выборка по кнопке
    def choice_clicked(self):
        sender = self.sender()
        self.progressBar.setValue(0)
        if (sender.text() == "Выбрать \n"" исходный \n"" файл"):
            self.input_file_selection()
        else:
            self.output_file_selection()

    # запуск архиватора. в т.ч. проверка на ошибки
    def launch_clicked(self):
        sender = self.sender()
        if self.lineEdit.text() == '':
            self.message_box('Нет исходного файла.\nЗаполните пустые поля')
        elif self.lineEdit_2.text() == '':
            self.message_box('Нет результирующего файла.\nЗаполните пустые поля')
        elif (not os.path.isfile(self.lineEdit.text())):
            self.message_box('Неправильный путь исходного файла \nили такого файла не существует.')
        elif (not os.path.isfile(self.lineEdit_2.text())):
            self.message_box('Неправильный путь результирующего файла \nили такого файла не существует')
        else:
            self.btn_5.setEnabled(True)
            if (sender.text() == "Добавить\n" " в архив"):
###
#                model.Archiver.pack(self)
#            else:
#                model.Archiver.unpack(self)

                self.step = 0                                                         # +
                self.archiver.pack(self.lineEdit.text(), self.lineEdit_2.text())      # + !!!
            else:
                self.step = 0                                                         # +
                self.archiver.unpack(self.lineEdit.text(), self.lineEdit_2.text())    # + !!!

    # остановка действия
    def stop_action(self):
        self.btn_5.setEnabled(False)
        sender = self.sender()
        if (sender.text() == 'Отмена'):
            with open(self.lineEdit_2.text(), 'wb') as p:
#                p.write(self.res_4)
                p.write(self.archiver.res_4)                                        # !!! self.archiver.res_4
            self.progressBar.setValue(0)
            self.message_box('Прервано! \nРезультирующий файл не изменился.')

#метод запуска программы
def main():
    app = QtWidgets.QApplication(sys.argv)
    window = Controller()
    window.show()
    app.exec_()

#запуск программы
if __name__ == '__main__':
    main()

введите сюда описание изображения

→ Ссылка