Skip to content

views.file_load.upload_window

File-picker with real upload progress tracking.

The selected file is processed locally and the progress bar shows the actual upload progress.

FileLoadView

Bases: QMainWindow, Ui_UploadWindow

File upload widget with real progress tracking.

Emits a signal with the file path when upload completes successfully.

Source code in src/views/file_load/upload_window.py
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
class FileLoadView(QMainWindow, Ui_UploadWindow):
    """
    File upload widget with real progress tracking.

    Emits a signal with the file path when upload completes successfully.
    """

    # Signal emitted when upload finishes, carrying the file path
    uploadFinished = Signal(str)

    def __init__(self) -> None:
        """
        Sets up the upload window and connects UI elements to handlers.

        Prepares the browse button and initializes worker and file references.
        """
        super().__init__()
        # Set up UI components from the .ui file
        self.setupUi(self)
        # Connect the Browse button to the file dialog handler
        self.buttonBrowse.clicked.connect(self._browse)
        # Placeholder for the UploadWorker thread (will be created on browse)
        self._worker: Optional[UploadWorker] = None
        # Store selected file path
        self._file: Optional[str] = None

    # ==========================================================================
    #  File Browsing and Starting Upload
    # ==========================================================================
    def _browse(self) -> None:
        """
        Opens a file dialog to allow the user to pick a file.

        The filter is determined by which radio button is selected.
        """
        # Determine the file filter based on radio button selection
        if self.radioExcel.isChecked():
            file_name_filter = "Excel files (*.xlsx *.xls)"
        elif self.radioCSV.isChecked():
            file_name_filter = "CSV files (*.csv)"
        elif self.radioPDF.isChecked():
            file_name_filter = "PDF files (*.pdf)"
        else:
            # Fallback to all files if no specific radio is checked
            file_name_filter = "All files (*)"

        # Open the QFileDialog and retrieve the selected path
        path, _ = QFileDialog.getOpenFileName(self, "Pick file", "", file_name_filter)
        if path:
            # If a path was chosen, start the upload process
            self._start_upload(path)

    def _start_upload(self, path: str) -> None:
        """
        Starts the upload process by creating and running the worker thread.

        Disables the browse button, resets the progress bar, and connects worker signals.
        """
        # Store the chosen file path
        self._file = path
        # Display the path in the line edit
        self.lineEditFilePath.setText(path)
        # Reset progress bar to 0
        self.progressBar.setValue(0)
        # Disable the Browse button to prevent multiple uploads
        self.buttonBrowse.setEnabled(False)

        # Create the worker thread with the selected file path
        self._worker = UploadWorker(path)
        # Connect worker's progress signal to update the UI progress bar
        self._worker.progress.connect(self._update_progress)
        # Connect worker's finished signal to handle successful completion
        self._worker.finished.connect(self._upload_finished)
        # Connect worker's error signal to handle failures
        self._worker.error.connect(self._upload_error)
        # Start the worker thread (which invokes run() in a separate thread)
        self._worker.start()

    # ==========================================================================
    #  Progress and Completion Handlers
    # ==========================================================================
    def _update_progress(self, value: int) -> None:
        """
        Updates the progress bar to reflect the current upload percentage.

        Receives integer percentage from the worker.
        """
        # Set the progress bar's value to the emitted percentage
        self.progressBar.setValue(value)

    def _upload_finished(self, path: str) -> None:
        """
        Handles successful upload completion.

        Updates UI to reflect 100% completion and re-enables the browse button.
        Emits uploadFinished signal with the file path.
        """
        # Ensure progress bar shows complete
        self.progressBar.setValue(100)
        # Re-enable the Browse button so user can upload another file
        self.buttonBrowse.setEnabled(True)
        # Emit the finished signal to notify parent that upload is done
        self.uploadFinished.emit(path)

    def _upload_error(self, error_msg: str) -> None:
        """
        Handles errors that occur during upload.

        Resets the UI and shows a critical message box with the error.
        """
        # Re-enable the Browse button so user can retry
        self.buttonBrowse.setEnabled(True)
        # Reset progress bar to 0 to indicate failure
        self.progressBar.setValue(0)
        # Show an error message box with the error details
        QMessageBox.critical(self, "Upload Error", f"Failed to upload file: {error_msg}")

    # ==========================================================================
    #  Navigation Guards
    # ==========================================================================
    def can_go_next(self) -> bool:
        """
        Prevents navigation to the next view until upload is fully complete.

        Returns True only when progress bar reaches 100%.
        """
        return self.progressBar.value() == 100

    # noinspection PyMethodMayBeStatic
    def can_go_back(self) -> bool:
        """
        Prevents navigation backward from this first page.

        The Upload window is the first page, so going back is not allowed.
        """
        return False

__init__()

Sets up the upload window and connects UI elements to handlers.

Prepares the browse button and initializes worker and file references.

Source code in src/views/file_load/upload_window.py
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
def __init__(self) -> None:
    """
    Sets up the upload window and connects UI elements to handlers.

    Prepares the browse button and initializes worker and file references.
    """
    super().__init__()
    # Set up UI components from the .ui file
    self.setupUi(self)
    # Connect the Browse button to the file dialog handler
    self.buttonBrowse.clicked.connect(self._browse)
    # Placeholder for the UploadWorker thread (will be created on browse)
    self._worker: Optional[UploadWorker] = None
    # Store selected file path
    self._file: Optional[str] = None

can_go_back()

Prevents navigation backward from this first page.

The Upload window is the first page, so going back is not allowed.

Source code in src/views/file_load/upload_window.py
151
152
153
154
155
156
157
def can_go_back(self) -> bool:
    """
    Prevents navigation backward from this first page.

    The Upload window is the first page, so going back is not allowed.
    """
    return False

can_go_next()

Prevents navigation to the next view until upload is fully complete.

Returns True only when progress bar reaches 100%.

Source code in src/views/file_load/upload_window.py
142
143
144
145
146
147
148
def can_go_next(self) -> bool:
    """
    Prevents navigation to the next view until upload is fully complete.

    Returns True only when progress bar reaches 100%.
    """
    return self.progressBar.value() == 100