Exemplo n.º 1
0
    def update_unit_stats(self, unit_data):
        """ Update unit stats """

        # Create tab if it's not there yey
        if not hasattr(self, 'TAB_CommUnitStats'):
            self.TAB_CommUnitStats = QtWidgets.QWidget()
            self.TABW_StatResults.insertTab(4, self.TAB_CommUnitStats,
                                            "Unit stats")

        # Update commander units widget
        if not hasattr(self, 'WD_unit_stats'):
            self.WD_unit_stats = MUI.UnitStats(unit_data,
                                               parent=self.TAB_CommUnitStats)
        else:
            self.WD_unit_stats.unit_data = unit_data
            self.WD_unit_stats.update_units()

        # Amon unit tab
        if not hasattr(self, 'TAB_AmonUnitStats'):
            self.TAB_AmonUnitStats = QtWidgets.QWidget()
            self.TABW_StatResults.insertTab(5, self.TAB_AmonUnitStats,
                                            "Amon stats")

        # Update amon units widget
        if not hasattr(self, 'WD_amon_unit_stats'):
            self.WD_amon_unit_stats = MUI.AmonUnitStats(
                unit_data['amon'], parent=self.TAB_AmonUnitStats)
        else:
            self.WD_amon_unit_stats.update_data(unit_data['amon'])
Exemplo n.º 2
0
    def filter_players(self):
        """ Filters only players with string in name or note """
        self.filter_players_running = True
        text = self.ED_Winrate_Search.text().lower()
        idx = 0
        show_max = 50 if self.CH_OnlyTop50.isChecked() else 10000
        created = 0

        # First hide all
        for player in self.player_winrate_UI_dict:
            self.player_winrate_UI_dict[player].hide()

        # Go through winrate data and check for player names
        for player in self.p.winrate_data:
            if text in player.lower() and idx < show_max:

                # If many created, pause for bit. Otherwise some PCs might struggle
                if created > 100:
                    self.p.wait_ms(5)
                    created = 0

                # Create element if necessary and show
                if not player in self.player_winrate_UI_dict:
                    created += 1
                    self.player_winrate_UI_dict[player] = MUI.PlayerEntry(player,
                                                                        self.p.winrate_data[player],
                                                                        SM.settings['player_notes'].get(player, None),
                                                                        self.SC_PlayersScrollAreaContents) #yapf: disable
                    self.SC_PlayersScrollAreaContentsLayout.addWidget(
                        self.player_winrate_UI_dict[player].widget)
                self.player_winrate_UI_dict[player].show()
                idx += 1

        # Go though notes
        for player, note in SM.settings['player_notes'].items():
            if text in note.lower() and idx < show_max:
                # Create element if necessary and show
                if not player in self.player_winrate_UI_dict:
                    self.player_winrate_UI_dict[player] = MUI.PlayerEntry(player,
                                                                        self.p.winrate_data[player],
                                                                        SM.settings['player_notes'].get(player, None),
                                                                        self.SC_PlayersScrollAreaContents) #yapf: disable
                    self.SC_PlayersScrollAreaContentsLayout.addWidget(
                        self.player_winrate_UI_dict[player].widget)
                self.player_winrate_UI_dict[player].show()
                idx += 1

        # Finished
        self.filter_players_running = False
Exemplo n.º 3
0
    def add_new_game_data(self, replay_dict):
        """ Updates game tab, player tab, sets winrate data in MF, updates mass replay analysis and generates stats anew """

        self.p.TAB_Randomizer.RNG_Overlay_changed()

        if hasattr(self.p, 'CAnalysis') and replay_dict is not None:
            # Add game to game tab
            try:
                # Update mass replay analysis
                full_data = self.p.CAnalysis.add_parsed_replay(replay_dict)
                if full_data is None:
                    return

                # Update UI in game tab
                self.game_UI_dict[replay_dict['parser']
                                  ['file']] = MUI.GameEntry(
                                      full_data, self.p.CAnalysis.main_handles,
                                      self.SC_GamesScrollAreaContent)
                self.SC_GamesScrollAreaContentLayout.insertWidget(
                    0, self.game_UI_dict[replay_dict['parser']['file']].widget)

                # Update player tab & set winrate data in MF & generate stats
                self.p.update_winrate_data()
                self.p.TAB_Stats.generate_stats()

                # Put the last player on top of player tab
                for player in {1, 2}:
                    name = replay_dict['parser']['players'][player].get(
                        'name', '-')
                    if not replay_dict['parser']['players'][player].get(
                            'handle', '-') in self.p.CAnalysis.main_handles:
                        self.p.TAB_Players.put_player_first(name)
                        break
            except Exception:
                logger.error(traceback.format_exc())
Exemplo n.º 4
0
 def detailed_my_commander_stats_update(self, commander):
     """ Updates my commander details"""
     self.my_commander_clicked = commander
     if hasattr(self,
                'my_detailed_info') and self.my_detailed_info is not None:
         self.my_detailed_info.deleteLater()
         self.my_detailed_info = None
     self.my_detailed_info = MUI.CommanderStats(
         commander,
         self.my_commander_analysis,
         parent=self.TAB_MyCommanders)
Exemplo n.º 5
0
    def __init__(self, parent):
        super().__init__()
        self.p = parent

        # Performance group box
        self.gb_Resources = QtWidgets.QFrame(self)
        self.gb_Resources.setAutoFillBackground(True)
        self.gb_Resources.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.gb_Resources.setFrameShadow(QtWidgets.QFrame.Plain)
        self.gb_Resources.setGeometry(QtCore.QRect(15, 15, 550, 310))

        # Performance description
        self.la_performance_description = QtWidgets.QLabel(self.gb_Resources)
        self.la_performance_description.setGeometry(QtCore.QRect(14, 10, self.gb_Resources.width() - 20, 300))
        self.la_performance_description.setAlignment(QtCore.Qt.AlignTop)
        self.la_performance_description.setText(
            '<b>Performance overlay:</b><br><br>Shows performance overlay with CPU/RAM/Disk/Network usage for system and StarCraft II.\
                                                <br><br><b>Read</b> and <b>Write</b> stats are disk usage of StarCraft II (current & total).\
                                                <br><b>CPUc</b> is per core CPU usage. 100% means one core fully used.')
        self.la_performance_description.setWordWrap(True)

        # Checks whether to show/hide
        self.ch_performance_show = QtWidgets.QCheckBox(self.gb_Resources)
        self.ch_performance_show.setGeometry(QtCore.QRect(14, 125, 200, 17))
        self.ch_performance_show.setText('Show performance overlay')
        self.ch_performance_show.clicked.connect(self.p.show_hide_performance_overlay)

        # Position overlay
        self.bt_performance_overlay_position = QtWidgets.QPushButton(self.gb_Resources)
        self.bt_performance_overlay_position.setGeometry(QtCore.QRect(14, 150, 150, 25))
        self.bt_performance_overlay_position.setText('Change overlay position')
        self.bt_performance_overlay_position.clicked.connect(self.p.update_performance_overlay_position)

        # Hotkey description
        self.la_hotkey_performance_desc = QtWidgets.QLabel(self.gb_Resources)
        self.la_hotkey_performance_desc.setGeometry(QtCore.QRect(15, 220, 300, 20))
        self.la_hotkey_performance_desc.setText('<b>Hotkey for showing/hiding overlay</b>')

        # Hotkey
        self.KEY_Performance = MUI.CustomKeySequenceEdit(self.gb_Resources)
        self.KEY_Performance.setGeometry(QtCore.QRect(15, 245, 113, 25))
        self.KEY_Performance.setToolTip('Key for showing or hiding performance overlay')
        self.KEY_Performance.keySequenceChanged.connect(self.p.hotkey_changed)

        # Apply
        self.bt_performance_apply = QtWidgets.QPushButton(self.gb_Resources)
        self.bt_performance_apply.setGeometry(QtCore.QRect(150, 245, 75, 25))
        self.bt_performance_apply.setText('Apply')
        self.bt_performance_apply.clicked.connect(self.p.saveSettings)
Exemplo n.º 6
0
    def put_player_first(self, player):
        """ Moves a player to the top spot in the player tab.
            Returns the last player on top (if any) to its position. """

        # Return the old player
        if self.last_ally_player is not None:
            w = self.player_winrate_UI_dict[self.last_ally_player]
            self.SC_PlayersScrollAreaContentsLayout.removeWidget(w.widget)

            # Find the position where to put it back
            wins = w.wins
            for idx, pplayer in enumerate(self.player_winrate_UI_dict):
                if wins >= self.player_winrate_UI_dict[
                        pplayer].wins and idx > 0:
                    self.SC_PlayersScrollAreaContentsLayout.insertWidget(
                        idx + 1, w.widget)
                    break

            # Color back
            w.highlight(False)

        # New player to top
        self.last_ally_player = player
        if player in self.player_winrate_UI_dict:
            # If it's there remove
            w = self.player_winrate_UI_dict[player]
            self.SC_PlayersScrollAreaContentsLayout.removeWidget(w.widget)

        else:
            # It's not there, create new one
            self.player_winrate_UI_dict[player] = MUI.PlayerEntry(player,
                                                                    self.p.winrate_data[player],
                                                                    SM.settings['player_notes'].get(player, None),
                                                                    self.SC_PlayersScrollAreaContents) #yapf: disable
            w = self.player_winrate_UI_dict[player]

        # Insert to top, show and change colors
        self.SC_PlayersScrollAreaContentsLayout.insertWidget(0, w.widget)
        w.highlight(True)
        w.widget.show()
Exemplo n.º 7
0
    def search_games(self):
        """ Searches for games with given strings in them and updates games tab"""

        if not hasattr(self.p, 'CAnalysis'):
            return

        search_for = [
            i.replace('_', ' ') for i in self.ed_games_search.text().split()
        ]
        if len(search_for) == 0:
            # Restore default
            new_replays = self.p.CAnalysis.get_last_replays(
                SM.settings['list_games'])
        else:
            # Search for replays with strings in them
            new_replays = self.p.CAnalysis.search(*search_for)
            logger.info(
                f'Searching games with {search_for} | found {len(new_replays)} replays'
            )

        # Hide current replays that are not in there
        for i in range(self.SC_GamesScrollAreaContentLayout.count()):
            widget = self.SC_GamesScrollAreaContentLayout.itemAt(i).widget()
            widget.hide()

        # Add replays
        for r in new_replays[:SM.settings['list_games']]:
            if r.file in self.game_UI_dict:
                self.SC_GamesScrollAreaContentLayout.addWidget(
                    self.game_UI_dict[r.file].widget)
                self.game_UI_dict[r.file].widget.show()
            else:
                self.game_UI_dict[r.file] = MUI.GameEntry(
                    r, self.p.CAnalysis.main_handles,
                    self.SC_GamesScrollAreaContent)
                self.SC_GamesScrollAreaContentLayout.addWidget(
                    self.game_UI_dict[r.file].widget)
Exemplo n.º 8
0
    def update(self, winrate_data, show_max=50):
        """ Updates player tab based on provide winrate data """
        if self.LA_Winrates_Wait is not None:
            self.LA_Winrates_Wait.deleteLater()
            self.LA_Winrates_Wait = None

        # Create new or update top `show_nax` players
        for idx, player in enumerate(winrate_data):
            if idx >= show_max:
                break
            if not player in self.player_winrate_UI_dict:
                self.player_winrate_UI_dict[player] = MUI.PlayerEntry(player,
                                                                      winrate_data[player],
                                                                      SM.settings['player_notes'].get(player, None),
                                                                      self.SC_PlayersScrollAreaContents) #yapf: disable
                self.SC_PlayersScrollAreaContentsLayout.addWidget(
                    self.player_winrate_UI_dict[player].widget)
            else:
                self.player_winrate_UI_dict[player].update_winrates(
                    winrate_data[player])

        # Show top `show_max` and hide the rest
        for idx, player in enumerate(self.player_winrate_UI_dict):
            if idx < show_max:
                self.player_winrate_UI_dict[player].show()
            else:
                self.player_winrate_UI_dict[player].hide()

        # Hide players not in winrate data
        for player in self.player_winrate_UI_dict:
            if not player in winrate_data:
                self.player_winrate_UI_dict[player].hide()

        self.SC_PlayersScrollAreaContents.setLayout(
            self.SC_PlayersScrollAreaContentsLayout)
        self.SC_PlayersScrollArea.setWidget(self.SC_PlayersScrollAreaContents)
Exemplo n.º 9
0
    def __init__(self, parent):
        super().__init__()
        self.p = parent
        self.stats_maps_UI_dict = dict()
        self.stats_region_UI_dict = dict()
        self.stats_mycommander_UI_dict = dict()
        self.stats_allycommander_UI_dict = dict()

        self.FR_Stats = QtWidgets.QFrame(self)
        self.FR_Stats.setGeometry(QtCore.QRect(10, 0, 964, 151))

        # Difficulty
        self.CH_DiffCasual = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_DiffCasual.setGeometry(QtCore.QRect(10, 20, 70, 17))
        self.CH_DiffCasual.setChecked(True)
        self.CH_DiffCasual.setText("Casual")
        self.CH_DiffCasual.stateChanged.connect(self.generate_stats)

        self.CH_DiffNormal = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_DiffNormal.setGeometry(QtCore.QRect(10, 40, 70, 17))
        self.CH_DiffNormal.setChecked(True)
        self.CH_DiffNormal.setText("Normal")
        self.CH_DiffNormal.stateChanged.connect(self.generate_stats)

        self.CH_DiffHard = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_DiffHard.setGeometry(QtCore.QRect(10, 60, 70, 17))
        self.CH_DiffHard.setChecked(True)
        self.CH_DiffHard.setText("Hard")
        self.CH_DiffHard.stateChanged.connect(self.generate_stats)

        self.CH_DiffBrutal = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_DiffBrutal.setGeometry(QtCore.QRect(10, 80, 70, 17))
        self.CH_DiffBrutal.setChecked(True)
        self.CH_DiffBrutal.setText("Brutal")
        self.CH_DiffBrutal.stateChanged.connect(self.generate_stats)

        self.CH_DiffBrutalPlus = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_DiffBrutalPlus.setGeometry(QtCore.QRect(10, 100, 70, 17))
        self.CH_DiffBrutalPlus.setChecked(True)
        self.CH_DiffBrutalPlus.setText("Brutal+")
        self.CH_DiffBrutalPlus.stateChanged.connect(self.generate_stats)

        # Region
        self.CH_Region_NA = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_Region_NA.setGeometry(QtCore.QRect(90, 20, 71, 17))
        self.CH_Region_NA.setChecked(True)
        self.CH_Region_NA.setText("Americas")
        self.CH_Region_NA.stateChanged.connect(self.generate_stats)

        self.CH_Region_EU = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_Region_EU.setGeometry(QtCore.QRect(90, 40, 71, 17))
        self.CH_Region_EU.setChecked(True)
        self.CH_Region_EU.setText("Europe")
        self.CH_Region_EU.stateChanged.connect(self.generate_stats)

        self.CH_Region_KR = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_Region_KR.setGeometry(QtCore.QRect(90, 60, 61, 17))
        self.CH_Region_KR.setChecked(True)
        self.CH_Region_KR.setText("Asia")
        self.CH_Region_KR.stateChanged.connect(self.generate_stats)

        self.CH_Region_CN = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_Region_CN.setGeometry(QtCore.QRect(90, 80, 61, 17))
        self.CH_Region_CN.setChecked(True)
        self.CH_Region_CN.setText("China")
        self.CH_Region_CN.stateChanged.connect(self.generate_stats)

        # Type
        self.CH_TypeNormal = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_TypeNormal.setGeometry(QtCore.QRect(180, 20, 110, 17))
        self.CH_TypeNormal.setChecked(True)
        self.CH_TypeNormal.setText("Normal games")
        self.CH_TypeNormal.stateChanged.connect(self.generate_stats)

        self.CH_TypeMutation = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_TypeMutation.setGeometry(QtCore.QRect(180, 40, 110, 17))
        self.CH_TypeMutation.setChecked(True)
        self.CH_TypeMutation.setText("Mutations")
        self.CH_TypeMutation.stateChanged.connect(self.generate_stats)

        self.CH_AllHistoric = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_AllHistoric.setGeometry(QtCore.QRect(290, 20, 180, 17))
        self.CH_AllHistoric.setChecked(True)
        self.CH_AllHistoric.setText("Override folder selection")
        self.CH_AllHistoric.setToolTip(
            "Shows stats from all replays regardless of which folder is selected"
        )
        self.CH_AllHistoric.stateChanged.connect(self.generate_stats)

        self.CH_DualMain = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_DualMain.setGeometry(QtCore.QRect(290, 40, 250, 17))
        self.CH_DualMain.setChecked(False)
        self.CH_DualMain.setText("Include multi-box games")
        self.CH_DualMain.setToolTip(
            "Include games where both players belong to your accounts")
        self.CH_DualMain.stateChanged.connect(self.generate_stats)

        # Sub15 and both mains
        self.CH_Sub15 = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_Sub15.setGeometry(QtCore.QRect(290, 60, 150, 17))
        self.CH_Sub15.setChecked(True)
        self.CH_Sub15.setText("Include levels 1-14")
        self.CH_Sub15.setToolTip(
            "Include games where the main player was level 1-14")
        self.CH_Sub15.stateChanged.connect(self.generate_stats)

        self.CH_Over15 = QtWidgets.QCheckBox(self.FR_Stats)
        self.CH_Over15.setGeometry(QtCore.QRect(290, 80, 150, 17))
        self.CH_Over15.setChecked(True)
        self.CH_Over15.setText("Include levels 15+")
        self.CH_Over15.setToolTip(
            "Include games where the main player was level 15+")
        self.CH_Over15.stateChanged.connect(self.generate_stats)

        # Games found
        self.LA_GamesFound = QtWidgets.QLabel(self.FR_Stats)
        self.LA_GamesFound.setEnabled(False)
        self.LA_GamesFound.setGeometry(QtCore.QRect(570, 110, 381, 20))
        self.LA_GamesFound.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.LA_GamesFound.setAlignment(QtCore.Qt.AlignRight
                                        | QtCore.Qt.AlignTrailing
                                        | QtCore.Qt.AlignVCenter)

        # Main names
        self.LA_IdentifiedPlayers = QtWidgets.QLabel(self.FR_Stats)
        self.LA_IdentifiedPlayers.setEnabled(False)
        self.LA_IdentifiedPlayers.setGeometry(QtCore.QRect(570, 125, 381, 20))
        self.LA_IdentifiedPlayers.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.LA_IdentifiedPlayers.setAlignment(QtCore.Qt.AlignRight
                                               | QtCore.Qt.AlignTrailing
                                               | QtCore.Qt.AlignVCenter)

        # Date time frame
        self.FR_DateTime = QtWidgets.QFrame(self.FR_Stats)
        self.FR_DateTime.setGeometry(QtCore.QRect(470, 15, 500, 300))

        # Date
        self.LA_ReplayDate = QtWidgets.QLabel(self.FR_DateTime)
        self.LA_ReplayDate.setGeometry(QtCore.QRect(160, 0, 101, 16))
        self.LA_ReplayDate.setStyleSheet('font-weight: bold')
        self.LA_ReplayDate.setAlignment(QtCore.Qt.AlignLeading
                                        | QtCore.Qt.AlignLeft
                                        | QtCore.Qt.AlignVCenter)
        self.LA_ReplayDate.setText("Replay date")

        self.LA_To = QtWidgets.QLabel(self.FR_DateTime)
        self.LA_To.setGeometry(QtCore.QRect(280, 52, 31, 16))
        self.LA_To.setText("To")
        self.TM_ToDate = QtWidgets.QDateEdit(self.FR_DateTime)
        self.TM_ToDate.setGeometry(QtCore.QRect(160, 52, 110, 22))
        self.TM_ToDate.setDateTime(
            QtCore.QDateTime(QtCore.QDate(2030, 12, 30), QtCore.QTime(0, 0,
                                                                      0)))
        self.TM_ToDate.setDisplayFormat("d/M/yyyy")
        self.TM_ToDate.dateChanged.connect(self.generate_stats)

        self.LA_From = QtWidgets.QLabel(self.FR_DateTime)
        self.LA_From.setGeometry(QtCore.QRect(280, 22, 31, 16))
        self.LA_From.setText("From")
        self.TM_FromDate = QtWidgets.QDateEdit(self.FR_DateTime)
        self.TM_FromDate.setGeometry(QtCore.QRect(160, 22, 110, 22))
        self.TM_FromDate.setDateTime(
            QtCore.QDateTime(QtCore.QDate(2015, 11, 10), QtCore.QTime(0, 0,
                                                                      0)))
        self.TM_FromDate.setDisplayFormat("d/M/yyyy")
        self.TM_FromDate.dateChanged.connect(self.generate_stats)

        # Game length
        self.LA_GameLength = QtWidgets.QLabel(self.FR_DateTime)
        self.LA_GameLength.setGeometry(QtCore.QRect(0, 0, 150, 16))
        self.LA_GameLength.setStyleSheet('font-weight: bold')
        self.LA_GameLength.setAlignment(QtCore.Qt.AlignLeading
                                        | QtCore.Qt.AlignLeft
                                        | QtCore.Qt.AlignVCenter)
        self.LA_GameLength.setText("Game length (minutes)")

        self.LA_Maximum = QtWidgets.QLabel(self.FR_DateTime)
        self.LA_Maximum.setGeometry(QtCore.QRect(50, 52, 60, 16))
        self.LA_Maximum.setText("Maximum")

        self.LA_Minimum = QtWidgets.QLabel(self.FR_DateTime)
        self.LA_Minimum.setGeometry(QtCore.QRect(50, 22, 60, 16))
        self.LA_Minimum.setText("Minimum")

        self.SP_MaxGamelength = QtWidgets.QSpinBox(self.FR_DateTime)
        self.SP_MaxGamelength.setGeometry(QtCore.QRect(0, 52, 42, 22))
        self.SP_MaxGamelength.setMinimum(0)
        self.SP_MaxGamelength.setMaximum(1000)
        self.SP_MaxGamelength.setProperty("value", 0)
        self.SP_MaxGamelength.valueChanged.connect(self.generate_stats)

        self.SP_MinGamelength = QtWidgets.QSpinBox(self.FR_DateTime)
        self.SP_MinGamelength.setGeometry(QtCore.QRect(0, 22, 42, 22))
        self.SP_MinGamelength.setMaximum(1000)
        self.SP_MinGamelength.setProperty("value", 0)
        self.SP_MinGamelength.valueChanged.connect(self.generate_stats)

        # Data dump
        self.BT_FA_dump = QtWidgets.QPushButton(self.FR_Stats)
        self.BT_FA_dump.setGeometry(QtCore.QRect(850, 10, 100, 25))
        self.BT_FA_dump.setText('Dump Data')
        self.BT_FA_dump.setToolTip(
            'Dumps all replay data to "replay_data_dump.json" file')
        self.BT_FA_dump.setEnabled(False)

        ##### RESULTS #####
        self.TABW_StatResults = QtWidgets.QTabWidget(self)
        self.TABW_StatResults.setGeometry(QtCore.QRect(5, 126, 971, 459))

        ### TAB Maps
        self.TAB_Maps = QtWidgets.QWidget()
        self.GB_MapsOverview = QtWidgets.QFrame(self.TAB_Maps)
        self.GB_MapsOverview.setGeometry(QtCore.QRect(8, 8, 470, 420))
        self.WD_Heading = MUI.MapEntry(self.GB_MapsOverview,
                                       0,
                                       'Map name',
                                       'Fastest',
                                       'Average',
                                       'Wins',
                                       'Losses',
                                       'Freq',
                                       'Bonus',
                                       bold=True,
                                       button=False)

        self.MapsComboBoxLabel = QtWidgets.QLabel(self.TAB_Maps)
        self.MapsComboBoxLabel.setGeometry(QtCore.QRect(485, 4, 100, 21))
        self.MapsComboBoxLabel.setText('<b>Sort by</b>')

        self.MapsComboBox = QtWidgets.QComboBox(self.TAB_Maps)
        self.MapsComboBox.setGeometry(QtCore.QRect(485, 24, 100, 21))
        self.MapsComboBox.addItem('Average time')
        self.MapsComboBox.addItem('Fastest time')
        self.MapsComboBox.addItem('Frequency')
        self.MapsComboBox.addItem('Wins')
        self.MapsComboBox.addItem('Losses')
        self.MapsComboBox.addItem('Winrate')
        self.MapsComboBox.addItem('Bonus')
        self.MapsComboBox.activated[str].connect(self.generate_stats)

        self.QB_FastestMap = MUI.FastestMap(self.TAB_Maps)

        self.LA_Stats_Wait = QtWidgets.QLabel(self.TAB_Maps)
        self.LA_Stats_Wait.setGeometry(
            QtCore.QRect(0, 0, 470, self.TAB_Maps.height()))
        self.LA_Stats_Wait.setText(
            '<b>Please wait. This can take few minutes the first time.<br>Analyzing your replays.</b>'
        )
        self.LA_Stats_Wait.setAlignment(QtCore.Qt.AlignVCenter
                                        | QtCore.Qt.AlignCenter)

        ### TAB Difficulty & Regions
        self.TAB_DifficultyRegions = QtWidgets.QWidget()
        self.LA_Difficulty_header = MUI.DifficultyEntry(
            'Difficuly',
            'Wins',
            'Losses',
            'Winrate',
            50,
            0,
            bold=True,
            line=True,
            parent=self.TAB_DifficultyRegions)
        self.ProgressionStatsHeading = MUI.RegionStats(
            'Region', {
                'Defeat': 'Losses',
                'Victory': 'Wins',
                'frequency': 'Frequency',
                'max_asc': 'Ascension level',
                'max_com': 'Maxed commanders',
                'winrate': 'Winrate',
                'prestiges': 'Prestiges unlocked'
            },
            0,
            parent=self.TAB_DifficultyRegions,
            bold=True,
            line=True)

        ### TAB Commanders
        self.TAB_MyCommanders = QtWidgets.QWidget()
        self.MyCommanderHeading = MUI.CommanderEntry(
            'Commander',
            'Freq',
            'Wins',
            'Losses',
            'Winrate',
            'APM',
            'Kills',
            2,
            bold=True,
            button=False,
            parent=self.TAB_MyCommanders)

        self.MyCommanderComboBoxLabel = QtWidgets.QLabel(self.TAB_MyCommanders)
        self.MyCommanderComboBoxLabel.setGeometry(QtCore.QRect(
            485, 2, 100, 21))
        self.MyCommanderComboBoxLabel.setText('<b>Sort by</b>')

        self.MyCommanderComboBox = QtWidgets.QComboBox(self.TAB_MyCommanders)
        self.MyCommanderComboBox.setGeometry(QtCore.QRect(485, 22, 100, 21))
        self.MyCommanderComboBox.addItem('Frequency')
        self.MyCommanderComboBox.addItem('Wins')
        self.MyCommanderComboBox.addItem('Losses')
        self.MyCommanderComboBox.addItem('Winrate')
        self.MyCommanderComboBox.addItem('APM')
        self.MyCommanderComboBox.addItem('Kills')
        self.MyCommanderComboBox.activated[str].connect(
            self.my_commander_sort_update)

        ### TAB Allied Commanders
        self.TAB_AlliedCommanders = QtWidgets.QWidget()
        self.LA_AlliedCommanders = QtWidgets.QLabel(self.TAB_AlliedCommanders)
        self.LA_AlliedCommanders.setGeometry(QtCore.QRect(555, 408, 400, 20))
        self.LA_AlliedCommanders.setText(
            "* Frequency has been corrected for your commander preferences")
        self.LA_AlliedCommanders.setAlignment(QtCore.Qt.AlignRight)
        self.LA_AlliedCommanders.setEnabled(False)

        self.AlliedCommanderHeading = MUI.CommanderEntry(
            'Allied commander',
            'Freq',
            'Wins',
            'Losses',
            'Winrate',
            'APM',
            'Kills',
            2,
            bold=True,
            button=False,
            parent=self.TAB_AlliedCommanders,
        )

        self.AllyCommanderComboBoxLabel = QtWidgets.QLabel(
            self.TAB_AlliedCommanders)
        self.AllyCommanderComboBoxLabel.setGeometry(
            QtCore.QRect(485, 2, 100, 21))
        self.AllyCommanderComboBoxLabel.setText('<b>Sort by</b>')

        self.AllyCommanderComboBox = QtWidgets.QComboBox(
            self.TAB_AlliedCommanders)
        self.AllyCommanderComboBox.setGeometry(QtCore.QRect(485, 22, 100, 21))
        self.AllyCommanderComboBox.addItem('Frequency')
        self.AllyCommanderComboBox.addItem('Wins')
        self.AllyCommanderComboBox.addItem('Losses')
        self.AllyCommanderComboBox.addItem('Winrate')
        self.AllyCommanderComboBox.addItem('APM')
        self.AllyCommanderComboBox.addItem('Kills')
        self.AllyCommanderComboBox.activated[str].connect(
            self.ally_commander_sort_update)

        # Full analysis
        self.TAB_FullAnalysis = QtWidgets.QWidget()

        self.CH_FA_description = QtWidgets.QLabel(self.TAB_FullAnalysis)
        self.CH_FA_description.setGeometry(QtCore.QRect(10, 0, 500, 80))
        self.CH_FA_description.setText(
            'Run full analysis to get more accurate game lengths and APM, and see additional statistics \
                                        related to player and unit kills, bonus objectives and other.<br><br><b>Warning! This might \
                                        take few hours and the application will be less responsive.</b>'
        )
        self.CH_FA_description.setWordWrap(True)

        self.BT_FA_run = QtWidgets.QPushButton(self.TAB_FullAnalysis)
        self.BT_FA_run.setGeometry(QtCore.QRect(10, 85, 80, 25))
        self.BT_FA_run.setText('Run')
        self.BT_FA_run.setEnabled(False)

        self.BT_FA_stop = QtWidgets.QPushButton(self.TAB_FullAnalysis)
        self.BT_FA_stop.setGeometry(QtCore.QRect(105, 85, 80, 25))
        self.BT_FA_stop.clicked.connect(self.p.stop_full_analysis)
        self.BT_FA_stop.setText('Stop')
        self.BT_FA_stop.setEnabled(False)

        self.CH_FA_atstart = QtWidgets.QCheckBox(self.TAB_FullAnalysis)
        self.CH_FA_atstart.setGeometry(QtCore.QRect(11, 115, 300, 25))
        self.CH_FA_atstart.setText('Continue full analysis at start')

        self.CH_FA_status = QtWidgets.QLabel(self.TAB_FullAnalysis)
        self.CH_FA_status.setGeometry(QtCore.QRect(10, 140, 400, 40))

        # Putting it together
        self.TABW_StatResults.addTab(self.TAB_Maps, "")
        self.TABW_StatResults.setTabText(
            self.TABW_StatResults.indexOf(self.TAB_Maps), "Maps")

        self.TABW_StatResults.addTab(self.TAB_AlliedCommanders, "")
        self.TABW_StatResults.setTabText(
            self.TABW_StatResults.indexOf(self.TAB_AlliedCommanders),
            "Allied commanders")

        self.TABW_StatResults.addTab(self.TAB_MyCommanders, "")
        self.TABW_StatResults.setTabText(
            self.TABW_StatResults.indexOf(self.TAB_MyCommanders),
            "My commanders")

        self.TABW_StatResults.addTab(self.TAB_DifficultyRegions, "")
        self.TABW_StatResults.setTabText(
            self.TABW_StatResults.indexOf(self.TAB_DifficultyRegions),
            "Difficulty and regions")

        self.TABW_StatResults.addTab(self.TAB_FullAnalysis, "")
        self.TABW_StatResults.setTabText(
            self.TABW_StatResults.indexOf(self.TAB_FullAnalysis),
            "Full analysis")

        self.TABW_StatResults.setCurrentIndex(0)
        self.TABW_StatResults.currentChanged.connect(self.switched_tab)
Exemplo n.º 10
0
    def ally_commander_sort_update(self):
        """ Creates and updates widgets for allu commander stats """
        sort_commanders_by = self.AllyCommanderComboBox.currentText()
        translate = {
            'APM': 'MedianAPM',
            'Winrate': 'Winrate',
            'Losses': 'Defeat',
            'Wins': 'Victory',
            'Frequency': 'Frequency',
            'Kills': 'KillFraction'
        }
        self.ally_commander_analysis = {
            k: v
            for k, v in sorted(
                self.ally_commander_analysis.items(),
                key=lambda x: x[1][translate[sort_commanders_by]],
                reverse=True)
        }

        for item in set(self.stats_allycommander_UI_dict.keys()):
            self.stats_allycommander_UI_dict[item].deleteLater()
            del self.stats_allycommander_UI_dict[item]

        idx = 0
        spacing = 21
        firstCommander = None
        for co in self.ally_commander_analysis:
            if co == 'any':
                continue
            if firstCommander is None:
                firstCommander = co
            self.stats_allycommander_UI_dict[co] = MUI.CommanderEntry(
                co,
                f"{100*self.ally_commander_analysis[co]['Frequency']:.1f}%",
                self.ally_commander_analysis[co]['Victory'],
                self.ally_commander_analysis[co]['Defeat'],
                f"{100*self.ally_commander_analysis[co]['Winrate']:.0f}%",
                f"{self.ally_commander_analysis[co]['MedianAPM']:.0f}",
                f"{100*self.ally_commander_analysis[co].get('KillFraction',0):.0f}%",
                idx * spacing + 23,
                parent=self.TAB_AlliedCommanders,
                bg=True if idx % 2 == 1 else False)

            self.stats_allycommander_UI_dict[co].bt_button.clicked.connect(
                partial(self.detailed_ally_commander_stats_update, co))
            idx += 1

        self.stats_allycommander_UI_dict['any'] = MUI.CommanderEntry(
            'Σ',
            f"{100*self.ally_commander_analysis['any']['Frequency']:.0f}%",
            self.ally_commander_analysis['any']['Victory'],
            self.ally_commander_analysis['any']['Defeat'],
            f"{100*self.ally_commander_analysis['any']['Winrate']:.0f}%",
            f"{self.ally_commander_analysis['any']['MedianAPM']:.0f}",
            f"{100*self.ally_commander_analysis['any'].get('KillFraction',0):.0f}%",
            idx * spacing + 23,
            parent=self.TAB_AlliedCommanders,
            button=False)

        # Update details
        if hasattr(
                self,
                'ally_detailed_info') and self.ally_detailed_info is not None:
            self.ally_detailed_info.deleteLater()
            self.ally_detailed_info = None

        if hasattr(
                self, 'ally_commander_clicked'
        ) and self.ally_commander_clicked in self.ally_commander_analysis:
            self.ally_detailed_info = MUI.CommanderStats(
                self.ally_commander_clicked,
                self.ally_commander_analysis,
                parent=self.TAB_AlliedCommanders)
        elif len(self.ally_commander_analysis) > 1:
            self.ally_detailed_info = MUI.CommanderStats(
                firstCommander,
                self.ally_commander_analysis,
                parent=self.TAB_AlliedCommanders)
Exemplo n.º 11
0
    def generate_stats(self):
        """ Generate stats and passes data to be shown"""

        if not hasattr(self.p, 'CAnalysis'):
            logger.error('Mass analysis hasn\'t finished yet')
            return

        # Check
        if self.CH_AllHistoric.isChecked():
            self.p.CAnalysis.update_data(showAll=True)
        else:
            self.p.CAnalysis.update_data(showAll=False)

        # Filter
        include_mutations = True if self.CH_TypeMutation.isChecked() else False
        include_normal_games = True if self.CH_TypeNormal.isChecked(
        ) else False

        difficulty_filter = set()
        if not self.CH_DiffCasual.isChecked():
            difficulty_filter.add('Casual')
        if not self.CH_DiffNormal.isChecked():
            difficulty_filter.add('Normal')
        if not self.CH_DiffHard.isChecked():
            difficulty_filter.add('Hard')
        if not self.CH_DiffBrutal.isChecked():
            difficulty_filter.add('Brutal')
        if not self.CH_DiffBrutalPlus.isChecked():
            difficulty_filter = difficulty_filter.union({1, 2, 3, 4, 5, 6})

        region_filter = set()
        if not self.CH_Region_NA.isChecked():
            region_filter.add('NA')
        if not self.CH_Region_EU.isChecked():
            region_filter.add('EU')
        if not self.CH_Region_KR.isChecked():
            region_filter.add('KR')
        if not self.CH_Region_CN.isChecked():
            region_filter.add('CN')

        mindate = self.TM_FromDate.date().toPyDate().strftime('%Y%m%d%H%M%S')
        mindate = None if mindate == '20151110000000' else int(mindate)
        maxdate = self.TM_ToDate.date().toPyDate().strftime('%Y%m%d%H%M%S')
        maxdate = None if maxdate == '20301230000000' else int(maxdate)

        minlength = None if self.SP_MinGamelength.value(
        ) == 0 else self.SP_MinGamelength.value()
        maxLength = None if self.SP_MaxGamelength.value(
        ) == 0 else self.SP_MaxGamelength.value()

        include_both_main = True if self.CH_DualMain.isChecked() else False
        sub_15 = True if self.CH_Sub15.isChecked() else False
        over_15 = True if self.CH_Over15.isChecked() else False

        ### Analyse
        analysis = self.p.CAnalysis.analyse_replays(
            include_mutations=include_mutations,
            include_normal_games=include_normal_games,
            difficulty_filter=difficulty_filter,
            region_filter=region_filter,
            mindate=mindate,
            maxdate=maxdate,
            minlength=minlength,
            maxLength=maxLength,
            sub_15=sub_15,
            over_15=over_15,
            include_both_main=include_both_main)

        self.LA_GamesFound.setText(f"Games found: {analysis['games']}")

        ### Map stats

        # Delete buttons if not required
        for item in set(self.stats_maps_UI_dict.keys()):
            self.stats_maps_UI_dict[item].deleteLater()
            del self.stats_maps_UI_dict[item]

        # Sort maps
        sort_by = self.MapsComboBox.currentText()
        trans_dict = {
            'Frequency': 'frequency',
            'Wins': 'Victory',
            'Losses': 'Defeat',
            'Winrate': 'winrate',
            'Average time': 'average_victory_time',
            'Bonus': 'bonus'
        }
        trans_dict_reverse = {
            'Frequency': True,
            'Wins': True,
            'Losses': True,
            'Winrate': True,
            'Average time': False,
            'Bonus': True
        }

        if sort_by == 'Fastest time':
            analysis['MapData'] = {
                k: v
                for k, v in sorted(analysis['MapData'].items(),
                                   key=lambda x: x[1]['Fastest']['length'])
            }
        else:
            analysis['MapData'] = {
                k: v
                for k, v in sorted(analysis['MapData'].items(),
                                   key=lambda x: x[1][trans_dict[sort_by]],
                                   reverse=trans_dict_reverse[sort_by])
            }

        # Add map buttons & update the fastest map
        idx = 0
        for m in analysis['MapData']:
            idx += 1
            self.stats_maps_UI_dict[m] = MUI.MapEntry(
                self.GB_MapsOverview,
                idx * 25,
                m,
                analysis['MapData'][m]['Fastest']['length'],
                analysis['MapData'][m]['average_victory_time'],
                analysis['MapData'][m]['Victory'],
                analysis['MapData'][m]['Defeat'],
                analysis['MapData'][m]['frequency'],
                analysis['MapData'][m]['bonus'],
                bg=idx % 2 == 0)

            self.stats_maps_UI_dict[m].bt_button.clicked.connect(
                partial(self.map_link_update,
                        mapname=m,
                        fdict=analysis['MapData'][m]['Fastest']))

        # Try to show the last visible fastest map if it's there
        if hasattr(self, 'last_fastest_map'
                   ) and self.last_fastest_map in analysis['MapData'].keys():
            self.map_link_update(
                self.last_fastest_map,
                analysis['MapData'][self.last_fastest_map]['Fastest'])

        elif len(analysis['MapData']) > 0:
            for m in analysis['MapData']:
                self.map_link_update(m, analysis['MapData'][m]['Fastest'])
                break

        # Show/hide the fastest map accordingly
        if len(analysis['MapData']) == 0:
            self.QB_FastestMap.hide()
        else:
            self.QB_FastestMap.show()

        ### Difficulty stats & region stats
        if hasattr(self, 'stats_difficulty_UI_dict'):
            for item in set(self.stats_difficulty_UI_dict.keys()):
                self.stats_difficulty_UI_dict[item].deleteLater()
                del self.stats_difficulty_UI_dict[item]
        else:
            self.stats_difficulty_UI_dict = dict()

        difficulties = [
            'Casual', 'Normal', 'Hard', 'Brutal', 'B+1', 'B+2', 'B+3', 'B+4',
            'B+5', 'B+6'
        ]
        idx = 0
        AllDiff = {'Victory': 0, 'Defeat': 0}
        for difficulty in difficulties:
            if difficulty in analysis['DifficultyData']:
                line = True if idx + 1 == len(
                    analysis['DifficultyData']) else False
                self.stats_difficulty_UI_dict[difficulty] = MUI.DifficultyEntry(
                    difficulty.replace('B+', 'Brutal+'),
                    analysis['DifficultyData'][difficulty]['Victory'],
                    analysis['DifficultyData'][difficulty]['Defeat'],
                    f"{100*analysis['DifficultyData'][difficulty]['Winrate']:.0f}%",
                    50,
                    idx * 18 + 20,
                    bg=idx % 2,
                    parent=self.TAB_DifficultyRegions,
                    line=line)
                idx += 1
                AllDiff['Victory'] += analysis['DifficultyData'][difficulty][
                    'Victory']
                AllDiff['Defeat'] += analysis['DifficultyData'][difficulty][
                    'Defeat']

        AllDiff[
            'Winrate'] = f"{100*AllDiff['Victory']/(AllDiff['Victory'] + AllDiff['Defeat']):.0f}%" if (
                AllDiff['Victory'] + AllDiff['Defeat']) > 0 else '-'

        self.stats_difficulty_UI_dict['All'] = MUI.DifficultyEntry(
            'Σ',
            AllDiff['Victory'],
            AllDiff['Defeat'],
            AllDiff['Winrate'],
            50,
            idx * 18 + 23,
            parent=self.TAB_DifficultyRegions)

        # Region stats
        for item in set(self.stats_region_UI_dict.keys()):
            self.stats_region_UI_dict[item].deleteLater()
            del self.stats_region_UI_dict[item]

        for idx, region in enumerate(analysis['RegionData']):
            self.stats_region_UI_dict[region] = MUI.RegionStats(
                region,
                analysis['RegionData'][region],
                20 + idx * 18,
                bg=True if idx % 2 else False,
                parent=self.TAB_DifficultyRegions)

        ### Commander stats
        self.my_commander_analysis = analysis['CommanderData']
        self.my_commander_sort_update()

        ### Ally commander stats
        self.ally_commander_analysis = analysis['AllyCommanderData']
        self.ally_commander_sort_update()

        ### Unit stats
        if self.p.CAnalysis.full_analysis_finished:
            self.update_unit_stats(analysis['UnitData'])
Exemplo n.º 12
0
 def initialize_data(self, CAnalysis):
     for game in CAnalysis.get_last_replays(SM.settings['list_games']):
         self.game_UI_dict[game.file] = MUI.GameEntry(
             game, CAnalysis.main_handles, self.SC_GamesScrollAreaContent)
         self.SC_GamesScrollAreaContentLayout.addWidget(
             self.game_UI_dict[game.file].widget)
Exemplo n.º 13
0
    def __init__(self, parent, TabWidget):
        super().__init__()
        self.p = parent
        self.game_UI_dict = dict()

        # Scroll
        self.SC_GamesScrollArea = QtWidgets.QScrollArea(self)
        self.SC_GamesScrollArea.setGeometry(
            QtCore.QRect(0, 30,
                         TabWidget.frameGeometry().width() - 5,
                         TabWidget.frameGeometry().height() - 30))
        self.SC_GamesScrollArea.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.SC_GamesScrollArea.setFrameShadow(QtWidgets.QFrame.Plain)
        self.SC_GamesScrollArea.setWidgetResizable(True)

        self.SC_GamesScrollAreaContent = QtWidgets.QWidget()
        self.SC_GamesScrollAreaContent.setGeometry(QtCore.QRect(
            0, 0, 931, 561))
        self.SC_GamesScrollAreaContentLayout = QtWidgets.QVBoxLayout()
        self.SC_GamesScrollAreaContentLayout.setAlignment(QtCore.Qt.AlignTop)
        self.SC_GamesScrollAreaContentLayout.setContentsMargins(10, 0, 0, 0)

        self.LA_Games_Wait = QtWidgets.QLabel(self.SC_GamesScrollAreaContent)
        self.LA_Games_Wait.setGeometry(
            QtCore.QRect(0, 0, self.SC_GamesScrollAreaContent.width(),
                         self.SC_GamesScrollAreaContent.height()))
        self.LA_Games_Wait.setText(
            '<b>Please wait. This can take few minutes the first time.<br>Analyzing your replays.</b>'
        )
        self.LA_Games_Wait.setAlignment(QtCore.Qt.AlignVCenter
                                        | QtCore.Qt.AlignCenter)

        # Heading
        self.WD_RecentGamesHeading = QtWidgets.QWidget(self)
        self.WD_RecentGamesHeading.setGeometry(QtCore.QRect(0, 0, 990, 32))
        self.WD_RecentGamesHeading.setStyleSheet("font-weight: bold")
        self.WD_RecentGamesHeading.setAutoFillBackground(True)
        self.WD_RecentGamesHeading.setBackgroundRole(QtGui.QPalette.Background)

        self.LA_Difficulty = QtWidgets.QLabel(self.WD_RecentGamesHeading)
        self.LA_Difficulty.setGeometry(QtCore.QRect(580, 0, 81, 31))
        self.LA_Difficulty.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Difficulty.setText("Difficulty")

        self.LA_Player2 = QtWidgets.QLabel(self.WD_RecentGamesHeading)
        self.LA_Player2.setGeometry(QtCore.QRect(305, 0, 200, 31))
        self.LA_Player2.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Player2.setText("Player 2")

        self.LA_Enemy = QtWidgets.QLabel(self.WD_RecentGamesHeading)
        self.LA_Enemy.setGeometry(QtCore.QRect(485, 0, 41, 31))
        self.LA_Enemy.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Enemy.setText("Enemy")

        self.LA_Length = QtWidgets.QLabel(self.WD_RecentGamesHeading)
        self.LA_Length.setGeometry(QtCore.QRect(525, 0, 71, 31))
        self.LA_Length.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Length.setText("Length")

        self.LA_Map = QtWidgets.QLabel(self.WD_RecentGamesHeading)
        self.LA_Map.setGeometry(QtCore.QRect(30, 0, 125, 31))
        self.LA_Map.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft
                                 | QtCore.Qt.AlignVCenter)
        self.LA_Map.setText("Map")

        self.LA_Player1 = QtWidgets.QLabel(self.WD_RecentGamesHeading)
        self.LA_Player1.setGeometry(QtCore.QRect(170, 0, 200, 31))
        self.LA_Player1.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Player1.setText("Player 1")

        self.LA_Result = QtWidgets.QLabel(self.WD_RecentGamesHeading)
        self.LA_Result.setGeometry(QtCore.QRect(145, 0, 50, 31))
        self.LA_Result.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Result.setText("Result")

        self.LA_Date = QtWidgets.QLabel(self.WD_RecentGamesHeading)
        self.LA_Date.setGeometry(QtCore.QRect(655, 0, 101, 31))
        self.LA_Date.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Date.setText("Time")

        self.GameTabLine = MUI.Cline(self.WD_RecentGamesHeading)
        self.GameTabLine.setGeometry(QtCore.QRect(20, 30, 921, 1))

        self.ed_games_search = QtWidgets.QLineEdit(self.WD_RecentGamesHeading)
        self.ed_games_search.setGeometry(QtCore.QRect(740, 5, 160, 20))
        self.ed_games_search.setAlignment(QtCore.Qt.AlignCenter)
        self.ed_games_search.setStyleSheet("font-weight: normal")
        self.ed_games_search.setPlaceholderText("Search")
        self.ed_games_search.setToolTip(
            "Search for any data in a game. Separate words by spaces.")

        self.bt_games_search = QtWidgets.QPushButton(
            self.WD_RecentGamesHeading)
        self.bt_games_search.setGeometry(QtCore.QRect(910, 3, 25, 25))
        self.bt_games_search.setStyleSheet("font-weight: normal")
        self.bt_games_search.setText("GO")
        self.bt_games_search.clicked.connect(self.search_games)
        self.bt_games_search.setShortcut("Return")

        # Finishing
        self.SC_GamesScrollAreaContent.setLayout(
            self.SC_GamesScrollAreaContentLayout)
        self.SC_GamesScrollArea.setWidget(self.SC_GamesScrollAreaContent)
Exemplo n.º 14
0
    def __init__(self, parent, TabWidget):
        super().__init__()
        self.p = parent
        self.filter_players_running = False
        self.player_winrate_UI_dict = dict()
        self.last_ally_player = None

        # Controls
        self.FR_Winrate_Controls = QtWidgets.QFrame(self)
        self.FR_Winrate_Controls.setGeometry(
            QtCore.QRect(0, 550,
                         TabWidget.frameGeometry().width(), 50))
        self.FR_Winrate_Controls.setAutoFillBackground(True)
        self.FR_Winrate_Controls.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.FR_Winrate_Controls.setFrameShadow(QtWidgets.QFrame.Raised)

        # Search
        self.ED_Winrate_Search = QtWidgets.QLineEdit(self.FR_Winrate_Controls)
        self.ED_Winrate_Search.setGeometry(QtCore.QRect(65, 7, 610, 20))
        self.ED_Winrate_Search.setAlignment(QtCore.Qt.AlignCenter)
        self.ED_Winrate_Search.setPlaceholderText(
            "Search for player name or note")
        self.ED_Winrate_Search.textChanged.connect(self.filter_players)

        # Top 50
        self.CH_OnlyTop50 = QtWidgets.QCheckBox(self.FR_Winrate_Controls)
        self.CH_OnlyTop50.setGeometry(QtCore.QRect(700, 8, 200, 17))
        self.CH_OnlyTop50.setText("Show max 50 players")
        self.CH_OnlyTop50.setToolTip(
            "Unchecking this will likely cause lag. All players are always searched no matter the status of this setting."
        )
        self.CH_OnlyTop50.setChecked(True)
        self.CH_OnlyTop50.stateChanged.connect(self.filter_players)

        # Scroll
        self.SC_PlayersScrollArea = QtWidgets.QScrollArea(self)
        self.SC_PlayersScrollArea.setGeometry(
            QtCore.QRect(0, 31,
                         TabWidget.frameGeometry().width() - 5,
                         TabWidget.frameGeometry().height() - 91))
        self.SC_PlayersScrollArea.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.SC_PlayersScrollArea.setFrameShadow(QtWidgets.QFrame.Plain)
        self.SC_PlayersScrollArea.setWidgetResizable(True)

        self.SC_PlayersScrollAreaContents = QtWidgets.QWidget()
        self.SC_PlayersScrollAreaContents.setGeometry(
            QtCore.QRect(0, 31, 961, 530))
        self.SC_PlayersScrollAreaContentsLayout = QtWidgets.QVBoxLayout()
        self.SC_PlayersScrollAreaContentsLayout.setAlignment(
            QtCore.Qt.AlignTop)
        self.SC_PlayersScrollAreaContentsLayout.setContentsMargins(10, 0, 0, 0)
        self.SC_PlayersScrollAreaContentsLayout.setSpacing(0)

        # Heading
        self.WD_WinratesHeading = QtWidgets.QWidget(self)
        self.WD_WinratesHeading.setGeometry(QtCore.QRect(0, 0, 981, 31))
        self.WD_WinratesHeading.setStyleSheet("font-weight:bold")
        self.WD_WinratesHeading.setAutoFillBackground(True)
        self.WD_WinratesHeading.setBackgroundRole(QtGui.QPalette.Background)

        self.LA_Name = QtWidgets.QLabel(self.WD_WinratesHeading)
        self.LA_Name.setGeometry(QtCore.QRect(30, 0, 41, 31))
        self.LA_Name.setText("Name")

        self.LA_Wins = QtWidgets.QLabel(self.WD_WinratesHeading)
        self.LA_Wins.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Wins.setGeometry(QtCore.QRect(145, 0, 50, 31))
        self.LA_Wins.setText("▼ Wins")

        self.LA_Losses = QtWidgets.QLabel(self.WD_WinratesHeading)
        self.LA_Losses.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Losses.setGeometry(QtCore.QRect(215, 0, 45, 31))
        self.LA_Losses.setText("Losses")

        self.LA_Winrate = QtWidgets.QLabel(self.WD_WinratesHeading)
        self.LA_Winrate.setGeometry(QtCore.QRect(270, 0, 51, 31))
        self.LA_Winrate.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Winrate.setText("Winrate")

        self.LA_PL_APM = QtWidgets.QLabel(self.WD_WinratesHeading)
        self.LA_PL_APM.setGeometry(QtCore.QRect(325, 0, 51, 31))
        self.LA_PL_APM.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_PL_APM.setText("APM")
        self.LA_PL_APM.setToolTip("Median APM")

        self.LA_PL_Kills = QtWidgets.QLabel(self.WD_WinratesHeading)
        self.LA_PL_Kills.setGeometry(QtCore.QRect(380, 0, 51, 31))
        self.LA_PL_Kills.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_PL_Kills.setText("Kills")
        self.LA_PL_Kills.setToolTip("Median percent of kills")

        self.LA_PL_Commander = QtWidgets.QLabel(self.WD_WinratesHeading)
        self.LA_PL_Commander.setGeometry(QtCore.QRect(430, 0, 81, 31))
        self.LA_PL_Commander.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_PL_Commander.setText("#1 Com")
        self.LA_PL_Commander.setToolTip("The most played commander")

        self.LA_PL_Frequency = QtWidgets.QLabel(self.WD_WinratesHeading)
        self.LA_PL_Frequency.setGeometry(QtCore.QRect(495, 0, 81, 31))
        self.LA_PL_Frequency.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_PL_Frequency.setText("Frequency")
        self.LA_PL_Frequency.setToolTip("The most played commander frequency")

        self.LA_Note = QtWidgets.QLabel(self.WD_WinratesHeading)
        self.LA_Note.setGeometry(QtCore.QRect(580, 0, 300, 31))
        self.LA_Note.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Note.setText("Player note (displayed together with winrates)")

        self.PlayerTabLine = MUI.Cline(self.WD_WinratesHeading)
        self.PlayerTabLine.setGeometry(QtCore.QRect(20, 30, 921, 1))

        # Wait
        self.LA_Winrates_Wait = QtWidgets.QLabel(self)
        self.LA_Winrates_Wait.setGeometry(
            QtCore.QRect(0, 0, self.SC_PlayersScrollAreaContents.width(),
                         self.SC_PlayersScrollAreaContents.height()))
        self.LA_Winrates_Wait.setText(
            '<b>Please wait. This can take few minutes the first time.<br>Analyzing your replays.</b>'
        )
        self.LA_Winrates_Wait.setAlignment(QtCore.Qt.AlignVCenter
                                           | QtCore.Qt.AlignCenter)
Exemplo n.º 15
0
    def __init__(self, parent, APPVERSION):
        super().__init__()
        self.p = parent
        ch_distance = 20

        # Start with Windows
        self.CH_StartWithWindows = QtWidgets.QCheckBox(self)
        self.CH_StartWithWindows.setGeometry(
            QtCore.QRect(20, ch_distance, 230, 17))
        self.CH_StartWithWindows.setText("Start with Windows")
        self.CH_StartWithWindows.setToolTip(
            "The app will start automatically with Windows")

        # Start minimized
        self.CH_StartMinimized = QtWidgets.QCheckBox(self)
        self.CH_StartMinimized.setGeometry(
            QtCore.QRect(20, 2 * ch_distance, 230, 17))
        self.CH_StartMinimized.setText("Start minimized")
        self.CH_StartMinimized.setToolTip("The app will start minimized")

        # Enable logging
        self.CH_EnableLogging = QtWidgets.QCheckBox(self)
        self.CH_EnableLogging.setGeometry(
            QtCore.QRect(20, 4 * ch_distance, 230, 17))
        self.CH_EnableLogging.setText("Enable logging")
        self.CH_EnableLogging.setToolTip(
            f"App logs will be saved into a text file")

        # Show session hidden
        self.CH_ShowSession = QtWidgets.QCheckBox(self)
        self.CH_ShowSession.setGeometry(
            QtCore.QRect(20, 5 * ch_distance, 300, 17))
        self.CH_ShowSession.setText("Show session stats")
        self.CH_ShowSession.setToolTip(
            "Shows how many games you played and won in the current session on the overlay"
        )

        # Show player winrate and notes
        self.CH_ShowPlayerWinrates = QtWidgets.QCheckBox(self)
        self.CH_ShowPlayerWinrates.setGeometry(
            QtCore.QRect(20, 6 * ch_distance, 230, 17))
        self.CH_ShowPlayerWinrates.setText("Show player winrates and notes")
        self.CH_ShowPlayerWinrates.setToolTip(
            "The number of games and winrate you had with your ally will be shown when a game starts.\nPlayer note will show as well if specified. Requires restart to enable."
        )

        # Mnimized when clicked
        self.CH_MinimizeToTray = QtWidgets.QCheckBox(self)
        self.CH_MinimizeToTray.setGeometry(
            QtCore.QRect(20, 3 * ch_distance, 300, 17))
        self.CH_MinimizeToTray.setText("Minimize to tray")
        self.CH_MinimizeToTray.setToolTip(
            "On closing the app will minimize to tray. The app can be closed there."
        )

        # Duration
        self.SP_Duration = QtWidgets.QSpinBox(self)
        self.SP_Duration.setGeometry(QtCore.QRect(250, 20, 42, 22))

        self.LA_Duration = QtWidgets.QLabel(self)
        self.LA_Duration.setGeometry(QtCore.QRect(300, 20, 191, 21))
        self.LA_Duration.setText("Duration")
        self.LA_Duration.setToolTip(
            "How long the overlay will show after a new game is analysed.")

        # Monitor
        self.SP_Monitor = QtWidgets.QSpinBox(self)
        self.SP_Monitor.setGeometry(QtCore.QRect(360, 20, 42, 22))
        self.SP_Monitor.setMinimum(1)
        self.SP_Monitor.setToolTip(
            "Determines on which monitor the overlay will be shown")

        self.LA_Monitor = QtWidgets.QLabel(self)
        self.LA_Monitor.setGeometry(QtCore.QRect(410, 20, 47, 20))
        self.LA_Monitor.setText("Monitor")
        self.LA_Monitor.setToolTip(
            "Determines on which monitor the overlay will be shown")

        # Charts
        self.CH_ShowCharts = QtWidgets.QCheckBox(self)
        self.CH_ShowCharts.setGeometry(
            QtCore.QRect(250, 3 * ch_distance, 300, 17))
        self.CH_ShowCharts.setText("Show charts")
        self.CH_ShowCharts.setToolTip("Show charts on overlay")
        self.CH_ShowCharts.clicked.connect(self.p.show_charts)

        # Dark theme
        self.CH_DarkTheme = QtWidgets.QCheckBox(self)
        self.CH_DarkTheme.setGeometry(
            QtCore.QRect(250, 4 * ch_distance, 300, 17))
        self.CH_DarkTheme.setText("Dark theme")
        self.CH_DarkTheme.setToolTip("Enables dark theme. Requires restart!")
        self.CH_DarkTheme.stateChanged.connect(self.p.change_theme)

        # Fast expand
        self.CH_FastExpand = QtWidgets.QCheckBox(self)
        self.CH_FastExpand.setGeometry(
            QtCore.QRect(250, 5 * ch_distance, 300, 17))
        self.CH_FastExpand.setText("Fast expand hints")
        self.CH_FastExpand.setToolTip(
            "Show fast expand hint dialogue when a new game starts.\n"
            f"maps: {', '.join(FastExpandSelector.valid_maps)}\n"
            f"commanders: {', '.join(FastExpandSelector.valid_commanders)}")

        # Force hidden
        self.CH_ForceHideOverlay = QtWidgets.QCheckBox(self)
        self.CH_ForceHideOverlay.setGeometry(
            QtCore.QRect(250, 6 * ch_distance, 300, 17))
        self.CH_ForceHideOverlay.setText("Don\'t show overlay on-screen")
        self.CH_ForceHideOverlay.setToolTip(
            "The overlay won't show directly on your screen. You can use this setting\nfor example when it's meant to be visible only on stream."
        )

        # Replay folder
        self.LA_AccountFolder = QtWidgets.QLabel(self)
        self.LA_AccountFolder.setGeometry(QtCore.QRect(520, 15, 350, 16))
        self.LA_AccountFolder.setText(
            "Change locations of StarCraft II account folder and screenshot folder"
        )

        self.BT_ChooseFolder = QtWidgets.QPushButton(self)
        self.BT_ChooseFolder.setGeometry(QtCore.QRect(520, 36, 150, 25))
        self.BT_ChooseFolder.setText('Account folder')
        self.BT_ChooseFolder.setToolTip(
            'Choose your account folder.\nThis is usually not necessary and the app will find its location automatically.'
        )
        self.BT_ChooseFolder.clicked.connect(self.p.findReplayFolder)

        self.LA_CurrentReplayFolder = QtWidgets.QLabel(self)
        self.LA_CurrentReplayFolder.setEnabled(False)
        self.LA_CurrentReplayFolder.setGeometry(QtCore.QRect(520, 53, 400, 31))

        # Screenshot folder
        self.BT_ScreenshotLocation = QtWidgets.QPushButton(self)
        self.BT_ScreenshotLocation.setGeometry(QtCore.QRect(520, 90, 150, 25))
        self.BT_ScreenshotLocation.setText('Screenshot folder')
        self.BT_ScreenshotLocation.setToolTip(
            'Choose the folder where screenshots are saved')
        self.BT_ScreenshotLocation.clicked.connect(
            self.p.chooseScreenshotFolder)

        self.LA_ScreenshotLocation = QtWidgets.QLabel(self)
        self.LA_ScreenshotLocation.setEnabled(False)
        self.LA_ScreenshotLocation.setGeometry(QtCore.QRect(520, 108, 400, 31))

        # Info label
        self.LA_InfoLabel = QtWidgets.QLabel(self)
        self.LA_InfoLabel.setGeometry(QtCore.QRect(20, 560, 800, 20))

        # Apply
        self.BT_MainApply = QtWidgets.QPushButton(self)
        self.BT_MainApply.setGeometry(QtCore.QRect(867, 400, 75, 25))
        self.BT_MainApply.setText('Apply')
        self.BT_MainApply.clicked.connect(self.p.saveSettings)

        # Reset
        self.BT_MainReset = QtWidgets.QPushButton(self)
        self.BT_MainReset.setGeometry(QtCore.QRect(785, 400, 75, 25))
        self.BT_MainReset.setText('Reset')
        self.BT_MainReset.clicked.connect(self.p.resetSettings)
        self.BT_MainReset.setToolTip(
            "Resets all settings on this tab apart from login for starcraft2coop.com"
        )

        # Screenshot
        self.BT_Screenshot = QtWidgets.QPushButton(self)
        self.BT_Screenshot.setGeometry(QtCore.QRect(19, 400, 157, 40))
        self.BT_Screenshot.setText('Overlay screenshot')
        self.BT_Screenshot.setToolTip(
            'Take screenshot of the overlay and save it on your desktop or chosen location'
        )
        self.BT_Screenshot.clicked.connect(self.p.save_screenshot)

        ### Hotkey frame
        self.FR_HotkeyFrame = QtWidgets.QFrame(self)
        self.FR_HotkeyFrame.setGeometry(QtCore.QRect(20, 170, 411, 211))
        self.FR_HotkeyFrame.setAutoFillBackground(True)
        self.FR_HotkeyFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.FR_HotkeyFrame.setFrameShadow(QtWidgets.QFrame.Plain)

        # Label
        self.LA_Hotkeys = QtWidgets.QLabel(self.FR_HotkeyFrame)
        self.LA_Hotkeys.setGeometry(QtCore.QRect(0, 10, 411, 20))
        self.LA_Hotkeys.setStyleSheet("font-weight: bold")
        self.LA_Hotkeys.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_Hotkeys.setText("Hotkeys")

        # Show/hide
        self.BT_ShowHide = QtWidgets.QPushButton(self.FR_HotkeyFrame)
        self.BT_ShowHide.setGeometry(QtCore.QRect(19, 50, 115, 25))
        self.BT_ShowHide.setText("Show / Hide")
        self.BT_ShowHide.clicked.connect(MF.keyboard_SHOWHIDE)

        self.KEY_ShowHide = MUI.CustomKeySequenceEdit(self.FR_HotkeyFrame)
        self.KEY_ShowHide.setGeometry(QtCore.QRect(20, 80, 113, 20))
        self.KEY_ShowHide.setToolTip(
            'The key for both showing and hiding the overlay')
        self.KEY_ShowHide.keySequenceChanged.connect(self.p.hotkey_changed)

        # Show
        self.BT_Show = QtWidgets.QPushButton(self.FR_HotkeyFrame)
        self.BT_Show.setGeometry(QtCore.QRect(149, 50, 115, 25))
        self.BT_Show.setText("Show")
        self.BT_Show.clicked.connect(MF.keyboard_SHOW)

        self.KEY_Show = MUI.CustomKeySequenceEdit(self.FR_HotkeyFrame)
        self.KEY_Show.setGeometry(QtCore.QRect(150, 80, 113, 20))
        self.KEY_Show.setToolTip('The key for just showing the overlay')
        self.KEY_Show.keySequenceChanged.connect(self.p.hotkey_changed)

        # Hide
        self.BT_Hide = QtWidgets.QPushButton(self.FR_HotkeyFrame)
        self.BT_Hide.setGeometry(QtCore.QRect(279, 50, 115, 25))
        self.BT_Hide.setText("Hide")
        self.BT_Hide.clicked.connect(MF.keyboard_HIDE)

        self.KEY_Hide = MUI.CustomKeySequenceEdit(self.FR_HotkeyFrame)
        self.KEY_Hide.setGeometry(QtCore.QRect(280, 80, 113, 20))
        self.KEY_Hide.setToolTip('The key for just hiding the overlay')
        self.KEY_Hide.keySequenceChanged.connect(self.p.hotkey_changed)

        # Newer
        self.BT_Newer = QtWidgets.QPushButton(self.FR_HotkeyFrame)
        self.BT_Newer.setGeometry(QtCore.QRect(19, 120, 115, 25))
        self.BT_Newer.setText("Show newer replay")
        self.BT_Newer.clicked.connect(MF.keyboard_NEWER)

        self.KEY_Newer = MUI.CustomKeySequenceEdit(self.FR_HotkeyFrame)
        self.KEY_Newer.setGeometry(QtCore.QRect(20, 150, 113, 20))
        self.KEY_Newer.setToolTip(
            'The key for showing a newer replay than is currently displayed')
        self.KEY_Newer.keySequenceChanged.connect(self.p.hotkey_changed)

        # Older
        self.BT_Older = QtWidgets.QPushButton(self.FR_HotkeyFrame)
        self.BT_Older.setGeometry(QtCore.QRect(149, 120, 115, 25))
        self.BT_Older.setText("Show older replay")
        self.BT_Older.clicked.connect(MF.keyboard_OLDER)

        self.KEY_Older = MUI.CustomKeySequenceEdit(self.FR_HotkeyFrame)
        self.KEY_Older.setGeometry(QtCore.QRect(150, 150, 113, 20))
        self.KEY_Older.setToolTip(
            'The key for showing an older replay than is currently displayed')
        self.KEY_Older.keySequenceChanged.connect(self.p.hotkey_changed)

        # Winrates
        self.BT_Winrates = QtWidgets.QPushButton(self.FR_HotkeyFrame)
        self.BT_Winrates.setGeometry(QtCore.QRect(279, 120, 115, 25))
        self.BT_Winrates.setText("Show player info")
        self.BT_Winrates.clicked.connect(MF.keyboard_PLAYERWINRATES)

        self.KEY_Winrates = MUI.CustomKeySequenceEdit(self.FR_HotkeyFrame)
        self.KEY_Winrates.setGeometry(QtCore.QRect(280, 150, 113, 20))
        self.KEY_Winrates.setToolTip(
            'The key for showing the last player winrates and notes')
        self.KEY_Winrates.keySequenceChanged.connect(self.p.hotkey_changed)

        # Colors
        self.FR_CustomizeColors = QtWidgets.QFrame(self)
        self.FR_CustomizeColors.setGeometry(QtCore.QRect(445, 170, 241, 211))
        self.FR_CustomizeColors.setAutoFillBackground(True)
        self.FR_CustomizeColors.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.FR_CustomizeColors.setFrameShadow(QtWidgets.QFrame.Plain)

        # Customize colors
        self.LA_CustomizeColors = QtWidgets.QLabel(self.FR_CustomizeColors)
        self.LA_CustomizeColors.setGeometry(QtCore.QRect(0, 10, 241, 20))
        self.LA_CustomizeColors.setStyleSheet("font-weight: bold")
        self.LA_CustomizeColors.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_CustomizeColors.setText("Customize colors")

        # Note
        self.LA_More = QtWidgets.QLabel(self.FR_CustomizeColors)
        self.LA_More.setEnabled(False)
        self.LA_More.setGeometry(QtCore.QRect(0, 19, 241, 31))
        self.LA_More.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_More.setText("more via editing custom.css")

        color_x_offset = 50
        color_height = 20
        color_width = 140

        self.LA_P1 = QtWidgets.QPushButton(self.FR_CustomizeColors)
        self.LA_P1.setGeometry(
            QtCore.QRect(color_x_offset, 70, color_width, color_height))
        self.LA_P1.clicked.connect(lambda: self.openColorDialog(self.LA_P1))

        self.LA_P2 = QtWidgets.QPushButton(self.FR_CustomizeColors)
        self.LA_P2.setGeometry(
            QtCore.QRect(color_x_offset, 100, color_width, color_height))
        self.LA_P2.clicked.connect(lambda: self.openColorDialog(self.LA_P2))

        self.LA_Amon = QtWidgets.QPushButton(self.FR_CustomizeColors)
        self.LA_Amon.setGeometry(
            QtCore.QRect(color_x_offset, 130, color_width, color_height))
        self.LA_Amon.clicked.connect(
            lambda: self.openColorDialog(self.LA_Amon))

        self.LA_Mastery = QtWidgets.QPushButton(self.FR_CustomizeColors)
        self.LA_Mastery.setGeometry(
            QtCore.QRect(color_x_offset, 160, color_width, color_height))
        self.LA_Mastery.clicked.connect(
            lambda: self.openColorDialog(self.LA_Mastery))

        # Aom
        self.FR_Aom = QtWidgets.QFrame(self)
        self.FR_Aom.setGeometry(QtCore.QRect(700, 170, 241, 211))
        self.FR_Aom.setAutoFillBackground(True)
        self.FR_Aom.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.FR_Aom.setFrameShadow(QtWidgets.QFrame.Plain)

        self.LA_AomPage = QtWidgets.QLabel(self.FR_Aom)
        self.LA_AomPage.setGeometry(QtCore.QRect(0, 10, 241, 20))
        self.LA_AomPage.setStyleSheet("font-weight: bold")
        self.LA_AomPage.setAlignment(QtCore.Qt.AlignCenter)
        self.LA_AomPage.setText("Settings for starcraft2coop.com")

        self.ED_AomAccount = QtWidgets.QLineEdit(self.FR_Aom)
        self.ED_AomAccount.setGeometry(QtCore.QRect(62, 70, 121, 20))
        self.ED_AomAccount.setAlignment(QtCore.Qt.AlignCenter)
        self.ED_AomAccount.setPlaceholderText("account name")

        self.ED_AomSecretKey = QtWidgets.QLineEdit(self.FR_Aom)
        self.ED_AomSecretKey.setGeometry(QtCore.QRect(62, 100, 121, 20))
        self.ED_AomSecretKey.setAlignment(QtCore.Qt.AlignCenter)
        self.ED_AomSecretKey.setPlaceholderText("secret key")
        self.ED_AomSecretKey.setEchoMode(
            QtWidgets.QLineEdit.PasswordEchoOnEdit)

        self.BT_AomTest = QtWidgets.QPushButton(self.FR_Aom)
        self.BT_AomTest.setGeometry(QtCore.QRect(75, 160, 85, 25))
        self.BT_AomTest.clicked.connect(self.validateAOM)
        self.BT_AomTest.setText("Verify")
        self.BT_AomTest.setToolTip(
            "Test if the combination of the account name and the secret key is valid"
        )

        # Manual parse
        self.BT_ManualParse = QtWidgets.QPushButton(self)
        self.BT_ManualParse.setGeometry(QtCore.QRect(185, 400, 157, 40))
        self.BT_ManualParse.setText("Parse replay")
        self.BT_ManualParse.setToolTip(
            "Parse selected replay, show it on the overlay, and save data to a json file."
        )
        self.BT_ManualParse.clicked.connect(self.parse_replay)

        # Paypal
        x = 835
        y = 520
        self.IMG_Front_Donate = QtWidgets.QLabel(self)
        self.IMG_Front_Donate.setGeometry(QtCore.QRect(835, y, 145, 50))
        self.IMG_Front_Donate.setPixmap(
            QtGui.QPixmap(innerPath("src/paypal.png")))
        self.IMG_Front_Donate.setGraphicsEffect(MUI.get_shadow())

        self.BT_Front_Donate = QtWidgets.QPushButton(self)
        self.BT_Front_Donate.setGeometry(QtCore.QRect(x - 5, y, 140, 50))
        self.BT_Front_Donate.clicked.connect(self.paypal_clicked)
        self.BT_Front_Donate.setStyleSheet(
            "QPushButton {border: 0px; background: transparent}")
        self.BT_Front_Donate.setToolTip(f'Donate to support this app')

        # Version
        self.LA_Version = QtWidgets.QLabel(self)
        self.LA_Version.setGeometry(QtCore.QRect(825, 560, 141, 20))
        self.LA_Version.setAlignment(QtCore.Qt.AlignBottom
                                     | QtCore.Qt.AlignRight
                                     | QtCore.Qt.AlignTrailing)
        self.LA_Version.setText(
            f"The app is up to date (v{str(APPVERSION)[0]}.{str(APPVERSION)[1:]})"
        )
        self.LA_Version.setEnabled(False)