Esempio n. 1
0
    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()
Esempio n. 2
0
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)