class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, path, config_dict, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        logging.info('mainwindow.py - UI initialization ...')
        self.setupUi(self)
        self.config_dict = config_dict
        self.config_path = path
        object_init(self)
        info_button_text(self)
        dataset_data_information(self)
        itemDelegate = QtWidgets.QStyledItemDelegate()
        self.main_cb_1.setItemDelegate(itemDelegate)
        self.main_cb_2.setItemDelegate(itemDelegate)
        self.main_cb_3.setItemDelegate(itemDelegate)
        self.main_cb_4.setItemDelegate(itemDelegate)
        self.main_cb_5.setItemDelegate(itemDelegate)
        self.main_cb_6.setItemDelegate(itemDelegate)
        self.main_cb_7.setItemDelegate(itemDelegate)
        self.main_cb_8.setItemDelegate(itemDelegate)
        self.download_method.setItemDelegate(itemDelegate)
        for i in range(5):
            self.download_method.model().item(i + 1).setEnabled(False)
        self.downloadproduct.clicked.connect(lambda: self.download_product())
        self.api_information()
        self.check_downloader_update()
        self.check_file_folder()
        self.prepare_datasets_database()
        self.main_cb_1.currentIndexChanged.connect(
            lambda: activate_type_cb(self))
        self.product_info_button.clicked.connect(self.product_information)
        self.main_cb_6.currentIndexChanged.connect(self.set_modified)
        self.main_cb_7.currentIndexChanged.connect(self.set_modified)
        self.main_cb_8.currentIndexChanged.connect(self.set_modified)
        self.space_ln_north.textChanged.connect(self.set_modified)
        self.space_ln_south.textChanged.connect(self.set_modified)
        self.space_ln_west.textChanged.connect(self.set_modified)
        self.space_ln_east.textChanged.connect(self.set_modified)
        self.main_ln_1.textChanged.connect(self.set_modified)
        self.main_de_1.dateChanged.connect(self.set_modified)
        self.main_de_2.dateChanged.connect(self.set_modified)
        for button in self.info_button_list:
            button.clicked.connect(lambda: info_button(self))
        self.make_window_title()
        logging.info('mainwindow.py - UI initialized ...')
        logging.info('*****************************************')

    @QtCore.pyqtSlot()
    def on_actionExit_triggered(self):
        self.close()

    @QtCore.pyqtSlot()
    def on_actionSave_triggered(self):
        self.save_document()

    @QtCore.pyqtSlot()
    def on_actionOpen_triggered(self):
        self.open_document()

    @QtCore.pyqtSlot()
    def on_actionExpert_triggered(self):
        self.open_expert_mode()

    @QtCore.pyqtSlot()
    def on_actionAbout_triggered(self):
        self.open_about()

    @QtCore.pyqtSlot()
    def on_actionOptions_triggered(self):
        self.open_options()

    @QtCore.pyqtSlot()
    def on_actionUpdate_triggered(self):
        self.download_and_install_update()

    def save_document(self):
        logging.debug('mainwindow.py - save_document')
        filename = self.get_file_name('save')
        if filename:
            save_xml_query(self, filename)

    def open_document(self):
        logging.debug('mainwindow.py - open_document')
        if self.modified:
            result = self.save_warning_window("Open")
            if result == "save_button":
                self.save_document()
                filename = self.get_file_name('open')
                if filename:
                    open_xml_query(self, filename)
            elif result == "nosave_button":
                filename = self.get_file_name('open')
                if filename:
                    open_xml_query(self, filename)
        else:
            filename = self.get_file_name('open')
            if filename:
                open_xml_query(self, filename)

    def open_expert_mode(self):
        logging.debug('mainwindow.py - open_expert_mode')
        self.expertWindow = MyExpert(self.info_button_text_dict)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.expertWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.expertWindow.setGeometry(x2, y2, w2, h2)
        self.expertWindow.exec_()
        query, filename = self.expertWindow.query, self.expertWindow.filename
        action, suffix = self.expertWindow.action, self.expertWindow.suffix
        if query and filename and action and suffix:
            if suffix == 'FTP':
                self.download_product_ftp(query)
            else:
                self.launch_query(query, filename, action, suffix)

    def open_about(self):
        logging.debug('mainwindow.py - open_about')
        text = (
            "The CMEMS Data Downloader v" + _downloader_version +
            " was developed by Olivier Henry" + ", using Eclipse " +
            _eclipse_version + ", Python " + _py_version + " and PyQt " +
            _qt_version +
            ". It was designed to help researchers to download data from CMEMS dif"
            + "ferent datasets by using the official CLS Motu API.")
        self.aboutWindow = MyAbout(text)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.aboutWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.aboutWindow.setGeometry(x2, y2, w2, h2)
        self.aboutWindow.setMinimumSize(QtCore.QSize(850, 450))
        self.aboutWindow.setMaximumSize(QtCore.QSize(850, 450))
        self.aboutWindow.exec_()

    def open_options(self):
        logging.debug('mainwindow.py - open_options')
        self.optionWindow = MyOptions(self.config_dict,
                                      self.info_button_text_dict)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.optionWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.optionWindow.setGeometry(x2, y2, w2, h2)
        self.optionWindow.exec_()
        if not self.optionWindow.cancel:
            self.config_dict = self.optionWindow.config_dict
            with open(os.path.join(self.config_path, 'cmems_downloader.ini'),
                      'w') as config_file:
                self.config_dict.write(config_file)
            logging.getLogger().setLevel(self.config_dict.get('LOG', 'level'))
            self.check_downloader_update()

    def api_information(self):
        logging.debug('mainwindow.py - api_information')
        if self.config_dict['OPTIONS'].getboolean('display_api_info'):
            self.apiWindow = MyApi()
            _, _, w, h = QtWidgets.QDesktopWidget().screenGeometry(
                -1).getRect()
            _, _, w2, h2 = self.apiWindow.geometry().getRect()
            self.apiWindow.setGeometry(w / 2 - w2 / 2, h / 2 - h2 / 2, w2, h2)
            self.apiWindow.setMinimumSize(QtCore.QSize(700, 550))
            self.apiWindow.setMaximumSize(QtCore.QSize(700, 550))
            self.apiWindow.exec_()
            if self.apiWindow.checkbox.isChecked():
                if not self.config_dict['OPTIONS'].getboolean(
                        'display_api_info'):
                    self.config_dict.set('OPTIONS', 'display_api_info', 'True')
                    with open(
                            os.path.join(self.config_path,
                                         'cmems_downloader.ini'),
                            'w') as config_file:
                        self.config_dict.write(config_file)
            else:
                if self.config_dict['OPTIONS'].getboolean('display_api_info'):
                    self.config_dict.set('OPTIONS', 'display_api_info',
                                         'False')
                    with open(
                            os.path.join(self.config_path,
                                         'cmems_downloader.ini'),
                            'w') as config_file:
                        self.config_dict.write(config_file)

    def check_file_folder(self):
        logging.debug('mainwindow.py - check_file_folder')
        if not os.path.isdir(self.config_dict.get(
                'CREDENTIALS', 'folder')) and self.config_dict.get(
                    'CREDENTIALS', 'folder'):
            logging.exception(
                'mainwindow.py - check_file_folder - exception occured when EDD checked the existence of the ECMWF file folder. '
                +
                'Please check that the folder exists. The folder option in the config file is going to be modified to the defa'
                + 'ult folder.')
            self.config_dict.set('CREDENTIALS', 'folder', '')
            with open(os.path.join(self.config_path, 'cmems_downloader.ini'),
                      'w') as config_file:
                self.config_dict.write(config_file)
            text = (
                'CDD has detected that the folder where ECMWF files are saved doesn\'t exist anymore. It has been reseted in the config file'
                +
                ' to the default folder. Please check your options and set a new folder for ECMWF files.'
            )
            self.infoWindow = MyInfo(text)
            _, _, w, h = QtWidgets.QDesktopWidget().screenGeometry(
                -1).getRect()
            _, _, w2, h2 = self.infoWindow.geometry().getRect()
            self.infoWindow.setGeometry(w / 2 - w2 / 2, h / 2 - h2 / 2, 450,
                                        self.infoWindow.sizeHint().height())
            self.infoWindow.setMinimumSize(
                QtCore.QSize(450,
                             self.infoWindow.sizeHint().height()))
            self.infoWindow.setMaximumSize(
                QtCore.QSize(450,
                             self.infoWindow.sizeHint().height()))
            self.infoWindow.exec_()

    def prepare_datasets_database(self):
        logging.debug('mainwindow.py - prepare_datasets_database')
        database_path = 'database/'
        file_nbr = 0
        try:
            if os.path.isdir(database_path):
                self.product_database, self.dataset_database = {}, {}
                for file in os.listdir(database_path):
                    if os.path.isfile(
                            os.path.join(database_path, file)
                    ) and file[
                            -4:] == '.dat' and file != 'PRODUCT_DATABASE.dat':
                        domain, data_type, source, mode, product, short_description, description, resolution = None, None, None, None, None, None, None, None
                        temporal_resolution, level, data_type, vertical, temporal, production, image, variables = None, None, None, None, None, None, None, None
                        subset, swath, suffix, other_parameters = None, None, None, None
                        name = file[:-4]
                        f = open(database_path + file, 'r', encoding='utf-8')
                        for line in f:
                            if line[:3] != '###':
                                index = line.find('=')
                                parameter = line[:index]
                                value = line[index + 1:].replace('\n', '')
                                if parameter != 'version' and parameter != 'creation_date':
                                    if parameter == 'server_url':
                                        if value == 'None':
                                            server_url = None
                                        else:
                                            server_url = value
                                    if parameter == 'ftp_url':
                                        ftp_url = value
                                    if parameter == 'domain':
                                        domain = value
                                    if parameter == 'type':
                                        data_type = value
                                    if parameter == 'source':
                                        source = value
                                    if parameter == 'mode':
                                        mode = value
                                    if parameter == 'product':
                                        product = value
                                    if parameter == 'short_description':
                                        short_description = value
                                    if parameter == 'description':
                                        description = value
                                    if parameter == 'resolution':
                                        resolution = value
                                    if parameter == 'temporal_resolution':
                                        temporal_resolution = value
                                    if parameter == 'level':
                                        level = value
                                    if parameter == 'dataset_type':
                                        dataset_type = value
                                    if parameter == 'vertical':
                                        vertical = value
                                    if parameter == 'swath_vertical':
                                        swath_vertical_tmp = value
                                        if swath_vertical_tmp == 'None':
                                            swath_vertical = None
                                        else:
                                            swath_vertical = []
                                            if '|' in swath_vertical_tmp:
                                                swath_vertical_tmp = swath_vertical_tmp.split(
                                                    '|')
                                                for swath in swath_vertical_tmp:
                                                    if 'to' in swath:
                                                        index = swath.find(
                                                            'to')
                                                        start = swath[:
                                                                      index].split(
                                                                          '/')
                                                        end = swath[index +
                                                                    2:].split(
                                                                        '/')
                                                        swath_vertical.append(
                                                            [start, end])
                                                    else:
                                                        swath_vertical.append(
                                                            [swath, swath])
                                            else:
                                                index = swath_vertical_tmp.find(
                                                    'to')
                                                start = swath_vertical_tmp[:
                                                                           index].split(
                                                                               '/'
                                                                           )
                                                end = swath_vertical_tmp[
                                                    index + 2:].split('/')
                                                swath_vertical.append(
                                                    [start, end])
                                    if parameter == 'temporal':
                                        temporal = value
                                    if parameter == 'production':
                                        production = value
                                    if parameter == 'image':
                                        image = value
                                    if parameter == 'variables':
                                        variables = value
                                        if variables == 'None':
                                            variables = None
                                        else:
                                            if '|' in variables:
                                                variables = variables.split(
                                                    '|')
                                                for index, var in enumerate(
                                                        variables):
                                                    if ',' in var:
                                                        var = var.split(',')
                                                    else:
                                                        var = [var]
                                                    variables[index] = sorted(
                                                        var)
                                            elif ',' in variables:
                                                variables = sorted(
                                                    variables.split(','))
                                            else:
                                                variables = [variables]
                                    if parameter == 'swath':
                                        swath = value
                                        if ',' in swath:
                                            swath = swath.split(',')
                                    if parameter == 'swath_temporal':
                                        swath_temporal = value
                                        if swath_temporal == 'None':
                                            swath_temporal = None
                                        else:
                                            if ',' in swath_temporal:
                                                swath_temporal = swath_temporal.split(
                                                    ',')
                                    if parameter == 'swath_temporal_resolution':
                                        swath_temporal_resolution = value
                                        if swath_temporal_resolution == 'None':
                                            swath_temporal_resolution = None
                                        else:
                                            if ',' in swath_temporal_resolution:
                                                swath_temporal_resolution = swath_temporal_resolution.split(
                                                    ',')
                                    if parameter == 'suffix':
                                        suffix = value
                                        if ',' in suffix:
                                            suffix = sorted(suffix.split(','))
                                        else:
                                            suffix = [suffix]
                                    if parameter == 'other_parameters':
                                        if value != 'None':
                                            other_parameters = ast.literal_eval(
                                                value)
                                        else:
                                            other_parameters = None
                        f.close()
                        try:
                            self.dataset_database[domain]
                        except KeyError:
                            self.dataset_database[domain] = {}
                        try:
                            self.dataset_database[domain][data_type]
                        except KeyError:
                            self.dataset_database[domain][data_type] = {}
                        try:
                            self.dataset_database[domain][data_type][source]
                        except KeyError:
                            self.dataset_database[domain][data_type][
                                source] = {}
                        try:
                            self.dataset_database[domain][data_type][source][
                                mode]
                        except KeyError:
                            self.dataset_database[domain][data_type][source][
                                mode] = []
                        self.dataset_database[domain][data_type][source][
                            mode].append(product)
                        try:
                            self.product_database[product]
                        except KeyError:
                            self.product_database[product] = {}
                        self.product_database[product]['information'] = {
                            'short_description': short_description,
                            'description': description,
                            'spatial_resolution': resolution,
                            'temporal_resolution': temporal_resolution,
                            'level': level,
                            'product_type': dataset_type,
                            'vertical_coverage': vertical,
                            'temporal_coverage': temporal,
                            'production': production,
                            'image': image
                        }
                        self.product_database[product]['variables'] = variables
                        self.product_database[product]['swath'] = swath
                        self.product_database[product][
                            'swath_temporal'] = swath_temporal
                        self.product_database[product][
                            'swath_temporal_resolution'] = swath_temporal_resolution
                        self.product_database[product][
                            'swath_vertical'] = swath_vertical
                        self.product_database[product]['suffix'] = suffix
                        self.product_database[product]['tree'] = [
                            domain, data_type, source, mode
                        ]
                        self.product_database[product][
                            'server_url'] = server_url
                        self.product_database[product]['ftp_url'] = ftp_url
                        self.product_database[product][
                            'other_parameters'] = other_parameters
                        file_nbr += 1
                domain_list = []
                for key, _ in self.dataset_database.items():
                    domain_list.append(key)
                self.main_cb_1.clear()
                self.main_cb_1.addItem('Make a choice...')
                self.main_cb_1.addItems(sorted(domain_list))
                logging.debug(
                    'mainwindow.py - prepare_datasets_database - database ready'
                )
                logging.info('mainwindow.py - prepare_datasets_database - ' +
                             str(file_nbr) + ' files have been read')
        except Exception:
            logging.exception(
                'An exception occured during the reading of the .dat files')

    def product_information(self):
        logging.debug('mainwindow.py - product_information')
        if self.main_cb_5.currentText(
        ) != 'Make a choice...' and self.main_cb_5.currentText(
        ) != 'No product available...':
            self.productWindow = MyProduct(
                self.main_cb_5.currentText(),
                self.product_database[self.main_cb_5.currentText()])
            x1, y1, w1, h1 = self.geometry().getRect()
            _, _, w2, h2 = self.productWindow.geometry().getRect()
            x2 = x1 + w1 / 2 - w2 / 2
            y2 = y1 + h1 / 2 - h2 / 2
            self.productWindow.setGeometry(x2, y2, w2, h2)
            self.productWindow.exec_()

    def download_product(self):
        if self.download_method.isEnabled():
            if self.download_method.currentText() != 'Make a choice...':
                if 'FTP' in self.download_method.currentText():
                    self.download_product_ftp()
                else:
                    if 'Check size' in self.download_method.currentText():
                        action = 'getSize'
                    else:
                        action = 'productdownload'
                    if 'Query' in self.download_method.currentText():
                        suffix = '-TDS'
                    elif 'Dataset' in self.download_method.currentText():
                        suffix = '-DGF'
                    self.launch_query(action=action, suffix=suffix)

    def launch_query(self,
                     query=None,
                     filename=None,
                     action=None,
                     suffix=None):
        logging.info('mainwindow.py - launch_query')
        if query is None and filename is None:
            user = self.config_dict['CREDENTIALS'].get('user')
            password = self.config_dict['CREDENTIALS'].get('password')
            if not user or not password:
                self.credentialsyWindow = MyCredentials(user, password)
                x1, y1, w1, h1 = self.geometry().getRect()
                _, _, w2, h2 = self.credentialsyWindow.geometry().getRect()
                x2 = x1 + w1 / 2 - w2 / 2
                y2 = y1 + h1 / 2 - h2 / 2
                self.credentialsyWindow.setGeometry(x2, y2, w2, h2)
                self.credentialsyWindow.exec_()
                if self.credentialsyWindow.username and self.credentialsyWindow.password:
                    user = self.credentialsyWindow.username
                    password = self.credentialsyWindow.password
            if user and password:
                query, motu_url, folder, filename = self.prepare_query()
                query['service'] = query['service'] + suffix
                if suffix == '-DGF':
                    try:
                        del query['x_lo']
                    except KeyError:
                        pass
                    try:
                        del query['x_hi']
                    except KeyError:
                        pass
                    try:
                        del query['y_lo']
                    except KeyError:
                        pass
                    try:
                        del query['y_hi']
                    except KeyError:
                        pass
                    try:
                        del query['z_lo']
                    except KeyError:
                        pass
                    try:
                        del query['z_hi']
                    except KeyError:
                        pass
                    try:
                        del query['variable']
                    except KeyError:
                        pass
                query['action'] = action
                self.queryWindow = MyQuery(query, motu_url, user, password,
                                           folder, filename)
                x1, y1, w1, h1 = self.geometry().getRect()
                _, _, w2, h2 = self.queryWindow.geometry().getRect()
                x2 = x1 + w1 / 2 - w2 / 2
                y2 = y1 + h1 / 2 - h2 / 2
                self.queryWindow.setGeometry(x2, y2, w2, h2)
                self.queryWindow.exec_()
                try:
                    download_time = self.queryWindow.download_time
                    file_path = self.queryWindow.file_path
                    average_speed = self.queryWindow.average_speed
                    self.successWindow = MySuccess(download_time, file_path,
                                                   average_speed)
                    x1, y1, w1, h1 = self.geometry().getRect()
                    _, _, w2, h2 = self.successWindow.geometry().getRect()
                    x2 = x1 + w1 / 2 - w2 / 2
                    y2 = y1 + h1 / 2 - h2 / 2
                    self.successWindow.setGeometry(x2, y2, w2, h2)
                    self.successWindow.exec_()
                except AttributeError:
                    pass
        else:
            user = self.config_dict['CREDENTIALS'].get('user')
            password = self.config_dict['CREDENTIALS'].get('password')
            if not user or not password:
                self.credentialsyWindow = MyCredentials(user, password)
                x1, y1, w1, h1 = self.geometry().getRect()
                _, _, w2, h2 = self.credentialsyWindow.geometry().getRect()
                x2 = x1 + w1 / 2 - w2 / 2
                y2 = y1 + h1 / 2 - h2 / 2
                self.credentialsyWindow.setGeometry(x2, y2, w2, h2)
                self.credentialsyWindow.exec_()
                if self.credentialsyWindow.username and self.credentialsyWindow.password:
                    user = self.credentialsyWindow.username
                    password = self.credentialsyWindow.password
            if user and password:
                folder = self.config_dict['CREDENTIALS'].get('folder')
                motu_url = query['url']
                del query['url']
                query['service'] = query['service'] + suffix
                if suffix == '-DGF':
                    try:
                        del query['x_lo']
                    except KeyError:
                        pass
                    try:
                        del query['x_hi']
                    except KeyError:
                        pass
                    try:
                        del query['y_lo']
                    except KeyError:
                        pass
                    try:
                        del query['y_hi']
                    except KeyError:
                        pass
                    try:
                        del query['z_lo']
                    except KeyError:
                        pass
                    try:
                        del query['z_hi']
                    except KeyError:
                        pass
                    try:
                        del query['variable']
                    except KeyError:
                        pass
                query['action'] = action
                self.queryWindow = MyQuery(query, motu_url, user, password,
                                           folder, filename)
                x1, y1, w1, h1 = self.geometry().getRect()
                _, _, w2, h2 = self.queryWindow.geometry().getRect()
                x2 = x1 + w1 / 2 - w2 / 2
                y2 = y1 + h1 / 2 - h2 / 2
                self.queryWindow.setGeometry(x2, y2, w2, h2)
                self.queryWindow.exec_()
                try:
                    download_time = self.queryWindow.download_time
                    file_path = self.queryWindow.file_path
                    average_speed = self.queryWindow.average_speed
                    self.successWindow = MySuccess(download_time, file_path,
                                                   average_speed)
                    x1, y1, w1, h1 = self.geometry().getRect()
                    _, _, w2, h2 = self.successWindow.geometry().getRect()
                    x2 = x1 + w1 / 2 - w2 / 2
                    y2 = y1 + h1 / 2 - h2 / 2
                    self.successWindow.setGeometry(x2, y2, w2, h2)
                    self.successWindow.exec_()
                except AttributeError:
                    pass

    def download_product_ftp(self, query=None):
        user = self.config_dict['CREDENTIALS'].get('user')
        password = self.config_dict['CREDENTIALS'].get('password')
        if not user or not password:
            self.credentialsyWindow = MyCredentials(user, password)
            x1, y1, w1, h1 = self.geometry().getRect()
            _, _, w2, h2 = self.credentialsyWindow.geometry().getRect()
            x2 = x1 + w1 / 2 - w2 / 2
            y2 = y1 + h1 / 2 - h2 / 2
            self.credentialsyWindow.setGeometry(x2, y2, w2, h2)
            self.credentialsyWindow.exec_()
            if self.credentialsyWindow.username and self.credentialsyWindow.password:
                user = self.credentialsyWindow.username
                password = self.credentialsyWindow.password
        if user and password:
            folder = self.config_dict['CREDENTIALS'].get('folder')
            if query is None:
                product = str(self.main_cb_5.currentText())
                dataset = str(self.main_cb_6.currentText())
                ftp_url = self.product_database[product]['ftp_url'][6:]
            else:
                product = query['service']
                dataset = query['product']
                ftp_url = query['url']
            self.ftpWindow = MyFTP(user, password, product, dataset, ftp_url,
                                   folder)
            self.ftpWindow.exec_()

    def check_downloader_update(self):
        logging.debug('mainwindow.py - check_downloader_update')
        self.actionUpdate.setEnabled(False)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("icons/cmems_data_downloader_icon.svg"),
                       QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.actionUpdate.setIcon(icon)
        self.actionUpdate.setToolTip('')
        if self.config_dict['OPTIONS'].getboolean('check_update'):
            self.check_downloader = CheckCMEMSDownloaderOnline()
            self.check_downloader.start()
            self.check_downloader.finished.connect(
                self.parse_downloader_update)
        else:
            logging.info(
                'mainwindow.py - check_downloader_update - from options, no update check'
            )

    def parse_downloader_update(self, val):
        logging.debug('mainwindow.py - parse_downloader_update - val ' +
                      str(val))
        if val == 'no new version':
            if self.config_dict['OPTIONS'].getboolean('check_database'):
                self.check_database = CheckDatabaseVersion()
                self.check_database.start()
                self.check_database.finished.connect(
                    self.parse_database_update)
            else:
                self.actionUpdate.setEnabled(False)
                icon = QtGui.QIcon()
                icon.addPixmap(
                    QtGui.QPixmap("icons/cmems_data_downloader_icon.svg"),
                    QtGui.QIcon.Normal, QtGui.QIcon.Off)
                self.actionUpdate.setIcon(icon)
                self.actionUpdate.setToolTip('No update available !')
        elif 'http' in val:
            self.actionUpdate.setEnabled(True)
            icon = QtGui.QIcon()
            icon.addPixmap(
                QtGui.QPixmap("icons/cmems_data_downloader_update_icon.svg"),
                QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionUpdate.setIcon(icon)
            if getattr(sys, 'frozen', False):
                self.actionUpdate.setToolTip(
                    'A new update is available for CMEMS Data Downloader ! Click here to install it automatically.'
                )
            else:
                self.actionUpdate.setToolTip(
                    'A new update is available for CMEMS Data Downloader ! Click here to download it.'
                )
            self.link_latest_version = val

    def download_and_install_update(self):
        logging.debug(
            'mainwindow.py - download_and_install_update - link_latest_version '
            + str(self.link_latest_version))
        if self.link_latest_version:
            if isinstance(self.link_latest_version, dict):
                self.downloadWindow = MyDatabaseUpdate(
                    self.link_latest_version)
                x1, y1, w1, h1 = self.geometry().getRect()
                _, _, w2, h2 = self.downloadWindow.geometry().getRect()
                x2 = x1 + w1 / 2 - w2 / 2
                y2 = y1 + h1 / 2 - h2 / 2
                self.downloadWindow.setGeometry(x2, y2, w2, h2)
                self.downloadWindow.setMinimumSize(
                    QtCore.QSize(500,
                                 self.downloadWindow.sizeHint().height()))
                self.downloadWindow.setMaximumSize(
                    QtCore.QSize(500,
                                 self.downloadWindow.sizeHint().height()))
                self.downloadWindow.exec_()
                if self.downloadWindow.done:
                    self.prepare_datasets_database()
                    self.actionUpdate.setEnabled(False)
                    icon = QtGui.QIcon()
                    icon.addPixmap(
                        QtGui.QPixmap("icons/cmems_data_downloader_icon.svg"),
                        QtGui.QIcon.Normal, QtGui.QIcon.Off)
                    self.actionUpdate.setIcon(icon)
                    self.actionUpdate.setToolTip('')
            else:
                frozen = False
                height = 250
                if getattr(sys, 'frozen', False):
                    frozen = True
                    height = 200
                self.updateWindow = MyWarningUpdate(frozen)
                x1, y1, w1, h1 = self.geometry().getRect()
                _, _, w2, h2 = self.updateWindow.geometry().getRect()
                x2 = x1 + w1 / 2 - w2 / 2
                y2 = y1 + h1 / 2 - h2 / 2
                self.updateWindow.setGeometry(x2, y2, w2, h2)
                self.updateWindow.setMinimumSize(QtCore.QSize(600, height))
                self.updateWindow.setMaximumSize(QtCore.QSize(600, height))
                self.updateWindow.exec_()
                try:
                    if self.updateWindow.buttonName == 'update_button':
                        if getattr(sys, 'frozen', False):
                            temp_folder = tempfile.gettempdir()
                        else:
                            temp_folder = os.path.expanduser(
                                "~") + "/Downloads/"
                        self.downloadWindow = MyUpdate(
                            self.link_latest_version, temp_folder)
                        x1, y1, w1, h1 = self.geometry().getRect()
                        _, _, w2, h2 = self.downloadWindow.geometry().getRect()
                        x2 = x1 + w1 / 2 - w2 / 2
                        y2 = y1 + h1 / 2 - h2 / 2
                        self.downloadWindow.setGeometry(x2, y2, w2, h2)
                        self.downloadWindow.setMinimumSize(
                            QtCore.QSize(
                                500,
                                self.downloadWindow.sizeHint().height()))
                        self.downloadWindow.setMaximumSize(
                            QtCore.QSize(
                                500,
                                self.downloadWindow.sizeHint().height()))
                        self.downloadWindow.exec_()
                        logging.debug(
                            'mainwindow.py - download_and_install_downloader_update - download finished'
                        )
                        if not self.downloadWindow.cancel:
                            if getattr(sys, 'frozen', False):
                                filename = self.link_latest_version[
                                    self.link_latest_version.rfind('/') + 1:]
                                if platform.system() == 'Windows':
                                    os.startfile(temp_folder + '\\' + filename)
                                    time.sleep(0.1)
                                    self.close()
                                elif platform.system() == 'Linux':
                                    shutil.copy('functions/unzip_update.py',
                                                temp_folder)
                                    install_folder = self.config_path + '/'
                                    command = 'python3 ' + temp_folder + '/unzip_update.py ' + temp_folder + '/' + filename + ' ' + install_folder
                                    os.system('x-terminal-emulator -e ' +
                                              command)
                                    time.sleep(0.1)
                                    self.close()
                            else:
                                time.sleep(0.1)
                                self.close()
                except AttributeError:
                    pass

    def parse_database_update(self, val):
        if val:
            self.actionUpdate.setEnabled(True)
            icon = QtGui.QIcon()
            icon.addPixmap(
                QtGui.QPixmap("icons/cmems_data_downloader_update_icon.svg"),
                QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionUpdate.setIcon(icon)
            self.actionUpdate.setToolTip(
                'New products are available for the product database. Click here to download them automatically.'
            )
            self.link_latest_version = val

    def get_file_name(self, action):
        logging.debug('mainwindow.py - get_file_name')
        file_dialog = QtWidgets.QFileDialog()
        file_dialog.setDefaultSuffix('xml')
        if action == 'save':
            file_name, _ = file_dialog.getSaveFileName(
                self, 'Save XML File', '', filter='XML Files (*.xml)')
        elif action == 'open':
            file_name, _ = file_dialog.getOpenFileName(
                self, 'Open XML File', '', filter='XML Files (*.xml)')
        logging.debug('mainwindow.py - get_file_name - file_name ' + file_name)
        return file_name

    def set_modified(self):
        logging.debug('mainwindow.py - set_modified')
        if not self.modified:
            self.modified = True
            self.make_window_title()

    def make_window_title(self):
        logging.debug('mainwindow.py - make_window_title - self.modified ' +
                      str(self.modified))
        title_string = 'CMEMS Data Downloader v' + _downloader_version
        modified_string = ''
        if self.modified:
            modified_string = ' - modified'
        title_string = title_string + modified_string
        self.setWindowTitle(title_string)

    def save_warning_window(self, string):
        logging.debug('mainwindow.py - save_warning_window')
        self.presaveWindow = MyWarning(string)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.presaveWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.presaveWindow.setGeometry(x2, y2, w2, h2)
        self.presaveWindow.setMinimumSize(
            QtCore.QSize(500,
                         self.presaveWindow.sizeHint().height()))
        self.presaveWindow.setMaximumSize(
            QtCore.QSize(500,
                         self.presaveWindow.sizeHint().height()))
        self.presaveWindow.exec_()
        return self.presaveWindow.buttonName

    def closeEvent(self, event):
        logging.debug('mainwindow.py - closeEvent - self.modified ' +
                      str(self.modified))
        if self.modified:
            result = self.save_warning_window("Close")
            if result == "save_button":
                self.save_document()
                logging.info('CMEMS Data Downloader ' + _downloader_version +
                             ' is closing ...')
                self.close()
            elif result == "nosave_button":
                logging.info('CMEMS Data Downloader ' + _downloader_version +
                             ' is closing ...')
                self.close()
            else:
                event.ignore()
        else:
            logging.info('CMEMS Data Downloader ' + _downloader_version +
                         ' is closing ...')
            self.close()

    def prepare_query(self):
        logging.debug('mainwindow.py - prepare_query')
        query = {}
        motu_url, service, product, var, folder, filename, output = None, None, None, None, None, None, None
        lon_min, lon_max, lat_min, lat_max, date_min, date_max, depth_min, depth_max = None, None, None, None, None, None, None, None

        ### service
        service = str(self.main_cb_5.currentText())

        ### product
        product = str(self.main_cb_6.currentText())

        ### url
        motu_url = self.product_database[
            self.main_cb_5.currentText()]['server_url']

        ### longitude and latitude
        if self.space_ln_north.isEnabled():
            if self.space_ln_north.text():
                lat_max = self.space_ln_north.text()
            if self.space_ln_south.text():
                lat_min = self.space_ln_south.text()
            if self.space_ln_west.text():
                lon_min = self.space_ln_west.text()
            if self.space_ln_east.text():
                lon_max = self.space_ln_east.text()

        ### depth
        if self.main_cb_7.isEnabled():
            if self.main_cb_7.currentText(
            ) != 'Make a choice...' and self.main_cb_8.currentText(
            ) != 'Make a choice...':
                depth_min, depth_max = self.main_cb_7.currentText(
                ), self.main_cb_8.currentText()

        ### date
        date_min = self.main_de_1.date().toString(QtCore.Qt.ISODate)
        date_max = self.main_de_2.date().toString(QtCore.Qt.ISODate)

        # filename and folder
        if self.main_ln_1.text():
            filename = str(self.main_ln_1.text())
        else:
            now = datetime.datetime.now()
            y = str(now.year)
            m = str(now.month)
            d = str(now.day)
            h = str(now.hour)
            mn = str(now.minute)
            s = str(now.second)
            filename = 'query_' + y + '-' + m + '-' + d + 'T' + h + '-' + mn + '-' + s
        folder = self.config_dict['CREDENTIALS'].get('folder')

        # variables
        var_tmp = []
        var_names = {v: k for k, v in self.variables_name.items()}
        checked_count = 0
        if self.variables_cb:
            for cb in self.variables_cb:
                if cb.isChecked():
                    checked_count += 1
                    var_tmp.append(var_names[cb.text()[:cb.text().find('(') -
                                                       1]])
        if var_tmp:
            if len(self.variables_cb) != checked_count:
                var = var_tmp

        # prepare dictionary
        parameter_list = [
            service, product, lon_min, lon_max, lat_min, lat_max, date_min,
            date_max, depth_min, depth_max, var, output
        ]
        name_list = [
            'service', 'product', 'x_lo', 'x_hi', 'y_lo', 'y_hi', 't_lo',
            't_hi', 'z_lo', 'z_hi', 'variable', 'output'
        ]
        for index, parameter in enumerate(parameter_list):
            if parameter != None:
                query[name_list[index]] = parameter
        query['scriptVersion'] = '1.5.00'
        query['mode'] = 'status'

        logging.debug('mainwindow.py - prepare_query - query ready: ' +
                      str(query))
        return query, motu_url, folder, filename
Exemplo n.º 2
0
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, path, config_dict, translations, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.config_dict = config_dict
        self.config_path = path
        self.text_translations = translations
        logging.info('mainwindow.py - UI initialization ...')
        self.setupUi(self)
        objectsInit(self)
        self.link_latest_version = None
        self.modified = False
        self.saved = False
        self.update_package_name = ''
        self.update_package_path = ''
        self.selected_list_widget = ''
        all_tool_buttons = []
        all_line_edits = []
        for i in range(self.tabWidget.count()):
            all_tool_buttons += getattr(self, 'tabWidgetPage' +
                                        str(i + 1)).findChildren(
                                            QtWidgets.QToolButton)
            all_line_edits += getattr(self, 'tabWidgetPage' +
                                      str(i + 1)).findChildren(Qt.QLineEdit)
        for widget in all_line_edits:
            widget.textChanged.connect(self.set_modified)
        for widget in all_tool_buttons:
            widget.clicked.connect(self.tool_button_clicked)
        self.home_ck_1.stateChanged.connect(
            self.check_prosim737_online_updates)
        self.home_ck_1.stateChanged.connect(self.set_modified)
        self.listWidget_2.itemClicked.connect(self.select_list_item)
        self.listWidget_2.itemSelectionChanged.connect(
            self.update_store_button_state)
        self.listWidget_2.itemSelectionChanged.connect(
            self.update_update_button_state)
        self.listWidget.itemClicked.connect(self.select_list_item)
        self.listWidget.itemSelectionChanged.connect(
            self.update_update_button_state)
        self.home_ln_1.textChanged.connect(self.check_prosim737_local_updates)
        self.home_ln_2.textChanged.connect(self.update_backup_buttons_state)
        self.home_ln_1.textChanged.connect(self.update_store_button_state)
        self.create_language_list()
        self.check_language_config()
        translate_elements(self, self.tabWidget,
                           self.config_dict['OPTIONS'].get('language'),
                           self.text_translations)
        self.download_prosim737_changelog()
        self.check_prosim737updater_update()
        self.make_window_title()
        try:
            read_updater_xml(self, 'prosim_udpater_options.xml')
            self.saved = True
        except FileNotFoundError:
            logging.exception(
                'mainwindow.py - xml file not found, no user options loaded')
        logging.info('mainwindow.py - UI initialized ...')
        logging.info('*****************************************')

    @QtCore.pyqtSlot()
    def on_actionSave_triggered(self):
        self.save_document()

    @QtCore.pyqtSlot()
    def on_actionOpen_triggered(self):
        self.open_document()

    @QtCore.pyqtSlot()
    def on_actionExit_triggered(self):
        self.close()

    @QtCore.pyqtSlot()
    def on_actionAbout_triggered(self):
        self.open_about()

    @QtCore.pyqtSlot()
    def on_actionChangelog_triggered(self):
        self.open_changelog()

    @QtCore.pyqtSlot()
    def on_actionOptions_triggered(self):
        self.open_options()

    @QtCore.pyqtSlot()
    def on_actionUpdate_triggered(self):
        self.download_and_install_prosim737updater_update()

    def save_document(self):
        logging.debug('mainwindow.py - save_document')
        xml_file = 'prosim_udpater_options.xml'
        create_updater_xml(self, xml_file)
        self.make_window_title()

    def open_document(self):
        logging.debug('mainwindow.py - open_document')
        if self.modified:
            result = self.make_onsave_msg_box(
                self.text_translations['iw_nosaveButton-text-open'][
                    self.config_dict['OPTIONS'].get('language')])
            if result == "iw_saveButton":
                self.save_document()
                self.open_file()
            elif result == "iw_nosaveButton":
                self.open_file()
        else:
            self.open_file()

    def open_about(self):
        logging.debug('mainwindow.py - open_about')
        self.aboutWindow = MyAbout(self.config_dict, self.text_translations)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.aboutWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.aboutWindow.setGeometry(x2, y2, w2, h2)
        self.aboutWindow.setMinimumSize(
            QtCore.QSize(480,
                         self.aboutWindow.sizeHint().height()))
        self.aboutWindow.setMaximumSize(
            QtCore.QSize(480,
                         self.aboutWindow.sizeHint().height()))
        self.aboutWindow.exec_()

    def open_changelog(self):
        logging.debug('mainwindow.py - open_changelog')
        self.logWindow = MyLog()
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.logWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.logWindow.setGeometry(x2, y2, w2, h2)
        self.logWindow.exec_()

    def open_options(self):
        logging.debug('mainwindow.py - open_options')
        language_before = self.config_dict.get('OPTIONS', 'language')
        self.optionWindow = MyOptions(self.config_dict, self.text_translations,
                                      self.language_list)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.optionWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.optionWindow.setGeometry(x2, y2, w2, h2)
        self.optionWindow.exec_()
        if not self.optionWindow.cancel:
            self.config_dict = self.optionWindow.config_dict
            language_after = self.config_dict.get('OPTIONS', 'language')
            with open(os.path.join(self.config_path, 'prosim_updater.ini'),
                      'w') as config_file:
                self.config_dict.write(config_file)
            logging.getLogger().setLevel(self.config_dict.get('LOG', 'level'))
            self.check_prosim737updater_update()
            if language_before != language_after:
                translate_elements(self, self.tabWidget, language_after,
                                   self.text_translations)
                translate_all_path_credential_elements(self)

    def closeEvent(self, event):
        logging.debug('mainwindow.py - closeEvent')
        if self.modified:
            result = self.make_onsave_msg_box(
                self.text_translations['iw_nosaveButton-text-close'][
                    self.config_dict['OPTIONS'].get('language')])
            if result == "iw_saveButton":
                self.save_document()
                event.accept()
            elif result == "iw_nosaveButton":
                event.accept()
            else:
                event.ignore()
        else:
            self.close()

    def make_window_title(self):
        logging.debug('mainwindow.py - make_window_title - self.modified ' +
                      str(self.modified) + ' ; self.saved ' + str(self.saved))
        title_string = 'Prosim737 Updater v' + _updater_version
        saved_string = ''
        modified_string = ''
        if not self.saved:
            saved_string = ' - unsaved'
        if self.modified:
            modified_string = ' - modified'
        title_string = title_string + saved_string + modified_string
        self.setWindowTitle(title_string)

    def set_modified(self):
        logging.debug('mainwindow.py - set_modified')
        if not self.modified:
            self.modified = True
            self.make_window_title()

    def get_directory(self):
        logging.debug('mainwindow.py - get_directory')
        file_dialog = QtWidgets.QFileDialog()
        out_dir = file_dialog.getExistingDirectory(self, "Select Directory")
        logging.debug('mainwindow.py - get_directory - ' + str(out_dir))
        return str(out_dir)

    def reset_all_fields(self):
        logging.debug('mainwindow.py - reset_all_fields - starting...')
        all_check_boxes = self.findChildren(QtWidgets.QCheckBox)
        for check_box in all_check_boxes:
            check_box.setCheckState(False)
        all_line_edits = self.findChildren(Qt.QLineEdit)
        for widget in all_line_edits:
            widget.clear()
        all_list_widgets = self.findChildren(Qt.QListWidget)
        for widget in all_list_widgets:
            widget.clear()
        for i in reversed(range(self.server_vl.count())):
            if i == 0:
                break
            del_path(self, i, 'server')
        for i in reversed(range(self.mcp_vl.count())):
            if i == 0:
                break
            del_path(self, i, 'mcp')
        for i in reversed(range(self.cdu_vl.count())):
            if i == 0:
                break
            del_path(self, i, 'cdu')
        for i in reversed(range(self.display_vl.count())):
            if i == 0:
                break
            del_path(self, i, 'display')
        for i in reversed(range(self.panel_vl.count())):
            if i == 0:
                break
            del_path(self, i, 'panel')
        for i in reversed(range(self.audio_vl.count())):
            if i == 0:
                break
            del_path(self, i, 'audio')
        for i in reversed(range(self.credentials_vl.count())):
            del_credentials(self, i)
        objectsInit(self)
        self.make_window_title()
        logging.debug('mainwindow.py - reset_all_fields - finished')

    def open_file(self):
        logging.debug('mainwindow.py - open_file')
        out_file_name, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Open XML File', '', 'XML Files (*.xml)')
        logging.debug('mainwindow.py - open_file - out_file_name ' +
                      str(out_file_name))
        if out_file_name:
            self.reset_all_fields()
            read_updater_xml(self, out_file_name)
            self.saved = True
            self.make_window_title()
            self.set_modified()

    def make_onsave_msg_box(self, string):
        logging.debug('mainwindow.py - make_onsave_msg_box - string ' + string)
        self.presaveWindow = MyWarning(string, self.config_dict,
                                       self.text_translations)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.presaveWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.presaveWindow.setGeometry(x2, y2, w2, h2)
        self.presaveWindow.setMinimumSize(
            QtCore.QSize(500,
                         self.presaveWindow.sizeHint().height()))
        self.presaveWindow.setMaximumSize(
            QtCore.QSize(500,
                         self.presaveWindow.sizeHint().height()))
        self.presaveWindow.exec_()
        try:
            return self.presaveWindow.buttonName
        except AttributeError:
            return None

    def tool_button_clicked(self):
        logging.debug(
            'mainwindow.py - tool_button_clicked - self.sender().objectName() '
            + self.sender().objectName())
        if "info" in self.sender().objectName():
            info_button(self)
        elif "create" in self.sender().objectName():
            create_backup(self)
        elif "restore" in self.sender().objectName():
            restore_backup(
                self,
                self.config_dict['OPTIONS'].getboolean('terminate_processes'),
                self.config_dict['OPTIONS'].getboolean('relaunch_processes'))
        elif "update" in self.sender().objectName():
            update_prosim(
                self,
                self.config_dict['OPTIONS'].getboolean('terminate_processes'),
                self.config_dict['OPTIONS'].getboolean('relaunch_processes'))
        elif "store" in self.sender().objectName():
            store_update(self)
        elif "changelog" in self.sender().objectName():
            display_changelog(self)
        elif "new" in self.sender().objectName():
            new_path(self)
        elif "cred_delete" in self.sender().objectName():
            del_credentials(self)
        elif "delete_bt" in self.sender().objectName():
            del_path(self)
        elif "credentials" in self.sender().objectName():
            new_credentials(self)
        elif 'none' in self.sender().objectName():
            pass
        else:
            if "_bt_" in self.sender().objectName():
                add_path(self)

    def check_prosim737_local_updates(self):
        logging.debug('mainwindow.py - check_prosim737_local_updates')
        self.listWidget.clear()
        self.listWidget.addItem('checking in progress...')
        item = self.listWidget.item(0)
        item.setFlags(QtCore.Qt.NoItemFlags)
        path = self.home_ln_1.text() + '\\'
        file_list = []
        if os.path.isdir(path):
            for name in os.listdir(path):
                if os.path.isfile(os.path.join(path, name)):
                    file_list.append(name)
        else:
            logging.debug(
                'mainwindow.py - check_prosim737_local_updates - no update ; path '
                + str(path))
        if file_list:
            file_names = []
            file_names_beta = []
            for filename in file_list:
                if 'ProSim737' in filename and '.zip' in filename:
                    if 'b' in filename:
                        file_names_beta.append(filename)
                    else:
                        file_names.append(filename)
            self.parse_prosim737_updates(
                ['local', file_names, file_names_beta])
        else:
            self.listWidget.clear()
            self.listWidget.addItem('no update found')
            item = self.listWidget.item(0)
            item.setFlags(QtCore.Qt.NoItemFlags)
            self.listWidget.setEnabled(False)
            self.home_lb_3.setEnabled(False)
        logging.debug(
            'mainwindow.py - check_prosim737_local_updates - len(file_list) ' +
            str(len(file_list)))

    def check_prosim737_online_updates(self):
        logging.debug('mainwindow.py - read_online_prosim_website')
        if self.home_ck_1.isChecked():
            self.listWidget_2.clear()
            self.listWidget_2.addItem('checking in progress...')
            item = self.listWidget_2.item(0)
            item.setFlags(QtCore.Qt.NoItemFlags)
            self.check_prosim737_online = CheckProsim737Online('online')
            self.check_prosim737_online.start()
            self.check_prosim737_online.finished.connect(
                self.parse_prosim737_updates)
        else:
            self.listWidget_2.clear()
            self.home_lb_4.setEnabled(False)
            self.listWidget_2.setEnabled(False)

    def parse_prosim737_updates(self, val):
        logging.debug('mainwindow.py - parse_prosim737_updates')
        if val[0] == 'online':
            widget = self.listWidget_2
            label = self.home_lb_4
        elif val[0] == 'local':
            widget = self.listWidget
            label = self.home_lb_3
        widget.clear()
        if val[1]:
            widget.setEnabled(True)
            label.setEnabled(True)
            widget.addItems(val[1])
        if val[1] and val[2]:
            widget.addItem('------------------------')
            item = widget.findItems('------------------------',
                                    Qt.Qt.MatchExactly)[0]
            item.setFlags(QtCore.Qt.NoItemFlags)
        elif not val[1] and not val[2]:
            widget.addItem('no update found')
            item = widget.item(0)
            item.setFlags(QtCore.Qt.NoItemFlags)
            label.setEnabled(False)
            widget.setEnabled(False)
        if val[2]:
            widget.setEnabled(True)
            label.setEnabled(True)
            widget.addItems(val[2])

    def select_list_item(self):
        logging.debug('mainwindow.py - select_list_item')
        if self.sender().objectName() == 'listWidget':
            if self.listWidget.currentItem():
                self.listWidget_2.clearSelection()
                self.update_package_name = self.listWidget.currentItem().text()
                self.update_package_path = self.home_ln_1.text() + '/'
                self.selected_list_widget = 'local'
        elif self.sender().objectName() == 'listWidget_2':
            if self.listWidget_2.currentItem():
                self.listWidget.clearSelection()
                self.update_package_name = self.listWidget_2.currentItem(
                ).text()
                if 'b' in self.update_package_name:
                    self.update_package_path = 'http://download.prosim-ar.com/ProSim737beta/'
                else:
                    self.update_package_path = 'http://prosim-ar.com/download/'
                self.selected_list_widget = 'online'
        logging.debug(
            'mainwindow.py - select_list_item - self.update_package_name ' +
            self.update_package_name + ' ; self.selected_list_widget ' +
            self.selected_list_widget)

    def update_backup_buttons_state(self):
        logging.debug('mainwindow.py - update_backup_buttons_state')
        if self.home_ln_2.text():
            if os.path.isdir(self.home_ln_2.text() + '\\'):
                self.home_create_backup.setEnabled(True)
                self.home_restore_backup.setEnabled(True)
            else:
                self.home_create_backup.setEnabled(False)
                self.home_restore_backup.setEnabled(False)
        else:
            self.home_create_backup.setEnabled(False)
            self.home_restore_backup.setEnabled(False)
        logging.debug(
            'mainwindow.py - update_backup_buttons_state - self.home_create_backup.isEnabled() '
            + str(self.home_create_backup.isEnabled()) +
            ' ; self.home_restore_backup.isEnabled() ' +
            str(self.home_restore_backup.isEnabled()))

    def update_store_button_state(self):
        logging.debug('mainwindow.py - update_store_button_state')
        try:
            if self.listWidget_2.currentItem().isSelected():
                if os.path.isdir(self.home_ln_1.text() + '\\'):
                    self.home_store.setEnabled(True)
                else:
                    self.home_store.setEnabled(False)
            else:
                self.home_store.setEnabled(False)
        except AttributeError:
            self.home_store.setEnabled(False)
        logging.debug(
            'mainwindow.py - update_store_button_state - self.home_store.isEnabled() '
            + str(self.home_store.isEnabled()))

    def update_update_button_state(self):
        logging.debug('mainwindow.py - update_update_button_state')
        left, right = False, False
        try:
            right = self.listWidget_2.currentItem().isSelected()
        except AttributeError:
            pass
        try:
            left = self.listWidget.currentItem().isSelected()
        except AttributeError:
            pass
        if left or right:
            self.home_update.setEnabled(True)
        else:
            self.home_update.setEnabled(False)
        logging.debug(
            'mainwindow.py - update_update_button_state - self.home_update.isEnabled() '
            + str(self.home_update.isEnabled()) + ' ; right ' + str(right) +
            ' ; left ' + str(left))

    def check_prosim737updater_update(self):
        logging.debug('mainwindow.py - check_prosim737updater_update')
        if self.config_dict['OPTIONS'].getboolean('check_update'):
            self.check_prosim737updater = CheckProsim737UpdaterOnline()
            self.check_prosim737updater.start()
            self.check_prosim737updater.finished.connect(
                self.parse_prosim737updater_update)
        else:
            self.actionUpdate.setEnabled(False)
            icon = QtGui.QIcon()
            icon.addPixmap(QtGui.QPixmap("icons/prosim_update_off_icon.svg"),
                           QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionUpdate.setIcon(icon)
            self.actionUpdate.setToolTip('')
            logging.info(
                'mainwindow.py - check_prosim737updater_update - from options, no update check'
            )

    def parse_prosim737updater_update(self, val):
        logging.debug('mainwindow.py - parse_prosim737updater_update - val ' +
                      str(val))
        if val == 'no new version':
            self.actionUpdate.setEnabled(False)
            icon = QtGui.QIcon()
            icon.addPixmap(QtGui.QPixmap("icons/prosim_update_off_icon.svg"),
                           QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionUpdate.setIcon(icon)
            self.text_translations['Path-missing'][
                self.config_dict['OPTIONS'].get('language')]
            self.actionUpdate.setToolTip('No update available !')
        elif 'http' in val:
            self.actionUpdate.setEnabled(True)
            icon = QtGui.QIcon()
            icon.addPixmap(QtGui.QPixmap("icons/prosim_update_on_icon.svg"),
                           QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionUpdate.setIcon(icon)
            self.actionUpdate.setToolTip(
                'A new update is available for Prosim737 Updater ! Click here to install it automatically.'
            )
            self.link_latest_version = val

    def download_and_install_prosim737updater_update(self):
        logging.debug(
            'mainwindow.py - download_and_install_prosim737updater_update - link_latest_version '
            + str(self.link_latest_version))
        if self.link_latest_version:
            temp_folder = tempfile.gettempdir()
            self.downloadWindow = MyUpdate(self.link_latest_version,
                                           temp_folder, self.config_dict,
                                           self.text_translations)
            x1, y1, w1, h1 = self.geometry().getRect()
            _, _, w2, h2 = self.downloadWindow.geometry().getRect()
            x2 = x1 + w1 / 2 - w2 / 2
            y2 = y1 + h1 / 2 - h2 / 2
            self.downloadWindow.setGeometry(x2, y2, w2, h2)
            self.downloadWindow.setMinimumSize(
                QtCore.QSize(500,
                             self.downloadWindow.sizeHint().height()))
            self.downloadWindow.setMaximumSize(
                QtCore.QSize(500,
                             self.downloadWindow.sizeHint().height()))
            self.downloadWindow.exec_()
            if not self.downloadWindow.cancel:
                os.startfile(temp_folder + '\\' +
                             self.link_latest_version[self.link_latest_version.
                                                      rfind('/') + 1:])
                time.sleep(0.1)
                self.close()

    def download_prosim737_changelog(self):
        logging.debug('mainwindow.py - download_prosim737_changelog')
        url_name = 'http://download.prosim-ar.com/ProSim737beta/changelog.txt'
        changelog_path = 'documentation\prosim_changelog.txt'
        self.thread = DownloadFile(url_name, self.config_dict,
                                   self.text_translations, changelog_path)
        self.thread.download_done.connect(self.activate_changelog_button)
        self.thread.start()

    def activate_changelog_button(self):
        logging.debug('mainwindow.py - activate_changelog_button')
        self.home_changelog.setEnabled(True)

    def create_language_list(self):
        logging.debug('mainwindow.py - create_language_list')
        value = next(iter(self.text_translations.values()))
        for key, _ in value.items():
            self.language_list[key] = key.title()

    def check_language_config(self):
        logging.debug('mainwindow.py - check_language_config')
        language = self.config_dict['OPTIONS'].get('language')
        try:
            self.language_list[language]
        except KeyError:
            logging.exception(
                'mainwindow.py - check_language_config - language ' +
                str(language) + ' not found.')
            self.config_dict.set('OPTIONS', 'language', 'english')
            infoText = self.text_translations['Language-not-found'][
                self.config_dict['OPTIONS'].get('language')] % language
            self.infoWindow = MyInfo(infoText, self.config_dict,
                                     self.text_translations)
            x1, y1, w1, h1 = self.geometry().getRect()
            _, _, w2, h2 = self.infoWindow.geometry().getRect()
            x2 = x1 + w1 / 2 - w2 / 2
            y2 = y1 + h1 / 2 - h2 / 2
            self.infoWindow.setGeometry(x2, y2, w2, h2)
            self.infoWindow.setMinimumSize(
                QtCore.QSize(450,
                             self.infoWindow.sizeHint().height()))
            self.infoWindow.setMaximumSize(
                QtCore.QSize(450,
                             self.infoWindow.sizeHint().height()))
            self.infoWindow.exec_()
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, path, config_dict, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.config_dict = config_dict
        self.config_path = path
        logging.info('mainwindow.py - UI initialization ...')
        self.setupUi(self)
        self.backup.clicked.connect(self.backup_configuration_file)
        self.check_downloader_update()
        self.check_file_folder()
        self.populate_folder_target()
        logging.info('mainwindow.py - UI initialized ...')
        logging.info('*****************************************')

    @QtCore.pyqtSlot()
    def on_actionExit_triggered(self):
        self.close()

    @QtCore.pyqtSlot()
    def on_actionAbout_triggered(self):
        self.open_about()

    @QtCore.pyqtSlot()
    def on_actionOptions_triggered(self):
        self.open_options()

    @QtCore.pyqtSlot()
    def on_actionUpdate_triggered(self):
        self.download_and_install_update()

    def populate_folder_target(self):
        logging.debug('mainwindow.py - populate_folder_target')
        self.label_3.setText(self.config_dict.get('CREDENTIALS', 'folder'))
        self.label_4.setText(self.config_dict.get('CREDENTIALS', 'target'))

    def backup_configuration_file(self):
        logging.debug('mainwindow.py - backup_configuration_file')
        target = self.config_dict.get('CREDENTIALS', 'target')
        if target:
            success = False
            failure_reason = ''
            nas_md5 = ''
            password = self.config_dict.get('CREDENTIALS', 'password')
            username = self.config_dict.get('CREDENTIALS', 'username')
            if not password or not username:
                logging.debug(
                    'mainwindow.py - backup_configuration_file - username/password missing'
                )
                self.credentialsyWindow = MyCredentials(username, password)
                x1, y1, w1, h1 = self.geometry().getRect()
                _, _, w2, h2 = self.credentialsyWindow.geometry().getRect()
                x2 = x1 + w1 / 2 - w2 / 2
                y2 = y1 + h1 / 2 - h2 / 2
                self.credentialsyWindow.setGeometry(x2, y2, w2, h2)
                self.credentialsyWindow.exec_()
                if self.credentialsyWindow.username and self.credentialsyWindow.password:
                    username = self.credentialsyWindow.username
                    password = self.credentialsyWindow.password
            if username and password:
                folder = self.config_dict.get('CREDENTIALS', 'folder')
                port = self.config_dict.get('CREDENTIALS', 'target_port')
                y, m, d = str(datetime.datetime.now().year), str(
                    datetime.datetime.now().month), str(
                        datetime.datetime.now().day)
                h, mm, s = str(datetime.datetime.now().hour), str(
                    datetime.datetime.now().minute), str(
                        datetime.datetime.now().second)
                if len(m) == 1:
                    m = '0' + m
                if len(d) == 1:
                    d = '0' + d
                if len(h) == 1:
                    h = '0' + h
                if len(mm) == 1:
                    mm = '0' + mm
                if len(s) == 1:
                    s = '0' + s
                filename = 'configuration_' + target + '_' + y + m + d + 'T' + h + mm + s + '.xml'
                try:
                    try:
                        logging.debug(
                            'mainwindow.py - backup_configuration_file - ssh connection...'
                        )
                        ssh_client = paramiko.SSHClient()
                        ssh_client.set_missing_host_key_policy(
                            paramiko.AutoAddPolicy())
                        ssh_client.connect(hostname=target,
                                           username=username,
                                           password=password)
                        logging.debug(
                            'mainwindow.py - backup_configuration_file - ssh connection established'
                        )
                        stdin, stdout, stderr = ssh_client.exec_command(
                            'md5 /conf/config.xml')
                        tmp = str(stdout.readlines())
                        if tmp != '[]':
                            index1 = tmp.find('=')
                            nas_md5 = tmp[index1 + 2:-4]
                            logging.debug(
                                'mainwindow.py - backup_configuration_file - MD5 checksum generated'
                            )
                        else:
                            failure_reason = str(stderr.readlines())[2:-4]
                            logging.debug(
                                'mainwindow.py - backup_configuration_file - MD5 checksum failed'
                            )
                        if platform.system() == 'Windows':
                            full_path = folder + '\\' + filename
                            separator = '\\'
                        elif platform.system() == 'Linux':
                            full_path = folder + '/' + filename
                            separator = '/'
                        logging.debug(
                            'mainwindow.py - backup_configuration_file - opening sftp'
                        )
                        ftp_client = ssh_client.open_sftp()
                        logging.debug(
                            'mainwindow.py - backup_configuration_file - sftp opened, requesting file'
                        )
                        ftp_client.get('/conf/config.xml', full_path)
                        logging.debug(
                            'mainwindow.py - backup_configuration_file - file downloaded'
                        )
                        ftp_client.close()
                        ssh_client.close()
                        success = True
                        local_md5 = hashlib.md5(open(full_path,
                                                     'rb').read()).hexdigest()
                    except paramiko.ssh_exception.AuthenticationException:
                        failure_reason = 'Authentication seems to have failed. Please check the username and/or the password for authentication.'
                        logging.exception(
                            'mainwindow.py - backup_configuration_file - AuthenticationException - authentication seems to have failed, check'
                            + ' username and/or password.')
                    except FileNotFoundError:
                        failure_reason = 'The configuration file has not been found. Please check the path and/or the name of the file.'
                        logging.exception(
                            'mainwindow.py - backup_configuration_file - FileNotFoundError - configuration file not found, check the path'
                            + ' and/or the name of the file.')
                    except PermissionError:
                        failure_reason = 'The account linked to the username and password doesn\'t seem to have sufficient rights to access NAS by SSH.'
                        logging.exception(
                            'mainwindow.py - backup_configuration_file - PermissionError - account with insufficient rights.'
                        )
                except Exception:
                    failure_reason = 'Download of the configuration file failed for an unknown reason. Please check the log file for details.'
                    logging.exception(
                        'mainwindow.py - backup_configuration_file - Exception - an exception has occured.'
                    )
                if not success:
                    text = failure_reason
                else:
                    if nas_md5 == local_md5 and nas_md5 != '':
                        text = (
                            'The configuration file has been well backed up in the folder:<br>&nbsp;&nbsp;&nbsp;&nbsp;<b>'
                            + folder + '</b><br>' +
                            'with the file name:<br>&nbsp;&nbsp;&nbsp;&nbsp;<b>'
                            + filename + '</b>.')
                    else:
                        if nas_md5 == '' and local_md5 == '':
                            text = (
                                'The configuration file has been downloaded in the folder:<br>&nbsp;&nbsp;&nbsp;&nbsp;<b>'
                                + folder + '</b><br>' +
                                'with the file name:<br>&nbsp;&nbsp;&nbsp;&nbsp;<b>'
                                + filename +
                                '</b>.<br><br><span style=\" font-weight:600' +
                                '; color:#c80000;\">The MD5 checksums of the original and downloaded files couldn\'t be checked. Please be car'
                                + 'efull with this configuration file.</span>')
                        else:
                            if nas_md5 == '':
                                text = (
                                    'The configuration file has been downloaded in the folder:<br>&nbsp;&nbsp;&nbsp;&nbsp;<b>'
                                    + folder + '</b><br>' +
                                    'with the file name:<br>&nbsp;&nbsp;&nbsp;&nbsp;<b>'
                                    + filename +
                                    '</b>.<br><br><span style=\" font-weight:600'
                                    +
                                    '; color:#c80000;\">The MD5 checksum of the original file couldn\'t be checked. Please be carefull with this c'
                                    + 'onfiguration file.</span>')
                            elif local_md5 == '':
                                text = (
                                    'The configuration file has been downloaded in the folder:<br>&nbsp;&nbsp;&nbsp;&nbsp;<b>'
                                    + folder + '</b><br>' +
                                    'with the file name:<br>&nbsp;&nbsp;&nbsp;&nbsp;<b>'
                                    + filename +
                                    '</b>.<br><br><span style=\" font-weight:600'
                                    +
                                    '; color:#c80000;\">The MD5 checksum of the downloaded file couldn\'t be checked. Please be carefull with this'
                                    + ' configuration file.</span>')
                            else:
                                text = (
                                    'The configuration file has been downloaded in the folder:<br>&nbsp;&nbsp;&nbsp;&nbsp;<b>'
                                    + folder + '</b><br>' +
                                    'with the file name:<br>&nbsp;&nbsp;&nbsp;&nbsp;<b>'
                                    + filename +
                                    '</b>.<br><br><span style=\" font-weight:600; c'
                                    +
                                    'olor:#c80000;\">The MD5 checksums of the original and downloaded files don\'t match. Please be carefull with thi'
                                    +
                                    's configuration file, it can be corrupted.</span>'
                                )
                self.infoWindow = MyInfo(text)
                _, _, w, h = QtWidgets.QDesktopWidget().screenGeometry(
                    -1).getRect()
                _, _, w2, h2 = self.infoWindow.geometry().getRect()
                self.infoWindow.setGeometry(
                    w / 2 - w2 / 2, h / 2 - h2 / 2, 600,
                    self.infoWindow.sizeHint().height())
                self.infoWindow.setMinimumSize(
                    QtCore.QSize(600,
                                 self.infoWindow.sizeHint().height()))
                self.infoWindow.setMaximumSize(
                    QtCore.QSize(600,
                                 self.infoWindow.sizeHint().height()))
                self.infoWindow.exec_()

    def open_about(self):
        logging.debug('mainwindow.py - open_about')
        text = (
            "The following software (v" + _backup_version +
            ") was developed by Olivier Henry, using Eclipse " +
            _eclipse_version + ", Python " + _py_version + " and PyQt " +
            _qt_version +
            ". It was designed to make a backup of the configuration file of XigmaNAS"
            + " using Python and scp commands.")
        self.aboutWindow = MyAbout(text)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.aboutWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.aboutWindow.setGeometry(x2, y2, w2, h2)
        self.aboutWindow.setMinimumSize(QtCore.QSize(850, 450))
        self.aboutWindow.setMaximumSize(QtCore.QSize(850, 450))
        self.aboutWindow.exec_()

    def open_options(self):
        logging.debug('mainwindow.py - open_options')
        self.optionWindow = MyOptions(self.config_dict)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.optionWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.optionWindow.setGeometry(x2, y2, w2, h2)
        self.optionWindow.exec_()
        if not self.optionWindow.cancel:
            self.config_dict = self.optionWindow.config_dict
            with open(os.path.join(self.config_path, 'xigmanas_backup.ini'),
                      'w') as config_file:
                self.config_dict.write(config_file)
            logging.getLogger().setLevel(self.config_dict.get('LOG', 'level'))
            self.check_downloader_update()
            self.populate_folder_target()

    def check_file_folder(self):
        logging.debug('mainwindow.py - check_file_folder')
        if not os.path.isdir(self.config_dict.get(
                'CREDENTIALS', 'folder')) and self.config_dict.get(
                    'CREDENTIALS', 'folder'):
            logging.exception(
                'mainwindow.py - check_file_folder - exception occured when the software checked the existence of the backup folder. '
                +
                'Please check that the folder exists. The folder option in the config file is going to be modified to the defa'
                + 'ult folder.')
            self.config_dict.set('CREDENTIALS', 'folder', '')
            with open(os.path.join(self.config_path, 'xigmanas_backup.ini'),
                      'w') as config_file:
                self.config_dict.write(config_file)
            text = (
                'The software has detected that the folder where XigmaNAS config files are saved doesn\'t exist anymore. It has been reseted in the config file'
                +
                ' to the default folder. Please check your options and set a new folder for backup.'
            )
            self.infoWindow = MyInfo(text)
            _, _, w, h = QtWidgets.QDesktopWidget().screenGeometry(
                -1).getRect()
            _, _, w2, h2 = self.infoWindow.geometry().getRect()
            self.infoWindow.setGeometry(w / 2 - w2 / 2, h / 2 - h2 / 2, 450,
                                        self.infoWindow.sizeHint().height())
            self.infoWindow.setMinimumSize(
                QtCore.QSize(450,
                             self.infoWindow.sizeHint().height()))
            self.infoWindow.setMaximumSize(
                QtCore.QSize(450,
                             self.infoWindow.sizeHint().height()))
            self.infoWindow.exec_()

    def check_downloader_update(self):
        logging.debug('mainwindow.py - check_downloader_update')
        self.actionUpdate.setEnabled(False)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("icons/xigmanas_conf_backup_icon.svg"),
                       QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.actionUpdate.setIcon(icon)
        self.actionUpdate.setToolTip('')
        if self.config_dict['OPTIONS'].getboolean('check_update'):
            self.check_downloader = CheckXNASBackupOnline()
            self.check_downloader.start()
            self.check_downloader.finished.connect(
                self.parse_downloader_update)
        else:
            logging.info(
                'mainwindow.py - check_downloader_update - from options, no update check'
            )

    def parse_downloader_update(self, val):
        logging.debug('mainwindow.py - parse_downloader_update - val ' +
                      str(val))
        if val == 'no new version':
            self.actionUpdate.setEnabled(False)
            icon = QtGui.QIcon()
            icon.addPixmap(
                QtGui.QPixmap("icons/xigmanas_conf_backup_icon.svg"),
                QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionUpdate.setIcon(icon)
            self.actionUpdate.setToolTip('No update available !')
        elif 'http' in val:
            self.actionUpdate.setEnabled(True)
            icon = QtGui.QIcon()
            icon.addPixmap(
                QtGui.QPixmap(
                    "icons/xigmanas_conf_backup_update_available.svg"),
                QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionUpdate.setIcon(icon)
            if getattr(sys, 'frozen', False):
                self.actionUpdate.setToolTip(
                    'A new update is available for XigmaNAS Conf Backup ! Click here to install it automatically.'
                )
            else:
                self.actionUpdate.setToolTip(
                    'A new update is available for XigmaNAS Conf Backup ! Click here to download it.'
                )
            self.link_latest_version = val

    def download_and_install_update(self):
        logging.debug(
            'mainwindow.py - download_and_install_update - link_latest_version '
            + str(self.link_latest_version))
        if self.link_latest_version:
            frozen = False
            height = 250
            if getattr(sys, 'frozen', False):
                frozen = True
                height = 200
            self.updateWindow = MyWarningUpdate(frozen)
            x1, y1, w1, h1 = self.geometry().getRect()
            _, _, w2, h2 = self.updateWindow.geometry().getRect()
            x2 = x1 + w1 / 2 - w2 / 2
            y2 = y1 + h1 / 2 - h2 / 2
            self.updateWindow.setGeometry(x2, y2, w2, h2)
            self.updateWindow.setMinimumSize(QtCore.QSize(600, height))
            self.updateWindow.setMaximumSize(QtCore.QSize(600, height))
            self.updateWindow.exec_()
            try:
                if self.updateWindow.buttonName == 'update_button':
                    if getattr(sys, 'frozen', False):
                        temp_folder = tempfile.gettempdir()
                    else:
                        temp_folder = os.path.expanduser("~") + "/Downloads/"
                    self.downloadWindow = MyUpdate(self.link_latest_version,
                                                   temp_folder)
                    x1, y1, w1, h1 = self.geometry().getRect()
                    _, _, w2, h2 = self.downloadWindow.geometry().getRect()
                    x2 = x1 + w1 / 2 - w2 / 2
                    y2 = y1 + h1 / 2 - h2 / 2
                    self.downloadWindow.setGeometry(x2, y2, w2, h2)
                    self.downloadWindow.setMinimumSize(
                        QtCore.QSize(500,
                                     self.downloadWindow.sizeHint().height()))
                    self.downloadWindow.setMaximumSize(
                        QtCore.QSize(500,
                                     self.downloadWindow.sizeHint().height()))
                    self.downloadWindow.exec_()
                    logging.debug(
                        'mainwindow.py - download_and_install_downloader_update - download finished'
                    )
                    if not self.downloadWindow.cancel:
                        if getattr(sys, 'frozen', False):
                            filename = self.link_latest_version[
                                self.link_latest_version.rfind('/') + 1:]
                            if platform.system() == 'Windows':
                                os.startfile(temp_folder + '\\' + filename)
                                time.sleep(0.1)
                                self.close()
                            elif platform.system() == 'Linux':
                                shutil.copy('functions/unzip_update.py',
                                            temp_folder)
                                install_folder = self.config_path + '/'
                                command = 'python3 ' + temp_folder + '/unzip_update.py ' + temp_folder + '/' + filename + ' ' + install_folder
                                os.system('x-terminal-emulator -e ' + command)
                                time.sleep(0.1)
                                self.close()
                        else:
                            time.sleep(0.1)
                            self.close()
            except AttributeError:
                pass

    def closeEvent(self, event):
        logging.debug('mainwindow.py - closeEvent')
        logging.info('XigmaNAS Conf Backup ' + _backup_version +
                     ' is closing ...')
        self.close()
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, path, config_dict, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.config_dict = config_dict
        self.config_path = path
        logging.info('mainwindow.py - UI initialization ...')
        self.setupUi(self)
        object_init(self)
        info_button_text(self)
        dataset_data_information(self)
        hide_area_map(self)
        self.area_rb_1.setChecked(True)
        itemDelegate = QtWidgets.QStyledItemDelegate()
        self.area_cb_1.setItemDelegate(itemDelegate)
        self.area_cb_2.setItemDelegate(itemDelegate)
        self.period_cb_1.setItemDelegate(itemDelegate)
        for widget in self.dataset_gb_1.buttons():
            widget.toggled.connect(lambda: populate_fields(self))
            widget.toggled.connect(lambda: clean_stylesheet_dataset(self))
        for widget in self.time_bg_1.buttons():
            widget.toggled.connect(lambda: clean_stylesheet_time(self))
            widget.toggled.connect(self.set_modified)
        for widget in self.step_bg_1.buttons():
            widget.toggled.connect(lambda: clean_stylesheet_step(self))
            widget.toggled.connect(self.set_modified)
        for widget in self.period_bg_1.buttons():
            widget.toggled.connect(lambda: activate_period_elements(self))
            widget.toggled.connect(lambda: clean_stylesheet_period(self))
            widget.toggled.connect(self.set_modified)
        for widget in self.file_bg_1.buttons():
            widget.toggled.connect(self.set_modified)
        for widget in self.info_buttons_list:
            widget.clicked.connect(lambda: info_button(self))
        self.area_cb_1.currentIndexChanged.connect(
            lambda: set_visibility_area_map(self))
        self.area_cb_1.currentIndexChanged.connect(self.set_modified)
        self.area_cb_2.currentIndexChanged.connect(self.set_modified)
        self.area_ln_5.textChanged.connect(self.set_modified)
        self.time_de_1.dateChanged.connect(self.set_modified)
        self.time_de_2.dateChanged.connect(self.set_modified)
        self.period_cb_1.currentIndexChanged.connect(
            lambda: populate_period_elements(self))
        self.period_cb_1.currentIndexChanged.connect(self.set_modified)
        self.download_bt_1.clicked.connect(self.check_tabs_for_download)
        self.check_downloader_update()
        self.make_window_title()
        logging.info('mainwindow.py - UI initialized ...')
        logging.info('*****************************************')
        self.api_information()
        self.check_file_folder()

    @QtCore.pyqtSlot()
    def on_actionExit_triggered(self):
        self.close()

    @QtCore.pyqtSlot()
    def on_actionSave_triggered(self):
        self.save_document()

    @QtCore.pyqtSlot()
    def on_actionOpen_triggered(self):
        self.open_document()

    @QtCore.pyqtSlot()
    def on_actionExpert_triggered(self):
        self.open_expert_mode()

    @QtCore.pyqtSlot()
    def on_actionAbout_triggered(self):
        self.open_about()

    @QtCore.pyqtSlot()
    def on_actionOptions_triggered(self):
        self.open_options()

    @QtCore.pyqtSlot()
    def on_actionUpdate_triggered(self):
        self.download_and_install_downloader_update()

    def api_information(self):
        logging.debug('mainwindow.py - api_information')
        if self.config_dict['OPTIONS'].getboolean('display_api_info'):
            self.apiWindow = MyApi()
            _, _, w, h = QtWidgets.QDesktopWidget().screenGeometry(
                -1).getRect()
            _, _, w2, h2 = self.apiWindow.geometry().getRect()
            self.apiWindow.setGeometry(w / 2 - w2 / 2, h / 2 - h2 / 2, w2, h2)
            self.apiWindow.setMinimumSize(QtCore.QSize(700, 500))
            self.apiWindow.setMaximumSize(QtCore.QSize(700, 500))
            self.apiWindow.exec_()
            if self.apiWindow.checkbox.isChecked():
                if not self.config_dict['OPTIONS'].getboolean(
                        'display_api_info'):
                    self.config_dict.set('OPTIONS', 'display_api_info', 'True')
                    with open(
                            os.path.join(self.config_path,
                                         'ecmwf_downloader.ini'),
                            'w') as config_file:
                        self.config_dict.write(config_file)
            else:
                if self.config_dict['OPTIONS'].getboolean('display_api_info'):
                    self.config_dict.set('OPTIONS', 'display_api_info',
                                         'False')
                    with open(
                            os.path.join(self.config_path,
                                         'ecmwf_downloader.ini'),
                            'w') as config_file:
                        self.config_dict.write(config_file)

    def check_file_folder(self):
        logging.debug('mainwindow.py - check_file_folder')
        if not os.path.isdir(self.config_dict.get(
                'CREDENTIALS', 'folder')) and self.config_dict.get(
                    'CREDENTIALS', 'folder'):
            logging.exception(
                'mainwindow.py - check_file_folder - exception occured when EDD checked the existence of the ECMWF file folder. '
                +
                'Please check that the folder exists. The folder option in the config file is going to be modified to the defa'
                + 'ult folder.')
            self.config_dict.set('CREDENTIALS', 'folder', '')
            with open(os.path.join(self.config_path, 'ecmwf_downloader.ini'),
                      'w') as config_file:
                self.config_dict.write(config_file)
            text = (
                'EDD has detected that the folder where ECMWF files are saved doesn\'t exist anymore. It has been reseted in the config file'
                +
                ' to the default folder. Please check your options and set a new folder for ECMWF files.'
            )
            self.infoWindow = MyInfo(text)
            _, _, w, h = QtWidgets.QDesktopWidget().screenGeometry(
                -1).getRect()
            _, _, w2, h2 = self.infoWindow.geometry().getRect()
            self.infoWindow.setGeometry(w / 2 - w2 / 2, h / 2 - h2 / 2, 450,
                                        self.infoWindow.sizeHint().height())
            self.infoWindow.setMinimumSize(
                QtCore.QSize(450,
                             self.infoWindow.sizeHint().height()))
            self.infoWindow.setMaximumSize(
                QtCore.QSize(450,
                             self.infoWindow.sizeHint().height()))
            self.infoWindow.exec_()

    def open_about(self):
        logging.debug('mainwindow.py - open_about')
        text = (
            "The ECMWF Data Downloader v" + _downloader_version +
            " was developed by Olivier Henry" + ", using Eclipse " +
            _eclipse_version + ", Python " + _py_version + " and PyQt " +
            _qt_version +
            ". It was designed to help researchers to download data from ECMWF dif"
            + "ferent projects by using the official ECMWF web API.")
        self.aboutWindow = MyAbout(text)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.aboutWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.aboutWindow.setGeometry(x2, y2, w2, h2)
        self.aboutWindow.setMinimumSize(QtCore.QSize(850, 450))
        self.aboutWindow.setMaximumSize(QtCore.QSize(850, 450))
        self.aboutWindow.exec_()

    def open_options(self):
        logging.debug('mainwindow.py - open_options')
        self.optionWindow = MyOptions(self.config_dict,
                                      self.info_button_text_dict)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.optionWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.optionWindow.setGeometry(x2, y2, w2, h2)
        self.optionWindow.exec_()
        if not self.optionWindow.cancel:
            self.config_dict = self.optionWindow.config_dict
            with open(os.path.join(self.config_path, 'ecmwf_downloader.ini'),
                      'w') as config_file:
                self.config_dict.write(config_file)
            logging.getLogger().setLevel(self.config_dict.get('LOG', 'level'))
            self.check_downloader_update()

    def save_document(self):
        logging.debug('mainwindow.py - save_document')
        filename = self.get_file_name('save')
        if filename:
            save_xml_query(self, filename)

    def open_document(self):
        logging.debug('mainwindow.py - open_document')
        if self.modified:
            result = self.save_warning_window("Open")
            if result == "save_button":
                self.save_document()
                filename = self.get_file_name('open')
                if filename:
                    open_xml_query(self, filename)
            elif result == "nosave_button":
                filename = self.get_file_name('open')
                if filename:
                    open_xml_query(self, filename)
        else:
            filename = self.get_file_name('open')
            if filename:
                open_xml_query(self, filename)

    def open_expert_mode(self):
        logging.debug('mainwindow.py - open_expert_mode')
        self.expertWindow = MyExpert(self.info_button_text_dict)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.expertWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.expertWindow.setGeometry(x2, y2, w2, h2)
        self.expertWindow.exec_()
        query = self.expertWindow.query
        if query:
            self.download_ecmwf_data(query)

    def check_tabs_for_download(self):
        logging.debug('mainwindow.py - check_tabs_for_download')
        checking_passed = tabs_checking(self)
        if not checking_passed:
            self.selectionWindow = MySelect()
            x1, y1, w1, h1 = self.geometry().getRect()
            _, _, w2, h2 = self.selectionWindow.geometry().getRect()
            self.selectionWindow.setGeometry(x1 + w1 / 2 - w2 / 2,
                                             y1 + h1 / 2 - h2 / 2, w2, h2)
            self.selectionWindow.setMinimumSize(
                QtCore.QSize(500,
                             self.selectionWindow.sizeHint().height()))
            self.selectionWindow.setMaximumSize(
                QtCore.QSize(500,
                             self.selectionWindow.sizeHint().height()))
            self.selectionWindow.exec_()
        else:
            self.download_ecmwf_data()

    def download_ecmwf_data(self, query=None):
        logging.debug('mainwindow.py - download_ecmwf_data')
        if query == None:
            query = prepare_query(self)
        logging.debug('mainwindow.py - download_ecmwf_data - query ' +
                      str(query))
        self.queryWindow = MyQuery(query, self.config_dict)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.queryWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.queryWindow.setGeometry(x2, y2, w2, h2)
        self.queryWindow.exec_()
        try:
            download_time = self.queryWindow.download_time
            file_path = self.queryWindow.file_path
            average_speed = self.queryWindow.average_speed
            self.successWindow = MySuccess(download_time, file_path,
                                           average_speed)
            x1, y1, w1, h1 = self.geometry().getRect()
            _, _, w2, h2 = self.successWindow.geometry().getRect()
            x2 = x1 + w1 / 2 - w2 / 2
            y2 = y1 + h1 / 2 - h2 / 2
            self.successWindow.setGeometry(x2, y2, w2, h2)
            self.successWindow.exec_()
        except AttributeError:
            pass

    def closeEvent(self, event):
        logging.debug('mainwindow.py - closeEvent - self.modified ' +
                      str(self.modified))
        if self.modified:
            result = self.save_warning_window("Close")
            if result == "save_button":
                self.save_document()
                logging.info('ECMWF Data Downloader ' + _downloader_version +
                             ' is closing ...')
                self.close()
            elif result == "nosave_button":
                logging.info('ECMWF Data Downloader ' + _downloader_version +
                             ' is closing ...')
                self.close()
            else:
                event.ignore()
        else:
            logging.info('ECMWF Data Downloader ' + _downloader_version +
                         ' is closing ...')
            self.close()

    def make_window_title(self):
        logging.debug('mainwindow.py - make_window_title - self.modified ' +
                      str(self.modified))
        title_string = 'ECMWF Data Downloader v' + _downloader_version
        modified_string = ''
        if self.modified:
            modified_string = ' - modified'
        title_string = title_string + modified_string
        self.setWindowTitle(title_string)

    def set_modified(self):
        logging.debug('mainwindow.py - set_modified')
        if not self.modified:
            self.modified = True
            self.make_window_title()

    def check_downloader_update(self):
        logging.debug('mainwindow.py - check_downloader_update')
        if self.config_dict['OPTIONS'].getboolean('check_update'):
            self.check_downloader = CheckECMWFDownloaderOnline()
            self.check_downloader.start()
            self.check_downloader.finished.connect(
                self.parse_downloader_update)
        else:
            self.actionUpdate.setEnabled(False)
            icon = QtGui.QIcon()
            icon.addPixmap(
                QtGui.QPixmap("icons/downloader_update_off_icon.svg"),
                QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionUpdate.setIcon(icon)
            self.actionUpdate.setToolTip('')
            logging.info(
                'mainwindow.py - check_downloader_update - from options, no update check'
            )

    def parse_downloader_update(self, val):
        logging.debug('mainwindow.py - parse_downloader_update - val ' +
                      str(val))
        if val == 'no new version':
            self.actionUpdate.setEnabled(False)
            icon = QtGui.QIcon()
            icon.addPixmap(
                QtGui.QPixmap("icons/downloader_update_off_icon.svg"),
                QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionUpdate.setIcon(icon)
            self.actionUpdate.setToolTip('No update available !')
        elif 'http' in val:
            self.actionUpdate.setEnabled(True)
            icon = QtGui.QIcon()
            icon.addPixmap(
                QtGui.QPixmap("icons/downloader_update_on_icon.svg"),
                QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionUpdate.setIcon(icon)
            if getattr(sys, 'frozen', False):
                self.actionUpdate.setToolTip(
                    'A new update is available for ECMWF Data Downloader ! Click here to install it automatically.'
                )
            else:
                self.actionUpdate.setToolTip(
                    'A new update is available for ECMWF Data Downloader ! Click here to download it.'
                )
            self.link_latest_version = val

    def download_and_install_downloader_update(self):
        logging.debug(
            'mainwindow.py - download_and_install_downloader_update - link_latest_version '
            + str(self.link_latest_version))
        if self.link_latest_version:
            frozen = False
            height = 250
            if getattr(sys, 'frozen', False):
                frozen = True
                height = 200
            self.updateWindow = MyWarningUpdate(frozen)
            x1, y1, w1, h1 = self.geometry().getRect()
            _, _, w2, h2 = self.updateWindow.geometry().getRect()
            x2 = x1 + w1 / 2 - w2 / 2
            y2 = y1 + h1 / 2 - h2 / 2
            self.updateWindow.setGeometry(x2, y2, w2, h2)
            self.updateWindow.setMinimumSize(QtCore.QSize(600, height))
            self.updateWindow.setMaximumSize(QtCore.QSize(600, height))
            self.updateWindow.exec_()
            try:
                if self.updateWindow.buttonName == 'update_button':
                    if getattr(sys, 'frozen', False):
                        temp_folder = tempfile.gettempdir()
                    else:
                        temp_folder = os.path.expanduser("~") + "/Downloads/"
                    self.downloadWindow = MyUpdate(self.link_latest_version,
                                                   temp_folder)
                    x1, y1, w1, h1 = self.geometry().getRect()
                    _, _, w2, h2 = self.downloadWindow.geometry().getRect()
                    x2 = x1 + w1 / 2 - w2 / 2
                    y2 = y1 + h1 / 2 - h2 / 2
                    self.downloadWindow.setGeometry(x2, y2, w2, h2)
                    self.downloadWindow.setMinimumSize(
                        QtCore.QSize(500,
                                     self.downloadWindow.sizeHint().height()))
                    self.downloadWindow.setMaximumSize(
                        QtCore.QSize(500,
                                     self.downloadWindow.sizeHint().height()))
                    self.downloadWindow.exec_()
                    logging.debug(
                        'mainwindow.py - download_and_install_downloader_update - download finished'
                    )
                    if not self.downloadWindow.cancel:
                        if getattr(sys, 'frozen', False):
                            filename = self.link_latest_version[
                                self.link_latest_version.rfind('/') + 1:]
                            if platform.system() == 'Windows':
                                os.startfile(temp_folder + '\\' + filename)
                                time.sleep(0.1)
                                self.close()
                            elif platform.system() == 'Linux':
                                shutil.copy('functions/unzip_update.py',
                                            temp_folder)
                                install_folder = self.config_path + '/test/'
                                command = 'python3 ' + temp_folder + '/unzip_update.py ' + temp_folder + '/' + filename + ' ' + install_folder
                                os.system('x-terminal-emulator -e ' + command)
                                time.sleep(0.1)
                                self.close()
                        else:
                            time.sleep(0.1)
                            self.close()
            except AttributeError:
                pass

    def get_file_name(self, action):
        logging.debug('mainwindow.py - get_file_name')
        file_dialog = QtWidgets.QFileDialog()
        file_dialog.setDefaultSuffix('xml')
        if action == 'save':
            file_name, _ = file_dialog.getSaveFileName(
                self, 'Save XML File', '', filter='XML Files (*.xml)')
        elif action == 'open':
            file_name, _ = file_dialog.getOpenFileName(
                self, 'Open XML File', '', filter='XML Files (*.xml)')
        logging.debug('mainwindow.py - get_file_name - file_name ' + file_name)
        return file_name

    def save_warning_window(self, string):
        logging.debug('mainwindow.py - save_warning_window')
        self.presaveWindow = MyWarning(string)
        x1, y1, w1, h1 = self.geometry().getRect()
        _, _, w2, h2 = self.presaveWindow.geometry().getRect()
        x2 = x1 + w1 / 2 - w2 / 2
        y2 = y1 + h1 / 2 - h2 / 2
        self.presaveWindow.setGeometry(x2, y2, w2, h2)
        self.presaveWindow.setMinimumSize(
            QtCore.QSize(500,
                         self.presaveWindow.sizeHint().height()))
        self.presaveWindow.setMaximumSize(
            QtCore.QSize(500,
                         self.presaveWindow.sizeHint().height()))
        self.presaveWindow.exec_()
        return self.presaveWindow.buttonName