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
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> <b>' + folder + '</b><br>' + 'with the file name:<br> <b>' + filename + '</b>.') else: if nas_md5 == '' and local_md5 == '': text = ( 'The configuration file has been downloaded in the folder:<br> <b>' + folder + '</b><br>' + 'with the file name:<br> <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> <b>' + folder + '</b><br>' + 'with the file name:<br> <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> <b>' + folder + '</b><br>' + 'with the file name:<br> <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> <b>' + folder + '</b><br>' + 'with the file name:<br> <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, translations, parent=None): logging.debug('mainwindow.py - MainWindow - __init__') QtWidgets.QMainWindow.__init__(self, parent) self.gui_path = path self.config_dict = config_dict self.translations_dict = translations self.setupUi(self) self.link_latest_version = None self.check_downloader = None self.optionsWindow = None self.aboutWindow = None self.managerWindow = None self.updateWindow = None self.downloadWindow = None self.infoWindow = None self.protocol = None self.downloading = False self.ftp_profiles = collections.OrderedDict() self.hidden_items = {} self.old_local_path = '' self.local_path = '' self.transfert_tree.setSelectionMode( QtWidgets.QAbstractItemView.ExtendedSelection) self.transfert_tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.transfert_tree.customContextMenuRequested.connect( lambda position: transfer_tree_menu(self, position)) self.connexion_browser.setContextMenuPolicy( QtCore.Qt.CustomContextMenu) self.connexion_browser.customContextMenuRequested.connect( lambda position: connection_browser_menu(self, position)) self.main_splitter_1.splitterMoved.connect( lambda left, right: set_splitter_position(self, left, right)) self.main_splitter_3.setSizes([605, 605]) translate_elements(self, self.config_dict['OPTIONS'].get('language'), self.translations_dict) set_ftp_profiles(self) set_profile_list(self) prepare_tree_widgets(self) display_local_path(self) display_remote_path(self) set_one_two_local(self) set_one_two_remote(self) set_local_tree(self) set_remote_tree(self) self.check_orionftp_update() self.info_button_1.clicked.connect(self.display_information) self.main_download_bt.clicked.connect(self.download_selection) self.main_connect_bt.clicked.connect(self.initiate_connection) self.main_profile_cb.currentIndexChanged.connect( lambda index: activate_connexion_button(self, index)) self.main_profile_cb.setItemDelegate(QtWidgets.QStyledItemDelegate()) self.transfert_tree.setHeaderHidden(False) set_default_path_local_tree(self) self.action_quit_bt.clicked.connect(self.close_window) self.action_option_bt.clicked.connect(self.open_options) self.action_about_bt.clicked.connect(self.open_about) self.action_update_bt.clicked.connect(self.download_and_install_update) self.action_refresh_bt.clicked.connect(self.refresh_remote_folder) self.action_close_bt.clicked.connect(self.close_connection) self.action_manager_bt.clicked.connect(self.open_manager) logging.info('mainwindow.py - MainWindow ready') def open_manager(self): logging.debug('mainwindow.py - open_manager') self.managerWindow = MyManager(self.config_dict, self.translations_dict, copy.deepcopy(self.ftp_profiles)) self.managerWindow.exec_() if self.managerWindow.ftp_profiles is not None: self.ftp_profiles = self.managerWindow.ftp_profiles create_profile_xml('ftp_profiles.xml', self.managerWindow.ftp_profiles) set_profile_list(self) def open_about(self): logging.debug('mainwindow.py - open_about') self.aboutWindow = MyAbout(self.config_dict, self.translations_dict) self.aboutWindow.exec_() def open_options(self): logging.debug('mainwindow.py - open_options') old_config_dict = copy_config_dict(self.config_dict) ftp_profile_list = [key for key in self.ftp_profiles] config_string = io.StringIO() self.config_dict.write(config_string) config_string.seek(0) config_dict_copy = configparser.ConfigParser() config_dict_copy.read_file(config_string) self.optionsWindow = MyOptions(config_dict_copy, self.translations_dict, ftp_profile_list) self.optionsWindow.available_update.connect(self.parse_orionftp_update) self.optionsWindow.exec_() if self.optionsWindow.ow_config_dict is not None: logging.debug('mainwindow.py - open_options - saving config dict') self.config_dict = self.optionsWindow.ow_config_dict ini_file = open(os.path.join(self.gui_path, 'orion_ftp.ini'), 'w') self.config_dict.write(ini_file) ini_file.close() self.apply_options(old_config_dict) def check_orionftp_update(self): logging.debug('mainwindow.py - check_orionftp_update') self.action_update_bt.setEnabled(False) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap("icons/orionftp_update_off.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.action_update_bt.setIcon(icon) self.action_update_bt.setToolTip('') if self.config_dict['OPTIONS'].getboolean('check_update'): self.check_downloader = CheckOrionFTPOnline() self.check_downloader.start() self.check_downloader.finished.connect(self.parse_orionftp_update) else: logging.info( 'mainwindow.py - check_orionftp_update - from options, no update check' ) def parse_orionftp_update(self, val): logging.debug('mainwindow.py - parse_orionftp_update - val ' + str(val)) if val == 'no new version': self.action_update_bt.setEnabled(False) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap("icons/orionftp_update_off.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.action_update_bt.setIcon(icon) self.action_update_bt.setToolTip( self.translations_dict['nonewupdate'][ self.config_dict['OPTIONS'].get('language')]) elif 'http' in val: self.action_update_bt.setEnabled(True) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap("icons/orionftp_update_on.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.action_update_bt.setIcon(icon) if getattr(sys, 'frozen', False): self.action_update_bt.setToolTip( self.translations_dict['newupdatefrozen'][ self.config_dict['OPTIONS'].get('language')]) else: self.action_update_bt.setToolTip( self.translations_dict['newupdatesources'][ self.config_dict['OPTIONS'].get('language')]) 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 if getattr(sys, 'frozen', False): frozen = True self.updateWindow = MyWarningUpdate(frozen, self.config_dict, self.translations_dict) self.updateWindow.exec_() temp_folder = None if self.updateWindow.update: if frozen: temp_folder = tempfile.gettempdir() else: if platform.system() == 'Windows': temp_folder = os.path.expanduser("~") + "\\Downloads\\" elif platform.system() == 'Linux': temp_folder = os.path.expanduser("~") + "/Downloads/" self.downloadWindow = MyUpdate(self.link_latest_version, temp_folder, self.config_dict, self.translations_dict) self.downloadWindow.exec_() logging.debug( 'mainwindow.py - download_and_install_update - download finished' ) if frozen: 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() def display_information(self): logging.debug('mainwindow.py - Mainwindow - display_information') self.infoWindow = MyMainInfo(self.config_dict, self.translations_dict) self.infoWindow.exec_() def initiate_connection(self): logging.debug('mainwindow.py - Mainwindow - initiate_connection') if self.main_profile_cb.currentIndex() != 0: widget_list = [ self.main_remote_ln, self.main_remote_tr_1, self.main_remote_tr_2, self.connexion_browser, self.transfert_tree ] if self.ftp_profiles[str( self.main_profile_cb.currentText())]['protocol'] == 'ftp': self.protocol = FTPProtocol( self.ftp_profiles[str(self.main_profile_cb.currentText())], widget_list, self.config_dict, self.translations_dict) elif self.ftp_profiles[str( self.main_profile_cb.currentText())]['protocol'] == 'sftp': self.protocol = SFTPProtocol( self.ftp_profiles[str(self.main_profile_cb.currentText())], widget_list, self.config_dict, self.translations_dict) self.protocol.update_local_file_list.connect( lambda: set_local_files(self)) self.protocol.connection_success.connect( self.successful_connection) self.protocol.connection_failure.connect( self.unsuccessful_connection) self.protocol.connection_issue.connect(self.connection_issue) self.protocol.connection_closed.connect(self.connection_closed) self.protocol.download_finished.connect( lambda: set_download_finished(self)) self.protocol.connection_start() def successful_connection(self): logging.debug('mainwindow.py - Mainwindow - successful_connection') activate_ftp_icons(self) deactivate_ftp_connection(self) self.main_local_ln.setSelection(0, 0) def unsuccessful_connection(self): logging.debug('mainwindow.py - Mainwindow - unsuccessful_connection') deactivate_ftp_icons(self) activate_ftp_connection(self) self.protocol = None text = self.translations_dict['connectiontimeout'][ self.config_dict['OPTIONS'].get('language')] self.infoWindow = MyInfo(text) self.infoWindow.resize(450, 200) self.infoWindow.exec_() def connection_issue(self): logging.debug('mainwindow.py - Mainwindow - connection_issue') text = self.translations_dict['connectionissue'][ self.config_dict['OPTIONS'].get('language')] self.infoWindow = MyInfo(text) self.infoWindow.resize(450, 200) self.infoWindow.exec_() def close_connection(self): logging.debug('mainwindow.py - MainWindow - close_connection') if self.protocol is not None: self.protocol.close_ftp() def connection_closed(self): logging.debug('mainwindow.py - Mainwindow - connection_closed') deactivate_ftp_icons(self) activate_ftp_connection(self) clean_remote_widgets(self) self.protocol = None set_download_finished(self) def refresh_remote_folder(self): logging.debug('mainwindow.py - MainWindow - refresh_remote_folder') if self.protocol is not None: try: index = self.main_remote_tr_1.selectedIndexes()[0] self.protocol.refresh(index) except IndexError: pass def download_selection(self): logging.debug('mainwindow.py - MainWindow - download_selection') if self.protocol is not None: self.main_tabwidget.setCurrentIndex(1) self.downloading = True self.protocol.download_selection(self.local_path) activate_download_button(self) def apply_options(self, config_dict): logging.debug('mainwindow.py - MainWindow - apply_options') if self.config_dict['OPTIONS'].get( 'language') != config_dict['language']: logging.debug( 'mainwindow.py - MainWindow - apply_options - language set') translate_elements(self, self.config_dict['OPTIONS'].get('language'), self.translations_dict) self.local_model.setText(self.translations_dict['qtreeview'][ self.config_dict['OPTIONS'].get('language')][0]) self.remote_model.setHeaderData( 0, QtCore.Qt.Horizontal, self.translations_dict['qtreeview'][ self.config_dict['OPTIONS'].get('language')][0]) if self.config_dict['OPTIONS'].getboolean( 'check_update') and self.config_dict['OPTIONS'].getboolean( 'check_update') != config_dict['check_update']: logging.debug( 'mainwindow.py - MainWindow - apply_options - update_check set' ) self.check_orionftp_update() if self.config_dict['LOG'].get('level') != config_dict['level']: logging.debug( 'mainwindow.py - MainWindow - apply_options - level set') logging.getLogger().setLevel(self.config_dict.get('LOG', 'level')) if (self.config_dict['INTERFACE'].getboolean('local_tree_one_widget') != config_dict['local_tree_one_widget']): set_one_two_local(self) display_file_folder_local_tree(self) set_connection_local_tree(self) if not self.config_dict['INTERFACE'].getboolean( 'local_tree_one_widget'): set_local_files(self) if (self.config_dict['INTERFACE'].getboolean( 'display_icons_local_tree') != config_dict['display_icons_local_tree']): set_local_icon_provider(self) if not self.config_dict['INTERFACE'].getboolean( 'local_tree_one_widget'): set_local_files(self) if (self.config_dict['INTERFACE'].getboolean('display_path_local_tree') != config_dict['display_path_local_tree']): display_local_path(self) if (self.config_dict['INTERFACE'].getboolean('remote_tree_one_widget') != config_dict['remote_tree_one_widget']): set_one_two_remote(self) if self.protocol is not None: self.protocol.one_tree_option = self.config_dict[ 'INTERFACE'].getboolean('remote_tree_one_widget') self.protocol.reset_tree() if (self.config_dict['INTERFACE'].getboolean( 'display_icons_remote_tree') != config_dict['display_icons_remote_tree']): if self.protocol is not None: self.protocol.display_icon = self.config_dict[ 'INTERFACE'].getboolean('display_icons_remote_tree') self.protocol.reset_tree() if (self.config_dict['INTERFACE'].getboolean( 'display_path_remote_tree') != config_dict['display_path_remote_tree']): display_remote_path(self) def close_window(self): logging.debug('mainwindow.py - MainWindow - close_window') self.close_connection() self.close() def closeEvent(self, event): logging.debug('mainwindow.py - MainWindow - closeEvent') logging.info('**********************************') logging.info('OrionFTP is closing ...') logging.info('**********************************')
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) 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