def show_splash(self): """ Class function to refresh API data from Frontier's servers, and to read systems and stations from JSON files downloaded from EDDB.IO NOTE: We create and destroy an app window to show this window before we launch our main GUI """ self.refresh_app = QtGui.QApplication(sys.argv) # For animated GIF, we use QMovie try: gif_busy = QtGui.QMovie(":/icons/busy.gif") gif_check = QtGui.QPixmap(":/icons/check-2x.png") except FileNotFoundError as err: print(err) exit(1) self.mainwindow = QtGui.QWidget() self.splash_window = Ui_splash() self.splash_window.setupUi(self.mainwindow) self.mainwindow.setStyleSheet(self.style) self.mainwindow.setWindowFlags(QtCore.Qt.FramelessWindowHint) self.mainwindow.show() # Initial values self.splash_window.lbl_progress_api.setMovie(gif_busy) gif_busy.start() # Starting animation anim_thread1 = Thread(target=self.refresh_api, args=(True,)) anim_thread1.daemon = True anim_thread1.start() while anim_thread1.is_alive(): self.refresh_app.processEvents() # We refresh the gui while we wait for thread to complete anim_thread1.join() if self.rerun: # We need to log in with GUI, which we cannot do from thread, so we do it manually here self.refresh_api(False) try: self.api_connected = True except: print("Unable to refresh API - we need to try adjusting settings") self.api_connected = False print("EXIT") # Updating labels self.splash_window.lbl_progress_api.setPixmap(gif_check) self.splash_window.lbl_progress_systems.setMovie(gif_busy) anim_thread2 = Thread(target=self.refresh_systems, args=(self.settings.systemsDataFile,)) anim_thread2.daemon = True anim_thread2.start() while anim_thread2.is_alive(): self.refresh_app.processEvents() # We refresh the gui while we wait for thread to complete anim_thread2.join() # Updating labels self.splash_window.lbl_progress_systems.setPixmap(gif_check) self.splash_window.lbl_progress_stations.setMovie(gif_busy) anim_thread3 = Thread(target=self.refresh_stations, args=(self.settings.stationsDataFile,)) anim_thread3.daemon = True anim_thread3.start() while anim_thread3.is_alive(): self.refresh_app.processEvents() # We refresh the gui while we wait for thread to complete anim_thread3.join() # Updating labels gif_busy.stop() # Stopping animation self.splash_window.lbl_progress_stations.setPixmap(gif_check) self.refresh_app.processEvents() # We refresh the gui time.sleep(1) self.mainwindow.close() self.refresh_app.quit()
class CMDR: """CMDR class - contains all CMDR data from Frontier's API""" def __init__(self, global_settings, style): # We need to import settings """ :global_settings:global program settings for EDreporter """ self.settings = global_settings self.style = style # self.database = TinyDB(self.settings.historyDatabase) # TODO: Store every api read in database. Only once entry per day, so if day same as previous, overwrite self.api_connected = False self.rerun = False # Do we need to run the api_refresh() outside of a thread in order to log in? self.show_splash() # Read the JSON files for stations and systems, and get data from the API (QSplashScreen) # API categories self.categories = [ "Commander", "Ship", "Credits", "Capacity (tons)", "Free Cargo (tons)", "Fuel level", "Current system", "Last docked", "Combat rank", "Trade rank", "Exploration rank", "CQC rank", "Federation rank", "Empire rank", ] self.rank_names = dict( combat=( "Harmless", "Mostly Harmless", "Novice", "Competent", "Expert", "Master", "Dangerous", "Deadly", "Elite", ), empire=( "None", "Outsider", "Serf", "Master", "Squire", "Knight", "Lord", "Baron", "Viscount", "Count", "Earl", "Marquis", "Duke", "Prince", "King", ), explore=( "Aimless", "Mostly Aimless", "Scout", "Surveyor", "Trailblazer", "Pathfinder", "Ranger", "Starblazer", "Elite", ), federation=( "None", "Recruit", "Cadet", "Midshipman", "Petty Officer", "Chief Petty Officer", "Warrant Officer", "Ensign", "Lieutenant", "Lieutenant Commander", "Post Commander", "Post Captain", "Rear Admiral", "Vice Admiral", "Admiral", ), trade=( "Penniless", "Mostly Penniless", "Pedler", "Dealer", "Merchant", "Broker", "Entrepreneur", "Tycoon", "Elite", ), cqc=( "Helpless", "Mostly Helpless", "Amateur", "Semi Professional", "Professional", "Champion", "Hero", "Legend", "Elite", ), ) # Values for the categories, fetched from the API and customized for output (note # that we need to ensure the API is refreshed first) if self.api_connected: self.values = [ self.api.profile["commander"]["name"], self.api.profile["ship"]["name"], "{:,}".format(self.api.profile["commander"]["credits"]).replace(",", "'"), # We introduce thousand separator and replace it with ' str(self.api.profile["ship"]["cargo"]["capacity"]).replace(",", "'"), str(self.api.profile["ship"]["cargo"]["capacity"] - self.api.profile["ship"]["cargo"]["qty"]).replace( ",", "'" ), str( int( 100 * self.api.profile["ship"]["fuel"]["main"]["level"] / self.api.profile["ship"]["fuel"]["main"]["capacity"] ) ) + "%", self.api.profile["lastSystem"]["name"] + " (" + self.api.profile["lastSystem"]["faction"] + ")", self.api.profile["lastStarport"]["name"], self.rank_names["combat"][self.api.profile["commander"]["rank"]["combat"]], self.rank_names["trade"][self.api.profile["commander"]["rank"]["trade"]], self.rank_names["explore"][self.api.profile["commander"]["rank"]["explore"]], self.rank_names["cqc"][self.api.profile["commander"]["rank"]["cqc"]], self.rank_names["federation"][self.api.profile["commander"]["rank"]["federation"]], self.rank_names["empire"][self.api.profile["commander"]["rank"]["empire"]], ] else: self.values = ["n / a"] * 14 # NOTE: This hardcoded number must correspond to number of API values above def show_splash(self): """ Class function to refresh API data from Frontier's servers, and to read systems and stations from JSON files downloaded from EDDB.IO NOTE: We create and destroy an app window to show this window before we launch our main GUI """ self.refresh_app = QtGui.QApplication(sys.argv) # For animated GIF, we use QMovie try: gif_busy = QtGui.QMovie(":/icons/busy.gif") gif_check = QtGui.QPixmap(":/icons/check-2x.png") except FileNotFoundError as err: print(err) exit(1) self.mainwindow = QtGui.QWidget() self.splash_window = Ui_splash() self.splash_window.setupUi(self.mainwindow) self.mainwindow.setStyleSheet(self.style) self.mainwindow.setWindowFlags(QtCore.Qt.FramelessWindowHint) self.mainwindow.show() # Initial values self.splash_window.lbl_progress_api.setMovie(gif_busy) gif_busy.start() # Starting animation anim_thread1 = Thread(target=self.refresh_api, args=(True,)) anim_thread1.daemon = True anim_thread1.start() while anim_thread1.is_alive(): self.refresh_app.processEvents() # We refresh the gui while we wait for thread to complete anim_thread1.join() if self.rerun: # We need to log in with GUI, which we cannot do from thread, so we do it manually here self.refresh_api(False) try: self.api_connected = True except: print("Unable to refresh API - we need to try adjusting settings") self.api_connected = False print("EXIT") # Updating labels self.splash_window.lbl_progress_api.setPixmap(gif_check) self.splash_window.lbl_progress_systems.setMovie(gif_busy) anim_thread2 = Thread(target=self.refresh_systems, args=(self.settings.systemsDataFile,)) anim_thread2.daemon = True anim_thread2.start() while anim_thread2.is_alive(): self.refresh_app.processEvents() # We refresh the gui while we wait for thread to complete anim_thread2.join() # Updating labels self.splash_window.lbl_progress_systems.setPixmap(gif_check) self.splash_window.lbl_progress_stations.setMovie(gif_busy) anim_thread3 = Thread(target=self.refresh_stations, args=(self.settings.stationsDataFile,)) anim_thread3.daemon = True anim_thread3.start() while anim_thread3.is_alive(): self.refresh_app.processEvents() # We refresh the gui while we wait for thread to complete anim_thread3.join() # Updating labels gif_busy.stop() # Stopping animation self.splash_window.lbl_progress_stations.setPixmap(gif_check) self.refresh_app.processEvents() # We refresh the gui time.sleep(1) self.mainwindow.close() self.refresh_app.quit() def refresh_api(self, threaded=False): """ Refreshes the API data from Frontier's servers Additionally stores the current value in the database in order to build a history for performance tracking :return: the EDAPIgui instance """ self.api = EDAPIgui() self.threaded = threaded self.rerun = False """ In the event that cookie file is missing or rejected, we open a login dialog which logs with username/password These credentials are not stored, but the cookie we get back from Frontier is, so we can log in without authenticating next time. """ if self.api.response == "Cookie file missing": if not self.threaded: self.login_window = _LoginWindow(self.api) self.login_window.show() while ( self.login_window.alive or self.login_window.token.alive ): # As long as either the login or code verification windows exists, wait for them self.refresh_app.processEvents() time.sleep(2) self.api = EDAPIgui() # We reinitialize the API to try over else: # We are being called from a thread (non-QThread) and cannot do GUI operations self.rerun = True # We need to re-run this function from the main thread return try: self.api.profile = self.api.response.json() except: sys.exit("Unable to parse JSON response for profile!") def refresh_systems(self, systems_file): try: self.systems = dict([(x["name"], str(x["id"])) for x in json.loads(open(systems_file).read())]) except FileNotFoundError: print(self.settings.systemsDataFile) showerror( "Critical error", 'Systems data file, "' + self.settings.systemsDataFile + '" missing. Aborting...' ) exit(1) def refresh_stations(self, stations_file): try: self.stations = dict([(x["name"], str(x["id"])) for x in json.loads(open(stations_file).read())]) except FileNotFoundError: showerror( "Critical error", 'Systems data file, "' + self.settings.stationsDataFile + '" missing. Aborting...' ) exit(1)