Example #1
0
    def setup_ui(self):
        # json file selector
        self.json_groupbox = QGroupBox("Export ODK Aggregate")
        layout = QGridLayout()
        self.json_select_button = PushButton("", self)
        self.json_select_button.clicked.connect(self.json_selector_clicked)
        layout.addWidget(self.json_select_button, 1, 0)
        self.json_groupbox.setLayout(layout)

        # destination folder selector
        self.destination_groupbox = QGroupBox("Destination")
        layout = QGridLayout()
        self.destination_select_button = PushButton(self.destination_folder,
                                                    self)
        self.destination_select_button.clicked.connect(
            self.destination_selector_clicked)
        layout.addWidget(self.destination_select_button, 1, 0)
        self.destination_groupbox.setLayout(layout)

        # period calendars
        today = datetime.date.today()
        self.period_groupbox = QGroupBox("Période")
        layout = QGridLayout()
        self.from_date_selector = DateTimeEdit(QDate(self.from_date))
        self.from_date_selector.dateChanged.connect(self.from_date_changed)
        self.from_date_selector.setMaximumDate(self.to_date)
        self.to_date_selector = DateTimeEdit(QDate(self.to_date))
        self.to_date_selector.dateChanged.connect(self.to_date_changed)
        self.to_date_selector.setMinimumDate(self.from_date)
        self.to_date_selector.setMaximumDate(today)
        layout.addWidget(Label("Du"), 2, 0)
        layout.addWidget(self.from_date_selector, 3, 0)
        layout.addWidget(Label("Au"), 2, 1)
        layout.addWidget(self.to_date_selector, 3, 1)
        self.period_groupbox.setLayout(layout)

        # start button
        self.start_button = PushButton("Démarrer")
        self.start_button.setEnabled(False)
        self.start_button.setDefault(True)
        self.start_button.clicked.connect(self.export_requested)

        # cancel button
        self.cancel_button = CancelPushButton("Annuler")
        self.cancel_button.setEnabled(False)
        self.cancel_button.clicked.connect(self.cancel_export)

        # grid
        self.gridBox = QGridLayout()
        self.gridBox.addWidget(self.json_groupbox, 0, 0, 1, 2)
        self.gridBox.addWidget(self.destination_groupbox, 1, 0, 1, 2)
        self.gridBox.addWidget(self.period_groupbox, 2, 0, 1, 2)
        self.gridBox.addWidget(self.start_button, 3, 0)
        self.gridBox.addWidget(self.cancel_button, 3, 1)

        vBox = QVBoxLayout()
        vBox.addLayout(self.gridBox)
        self.setLayout(vBox)

        self.json_fpath = None
Example #2
0
    def setup_ui(self):
        # json file selector
        self.json_groupbox = QGroupBox("Export ODK Aggregate")
        layout = QGridLayout()
        self.json_select_button = PushButton("", self)
        self.json_select_button.clicked.connect(self.json_selector_clicked)
        layout.addWidget(self.json_select_button, 1, 0)
        self.json_groupbox.setLayout(layout)

        # destination folder selector
        self.destination_groupbox = QGroupBox("Destination")
        layout = QGridLayout()
        self.destination_select_button = PushButton(
            self.destination_folder, self)
        self.destination_select_button.clicked.connect(
            self.destination_selector_clicked)
        layout.addWidget(self.destination_select_button, 1, 0)
        self.destination_groupbox.setLayout(layout)

        # period calendars
        today = datetime.date.today()
        self.period_groupbox = QGroupBox("Période")
        layout = QGridLayout()
        self.from_date_selector = DateTimeEdit(QDate(self.from_date))
        self.from_date_selector.dateChanged.connect(self.from_date_changed)
        self.from_date_selector.setMaximumDate(self.to_date)
        self.to_date_selector = DateTimeEdit(QDate(self.to_date))
        self.to_date_selector.dateChanged.connect(self.to_date_changed)
        self.to_date_selector.setMinimumDate(self.from_date)
        self.to_date_selector.setMaximumDate(today)
        layout.addWidget(Label("Du"), 2, 0)
        layout.addWidget(self.from_date_selector, 3, 0)
        layout.addWidget(Label("Au"), 2, 1)
        layout.addWidget(self.to_date_selector, 3, 1)
        self.period_groupbox.setLayout(layout)

        # start button
        self.start_button = PushButton("Démarrer")
        self.start_button.setEnabled(False)
        self.start_button.setDefault(True)
        self.start_button.clicked.connect(self.export_requested)

        # cancel button
        self.cancel_button = CancelPushButton("Annuler")
        self.cancel_button.setEnabled(False)
        self.cancel_button.clicked.connect(self.cancel_export)

        # grid
        self.gridBox = QGridLayout()
        self.gridBox.addWidget(self.json_groupbox, 0, 0, 1, 2)
        self.gridBox.addWidget(self.destination_groupbox, 1, 0, 1, 2)
        self.gridBox.addWidget(self.period_groupbox, 2, 0, 1, 2)
        self.gridBox.addWidget(self.start_button, 3, 0)
        self.gridBox.addWidget(self.cancel_button, 3, 1)

        vBox = QVBoxLayout()
        vBox.addLayout(self.gridBox)
        self.setLayout(vBox)

        self.json_fpath = None
Example #3
0
    def __init__(self, parent, nb_instances_successful, nb_instances_failed,
                 nb_medias_successful, nb_medias_failed, from_date, to_date,
                 *args, **kwargs):
        super(ConfirmationWidget, self).__init__(parent=parent)

        title_label = Label(
            "<h2><font color='green'>Félicitations !</font></h2>")
        icon_label = QLabel()
        icon_label.setPixmap(
            QPixmap(Constants.intpath([Constants.IMAGES_FOLDER,
                                       'success.png'])))

        date_fmt = "%d-%m-%Y"
        nb_submissions_total = nb_instances_successful + nb_instances_failed
        message_label = Label(
            "<p>L'ensemble des données de la collecte ;<br />"
            "({nb_submissions_total}) enregistrements entre le {from_date} "
            "et le {to_date} ;<br />"
            "ont été exportées avec succes.</p>"
            "<h6>Nombre enregistrements : {nb_instances_successful} </h6>"
            "<h6> Nombre de médias : {nb_medias_successful} </h6>".format(
                nb_submissions_total=nb_submissions_total,
                from_date=from_date.strftime(date_fmt),
                to_date=to_date.strftime(date_fmt),
                nb_instances_successful=nb_instances_successful,
                nb_medias_successful=nb_medias_successful))

        size_policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        message_label.setSizePolicy(size_policy)

        reset_button = PushButton("Nouvel export")
        reset_button.clicked.connect(self.parentWidget().reset)

        quit_button = PushButton("Quitter")
        quit_button.clicked.connect(self.parentWidget().close)

        gridBox = QGridLayout()
        gridBox.addWidget(icon_label, 0, 1)
        gridBox.addWidget(title_label, 0, 2)
        gridBox.addWidget(message_label, 1, 1, 3, 2)
        gridBox.addWidget(reset_button, 4, 1)
        gridBox.addWidget(quit_button, 4, 2)
        gridBox.setRowStretch(1, 3)

        vBox = QVBoxLayout()
        vBox.addLayout(gridBox)
        self.setLayout(vBox)
Example #4
0
    def __init__(self, parent=None, *args, **kwargs):
        super(QDialog, self).__init__(parent)
        super(BaseWidget, self).__init__(parent)

        self.setWindowTitle("ODK Aggregate indisponible")
        self.setWindowIcon(QIcon(Constants.intpath(Constants.PNG_ICON)))

        icon_label = QLabel()
        icon_label.setPixmap(
            QPixmap(Constants.intpath([Constants.IMAGES_FOLDER, 'alert.png'])))
        title = Label(
            "<h3><font color='orange'>ODK Aggregate indisponible</font></h3>")
        message = Label(
            "<p>Impossible de joindre le serveur ODK Aggregate.</p>"
            "<h6>Merci de vérifier la configuration du réseau et le lancement "
            "de la machine virtuelle. </h6>"
            "<hr/>"
            "<h6> Sans le serveur ODK Aggregate; vous pourrez exporter les "
            "fiches d'enquête préremplies, </h6>"
            "mais vous ne pourrez pas exporter les médias."
            "<h4> Voulez-vous continuer sans ODK Aggregate ?</h4>")

        continue_button = PushButton("Continuez sans les médias")
        continue_button.clicked.connect(self.accept)

        cancel_button = PushButton("Annuler l'export")
        cancel_button.clicked.connect(self.close)
        cancel_button.setFocus()

        # grid layout
        gridBox = QGridLayout()
        gridBox.addWidget(icon_label, 0, 0)
        gridBox.addWidget(title, 0, 1)
        gridBox.addWidget(message, 1, 1, 2, 2)
        gridBox.addWidget(cancel_button, 4, 2)
        gridBox.addWidget(continue_button, 4, 1)
        gridBox.setRowStretch(3, 2)

        vbox = QVBoxLayout()
        vbox.addLayout(gridBox)
        self.setLayout(vbox)
Example #5
0
    def __init__(self, parent=None, *args, **kwargs):
        super(QDialog, self).__init__(parent)
        super(BaseWidget, self).__init__(parent)

        self.setWindowTitle("ODK Aggregate indisponible")
        self.setWindowIcon(QIcon(Constants.intpath(Constants.PNG_ICON)))

        icon_label = QLabel()
        icon_label.setPixmap(
            QPixmap(Constants.intpath([Constants.IMAGES_FOLDER, 'alert.png'])))
        title = Label(
            "<h3><font color='orange'>ODK Aggregate indisponible</font></h3>")
        message = Label(
            "<p>Impossible de joindre le serveur ODK Aggregate.</p>"
            "<h6>Merci de vérifier la configuration du réseau et le lancement "
            "de la machine virtuelle. </h6>"
            "<hr/>"
            "<h6> Sans le serveur ODK Aggregate; vous pourrez exporter les "
            "fiches d'enquête préremplies, </h6>"
            "mais vous ne pourrez pas exporter les médias."
            "<h4> Voulez-vous continuer sans ODK Aggregate ?</h4>")

        continue_button = PushButton("Continuez sans les médias")
        continue_button.clicked.connect(self.accept)

        cancel_button = PushButton("Annuler l'export")
        cancel_button.clicked.connect(self.close)
        cancel_button.setFocus()

        # grid layout
        gridBox = QGridLayout()
        gridBox.addWidget(icon_label, 0, 0)
        gridBox.addWidget(title, 0, 1)
        gridBox.addWidget(message, 1, 1, 2, 2)
        gridBox.addWidget(cancel_button, 4, 2)
        gridBox.addWidget(continue_button, 4, 1)
        gridBox.setRowStretch(3, 2)

        vbox = QVBoxLayout()
        vbox.addLayout(gridBox)
        self.setLayout(vbox)
Example #6
0
class HomeWidget(BaseWidget):
    def __init__(self, parent=0, *args, **kwargs):
        super(HomeWidget, self).__init__(parent=parent, *args, **kwargs)

        # inputs
        self._json_fpath = None
        self._destination_folder = self.guess_destination()
        self._from_date, self._to_date = self.guess_dates()
        self.nb_instances = 0

        self.setup_ui()

    @property
    def json_fpath(self):
        return self._json_fpath

    @json_fpath.setter
    def json_fpath(self, value):
        self._json_fpath = value
        self.json_select_button.setText(
            value if value else "Sélection fichier JSON ODK Aggregate ...")
        self.update_start_button_state()

    @property
    def destination_folder(self):
        return self._destination_folder

    @destination_folder.setter
    def destination_folder(self, value):
        self._destination_folder = value
        self.destination_select_button.setText(self.destination_folder)
        self.update_start_button_state()

    @property
    def from_date(self):
        return self._from_date

    @from_date.setter
    def from_date(self, value):
        self._from_date = value
        self.from_date_selector.setPythonDate(self.from_date)
        self.update_start_button_state()

    @property
    def to_date(self):
        return self._to_date

    @to_date.setter
    def to_date(self, value):
        self._to_date = value
        self.to_date_selector.setPythonDate(self.to_date)
        self.update_start_button_state()

    def setup_ui(self):
        # json file selector
        self.json_groupbox = QGroupBox("Export ODK Aggregate")
        layout = QGridLayout()
        self.json_select_button = PushButton("", self)
        self.json_select_button.clicked.connect(self.json_selector_clicked)
        layout.addWidget(self.json_select_button, 1, 0)
        self.json_groupbox.setLayout(layout)

        # destination folder selector
        self.destination_groupbox = QGroupBox("Destination")
        layout = QGridLayout()
        self.destination_select_button = PushButton(self.destination_folder,
                                                    self)
        self.destination_select_button.clicked.connect(
            self.destination_selector_clicked)
        layout.addWidget(self.destination_select_button, 1, 0)
        self.destination_groupbox.setLayout(layout)

        # period calendars
        today = datetime.date.today()
        self.period_groupbox = QGroupBox("Période")
        layout = QGridLayout()
        self.from_date_selector = DateTimeEdit(QDate(self.from_date))
        self.from_date_selector.dateChanged.connect(self.from_date_changed)
        self.from_date_selector.setMaximumDate(self.to_date)
        self.to_date_selector = DateTimeEdit(QDate(self.to_date))
        self.to_date_selector.dateChanged.connect(self.to_date_changed)
        self.to_date_selector.setMinimumDate(self.from_date)
        self.to_date_selector.setMaximumDate(today)
        layout.addWidget(Label("Du"), 2, 0)
        layout.addWidget(self.from_date_selector, 3, 0)
        layout.addWidget(Label("Au"), 2, 1)
        layout.addWidget(self.to_date_selector, 3, 1)
        self.period_groupbox.setLayout(layout)

        # start button
        self.start_button = PushButton("Démarrer")
        self.start_button.setEnabled(False)
        self.start_button.setDefault(True)
        self.start_button.clicked.connect(self.export_requested)

        # cancel button
        self.cancel_button = CancelPushButton("Annuler")
        self.cancel_button.setEnabled(False)
        self.cancel_button.clicked.connect(self.cancel_export)

        # grid
        self.gridBox = QGridLayout()
        self.gridBox.addWidget(self.json_groupbox, 0, 0, 1, 2)
        self.gridBox.addWidget(self.destination_groupbox, 1, 0, 1, 2)
        self.gridBox.addWidget(self.period_groupbox, 2, 0, 1, 2)
        self.gridBox.addWidget(self.start_button, 3, 0)
        self.gridBox.addWidget(self.cancel_button, 3, 1)

        vBox = QVBoxLayout()
        vBox.addLayout(self.gridBox)
        self.setLayout(vBox)

        self.json_fpath = None

    def guess_destination(self, root_only=False):
        start_folder = os.path.join(os.path.expanduser("~"), 'Desktop')
        if root_only:
            return start_folder
        return os.path.join(start_folder, Constants.DEFAULT_FOLDER_NAME)

    def guess_dates(self):
        to = datetime.date.today()
        start = to - datetime.timedelta(days=15)
        return start, to

    def update_start_button_state(self):
        self.start_button.setEnabled(
            all([
                self.json_fpath, self.destination_folder, self.from_date,
                self.to_date
            ]))

    def json_selector_clicked(self):
        # self.file_name_field.setText("Aucun fichier")
        self.start_button.setEnabled(False)
        fpath = QFileDialog.getOpenFileName(
            self, "Choisir le fichier d'export JSON", self.json_fpath
            or self.guess_destination(root_only=True),
            "Fichiers JSON (*.json)")
        self.json_fpath = os.path.abspath(fpath) if fpath else self.json_fpath

    def destination_selector_clicked(self):
        path = QFileDialog.getExistingDirectory(self,
                                                "Sélectionner le dossier",
                                                self.destination_folder)
        if path:
            self.destination_folder = os.path.abspath(path)

    def from_date_changed(self, new_date):
        self.from_date = new_date.toPyDate()

    def to_date_changed(self, new_date):
        self.to_date = new_date.toPyDate()

    def export_requested(self):
        logger.debug("export_requested")
        self.parentWidget().exporter.check_aggregate_presence()

    def display_missing_aggregate_confirmation(self):
        if MissingODKConfirmationWidget().exec_() == QDialog.Accepted:
            self.start_export()

    def start_export(self):
        logger.debug("Lancement ...")
        self.add_progressbar()
        self.start_button.setEnabled(False)
        self.cancel_button.setEnabled(True)
        self.parentWidget().exporter.parse(
            destination_folder=self.destination_folder,
            fname=self.json_fpath,
            from_date=self.from_date,
            to_date=self.to_date)

    def cancel_export(self):
        logger.debug("cancel")
        self.parentWidget().exporter.cancel()

    def update_progress_label(self, index):
        progression_label = "Export en cours...    {index}/{total}" \
                            .format(index=index,
                                    total=self.nb_instances)
        self.progression_groupbox.setTitle(progression_label)

    def add_progressbar(self):
        self.progressbar = QProgressBar()
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(100)
        self.progressbar.reset()
        self.progressbar.setTextVisible(False)

        self.progression_groupbox = QGroupBox("...")
        progress_layout = QHBoxLayout()
        progress_layout.addWidget(self.progressbar)
        self.progression_groupbox.setLayout(progress_layout)
        self.gridBox.addWidget(self.progression_groupbox, 4, 0, 1, 2)

    def remove_progressbar(self):
        self.progression_groupbox.deleteLater()
        self.progression_groupbox = None

    @pyqtSlot(bool, int, str)
    def parsing_ended(self, succeeded, nb_instances, error_message):
        if succeeded:
            self.nb_instances = nb_instances

    @pyqtSlot(str, int)
    def exporting_instance(self, ident, index):
        logger.debug("exporting_instance")
        self.update_progress_label(index)

    @pyqtSlot(bool, int)
    def instance_completed(self, succeeded, index):
        logger.debug("instance_completed")
        pc = index * 100 // self.nb_instances
        self.progressbar.setValue(pc)

    @pyqtSlot(int, int, int, int)
    def export_ended(self, nb_instances_successful, nb_instances_failed,
                     nb_medias_successful, nb_medias_failed):
        self.cancel_button.setEnabled(False)
        self.start_button.setEnabled(True)

    @pyqtSlot()
    def export_canceled(self):
        self.remove_progressbar()
        self.cancel_button.setEnabled(False)
        self.start_button.setEnabled(True)
        QMessageBox.warning(
            self, "Export annulé !", "L'export en cours a été annulé.\n"
            "Tous les fichiers créés ont été supprimés", QMessageBox.Ok,
            QMessageBox.NoButton)
        if self.parentWidget().is_exiting:
            self.parentWidget().do_close()
Example #7
0
class HomeWidget(BaseWidget):

    def __init__(self, parent=0, *args, **kwargs):
        super(HomeWidget, self).__init__(parent=parent, *args, **kwargs)

        # inputs
        self._json_fpath = None
        self._destination_folder = self.guess_destination()
        self._from_date, self._to_date = self.guess_dates()
        self.nb_instances = 0

        self.setup_ui()

    @property
    def json_fpath(self):
        return self._json_fpath

    @json_fpath.setter
    def json_fpath(self, value):
        self._json_fpath = value
        self.json_select_button.setText(
            value if value else "Sélection fichier JSON ODK Aggregate ...")
        self.update_start_button_state()

    @property
    def destination_folder(self):
        return self._destination_folder

    @destination_folder.setter
    def destination_folder(self, value):
        self._destination_folder = value
        self.destination_select_button.setText(self.destination_folder)
        self.update_start_button_state()

    @property
    def from_date(self):
        return self._from_date

    @from_date.setter
    def from_date(self, value):
        self._from_date = value
        self.from_date_selector.setPythonDate(self.from_date)
        self.update_start_button_state()

    @property
    def to_date(self):
        return self._to_date

    @to_date.setter
    def to_date(self, value):
        self._to_date = value
        self.to_date_selector.setPythonDate(self.to_date)
        self.update_start_button_state()

    def setup_ui(self):
        # json file selector
        self.json_groupbox = QGroupBox("Export ODK Aggregate")
        layout = QGridLayout()
        self.json_select_button = PushButton("", self)
        self.json_select_button.clicked.connect(self.json_selector_clicked)
        layout.addWidget(self.json_select_button, 1, 0)
        self.json_groupbox.setLayout(layout)

        # destination folder selector
        self.destination_groupbox = QGroupBox("Destination")
        layout = QGridLayout()
        self.destination_select_button = PushButton(
            self.destination_folder, self)
        self.destination_select_button.clicked.connect(
            self.destination_selector_clicked)
        layout.addWidget(self.destination_select_button, 1, 0)
        self.destination_groupbox.setLayout(layout)

        # period calendars
        today = datetime.date.today()
        self.period_groupbox = QGroupBox("Période")
        layout = QGridLayout()
        self.from_date_selector = DateTimeEdit(QDate(self.from_date))
        self.from_date_selector.dateChanged.connect(self.from_date_changed)
        self.from_date_selector.setMaximumDate(self.to_date)
        self.to_date_selector = DateTimeEdit(QDate(self.to_date))
        self.to_date_selector.dateChanged.connect(self.to_date_changed)
        self.to_date_selector.setMinimumDate(self.from_date)
        self.to_date_selector.setMaximumDate(today)
        layout.addWidget(Label("Du"), 2, 0)
        layout.addWidget(self.from_date_selector, 3, 0)
        layout.addWidget(Label("Au"), 2, 1)
        layout.addWidget(self.to_date_selector, 3, 1)
        self.period_groupbox.setLayout(layout)

        # start button
        self.start_button = PushButton("Démarrer")
        self.start_button.setEnabled(False)
        self.start_button.setDefault(True)
        self.start_button.clicked.connect(self.export_requested)

        # cancel button
        self.cancel_button = CancelPushButton("Annuler")
        self.cancel_button.setEnabled(False)
        self.cancel_button.clicked.connect(self.cancel_export)

        # grid
        self.gridBox = QGridLayout()
        self.gridBox.addWidget(self.json_groupbox, 0, 0, 1, 2)
        self.gridBox.addWidget(self.destination_groupbox, 1, 0, 1, 2)
        self.gridBox.addWidget(self.period_groupbox, 2, 0, 1, 2)
        self.gridBox.addWidget(self.start_button, 3, 0)
        self.gridBox.addWidget(self.cancel_button, 3, 1)

        vBox = QVBoxLayout()
        vBox.addLayout(self.gridBox)
        self.setLayout(vBox)

        self.json_fpath = None

    def guess_destination(self, root_only=False):
        start_folder = os.path.join(os.path.expanduser("~"), 'Desktop')
        if root_only:
            return start_folder
        return os.path.join(start_folder, Constants.DEFAULT_FOLDER_NAME)

    def guess_dates(self):
        to = datetime.date.today()
        start = to - datetime.timedelta(days=15)
        return start, to

    def update_start_button_state(self):
        self.start_button.setEnabled(
            all([self.json_fpath, self.destination_folder,
                 self.from_date, self.to_date]))

    def json_selector_clicked(self):
        # self.file_name_field.setText("Aucun fichier")
        self.start_button.setEnabled(False)
        fpath = QFileDialog.getOpenFileName(
            self, "Choisir le fichier d'export JSON",
            self.json_fpath or self.guess_destination(root_only=True),
            "Fichiers JSON (*.json)")
        self.json_fpath = os.path.abspath(fpath) if fpath else self.json_fpath

    def destination_selector_clicked(self):
        path = QFileDialog.getExistingDirectory(
            self, "Sélectionner le dossier", self.destination_folder)
        if path:
            self.destination_folder = os.path.abspath(path)

    def from_date_changed(self, new_date):
        self.from_date = new_date.toPyDate()

    def to_date_changed(self, new_date):
        self.to_date = new_date.toPyDate()

    def export_requested(self):
        logger.debug("export_requested")
        self.parentWidget().exporter.check_aggregate_presence()

    def display_missing_aggregate_confirmation(self):
        if MissingODKConfirmationWidget().exec_() == QDialog.Accepted:
            self.start_export()

    def start_export(self):
        logger.debug("Lancement ...")
        self.add_progressbar()
        self.start_button.setEnabled(False)
        self.cancel_button.setEnabled(True)
        self.parentWidget().exporter.parse(
            destination_folder=self.destination_folder,
            fname=self.json_fpath,
            from_date=self.from_date,
            to_date=self.to_date)

    def cancel_export(self):
        logger.debug("cancel")
        self.parentWidget().exporter.cancel()

    def update_progress_label(self, index):
        progression_label = "Export en cours...    {index}/{total}" \
                            .format(index=index,
                                    total=self.nb_instances)
        self.progression_groupbox.setTitle(progression_label)

    def add_progressbar(self):
        self.progressbar = QProgressBar()
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(100)
        self.progressbar.reset()
        self.progressbar.setTextVisible(False)

        self.progression_groupbox = QGroupBox("...")
        progress_layout = QHBoxLayout()
        progress_layout.addWidget(self.progressbar)
        self.progression_groupbox.setLayout(progress_layout)
        self.gridBox.addWidget(self.progression_groupbox, 4, 0, 1, 2)

    def remove_progressbar(self):
        self.progression_groupbox.deleteLater()
        self.progression_groupbox = None

    @pyqtSlot(bool, int, str)
    def parsing_ended(self, succeeded, nb_instances, error_message):
        if succeeded:
            self.nb_instances = nb_instances

    @pyqtSlot(str, int)
    def exporting_instance(self, ident, index):
        logger.debug("exporting_instance")
        self.update_progress_label(index)

    @pyqtSlot(bool, int)
    def instance_completed(self, succeeded, index):
        logger.debug("instance_completed")
        pc = index * 100 // self.nb_instances
        self.progressbar.setValue(pc)

    @pyqtSlot(int, int, int, int)
    def export_ended(self, nb_instances_successful, nb_instances_failed,
                     nb_medias_successful, nb_medias_failed):
        self.cancel_button.setEnabled(False)
        self.start_button.setEnabled(True)

    @pyqtSlot()
    def export_canceled(self):
        self.remove_progressbar()
        self.cancel_button.setEnabled(False)
        self.start_button.setEnabled(True)
        QMessageBox.warning(self,
                            "Export annulé !",
                            "L'export en cours a été annulé.\n"
                            "Tous les fichiers créés ont été supprimés",
                            QMessageBox.Ok,
                            QMessageBox.NoButton)
        if self.parentWidget().is_exiting:
            self.parentWidget().do_close()