Beispiel #1
0
class Ui_MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowIcon(QIcon(resource_path('icon.ico')))
        self.setFixedSize(540, 470)

    def setupUi(self):
        self.centralwidget = QWidget(self)
        with open(resource_path('style.css'), 'r') as file:
            self.centralwidget.setStyleSheet(file.read())
        self.appswidget = QWidget(self.centralwidget)
        self.appswidget.setGeometry(50, 0, 490, 470)
        self.appswidget.setProperty('class', 'appswidget')
        self.sidebar = QFrame(self.centralwidget)
        self.sidebar.setFrameShape(QFrame.StyledPanel)
        self.sidebar.setGeometry(0, 0, 50, 470)
        self.sidebar.setProperty('class', 'sidebar')

        self.refresh_btn = QPushButton(self.sidebar)
        self.refresh_btn.setGeometry(QRect(0, 0, 51, 51))
        self.refresh_btn.setProperty('class', 'sidebar_btns')
        self.refresh_btn.setIcon(QIcon(':/icon/refresh_icon.png'))
        self.refresh_btn.setIconSize(QSize(24, 24))
        self.refresh_bind = QShortcut(QKeySequence('Ctrl+R'), self)

        self.store_btn = QPushButton(self.sidebar)
        self.store_btn.setGeometry(QRect(0, 51, 51, 51))
        self.store_btn.setProperty('class', 'sidebar_btns')
        self.store_btn.setIcon(QIcon(':/icon/store_icon.png'))
        self.store_btn.setIconSize(QSize(24, 24))
        self.store_bind = QShortcut(QKeySequence('Ctrl+S'), self)

        self.homepage_btn = QPushButton(self.sidebar)
        self.homepage_btn.setGeometry(QRect(0, 102, 51, 51))
        self.homepage_btn.setProperty('class', 'sidebar_btns')
        self.homepage_btn.setIcon(QIcon(':/icon/github_icon.png'))
        self.homepage_btn.setIconSize(QSize(24, 24))
        self.homepage_bind = QShortcut(QKeySequence('Ctrl+G'), self)

        self.about_btn = QPushButton(self.sidebar)
        self.about_btn.setGeometry(QRect(0, 153, 51, 51))
        self.about_btn.setProperty('class', 'sidebar_btns')
        self.about_btn.setIcon(QIcon(':/icon/about_icon.png'))
        self.about_btn.setIconSize(QSize(24, 24))
        self.about_bind = QShortcut(QKeySequence('Ctrl+A'), self)

        self.quit_btn = QPushButton(self.sidebar)
        self.quit_btn.setGeometry(QRect(0, 420, 51, 51))
        self.quit_btn.setProperty('class', 'sidebar_btns_quit')
        self.quit_btn.setIcon(QIcon(':/icon/quit_icon.png'))
        self.quit_btn.setIconSize(QSize(24, 24))
        self.quit_bind = QShortcut(QKeySequence('Ctrl+Q'), self)

        self.font = QFont()
        self.font.setPointSize(8)
        self.font.setStyleStrategy(QFont.PreferAntialias)

        self.label_refresh = QLabel(self.appswidget)
        self.label_refresh.setFont(self.font)
        self.label_refresh.setGeometry(QRect(20, 10, 441, 15))

        self.label_info = QLabel(self.appswidget)
        self.label_info.setFont(self.font)
        self.label_info.setGeometry(QRect(20, 10, 441, 30))

        self.progressbar = QProgressBar(self.appswidget)
        self.progressbar.setGeometry(QRect(20, 30, 441, 20))

        self.layout_widget_checkboxes = QWidget(self.appswidget)
        self.layout_widget_checkboxes.setGeometry(QRect(20, 55, 155, 311))
        self.layout_checkboxes = QVBoxLayout(self.layout_widget_checkboxes)
        self.layout_checkboxes.setContentsMargins(0, 0, 0, 0)

        self.layout_widget_checkboxes_2 = QWidget(self.appswidget)
        self.layout_widget_checkboxes_2.setGeometry(QRect(175, 55, 155, 311))
        self.layout_checkboxes_2 = QVBoxLayout(self.layout_widget_checkboxes_2)
        self.layout_checkboxes_2.setContentsMargins(0, 0, 0, 0)

        self.layout_widget_checkboxes_3 = QWidget(self.appswidget)
        self.layout_widget_checkboxes_3.setGeometry(QRect(330, 55, 155, 311))
        self.layout_checkboxes_3 = QVBoxLayout(self.layout_widget_checkboxes_3)
        self.layout_checkboxes_3.setContentsMargins(0, 0, 0, 0)

        self.layout_widget_labels = QWidget(self.appswidget)
        self.layout_widget_labels.setGeometry(QRect(20, 390, 350, 16))
        self.layout_labels = QHBoxLayout(self.layout_widget_labels)
        self.layout_labels.setContentsMargins(0, 0, 0, 0)
        self.label_space = QLabel(self.appswidget)
        self.label_space.setFont(self.font)
        self.layout_labels.addWidget(self.label_space)
        self.label_size = QLabel(self.appswidget)
        self.label_size.setFont(self.font)
        self.layout_labels.addWidget(self.label_size)

        self.layout_widget_buttons = QWidget(self.appswidget)
        self.layout_widget_buttons.setGeometry(QRect(20, 420, 454, 31))
        self.layout_buttons = QHBoxLayout(self.layout_widget_buttons)
        self.layout_buttons.setContentsMargins(0, 0, 0, 0)
        self.button_select_all = QPushButton(self.layout_widget_buttons)
        self.button_select_all.setIcon(QIcon(':/icon/check_icon.png'))
        self.button_select_all.setIconSize(QSize(18, 18))
        self.button_select_all.setLayoutDirection(Qt.RightToLeft)
        self.layout_buttons.addWidget(self.button_select_all)
        self.button_select_all.setMinimumSize(100, 30)
        self.button_select_all.setProperty('class', 'Aqua')
        self.button_deselect_all = QPushButton(self.layout_widget_buttons)
        self.button_deselect_all.setIcon(QIcon(':/icon/cancel_icon.png'))
        self.button_deselect_all.setIconSize(QSize(18, 18))
        self.button_deselect_all.setLayoutDirection(Qt.RightToLeft)
        self.layout_buttons.addWidget(self.button_deselect_all)
        self.button_deselect_all.setMinimumSize(100, 30)
        self.button_deselect_all.setProperty('class', 'Aqua')
        self.layout_buttons.addStretch()
        self.button_uninstall = QPushButton(self.layout_widget_buttons)
        self.button_uninstall.setIcon(QIcon(':/icon/trash_icon.png'))
        self.button_uninstall.setIconSize(QSize(18, 18))
        self.button_uninstall.setLayoutDirection(Qt.RightToLeft)
        self.layout_buttons.addWidget(self.button_uninstall)
        self.button_uninstall.setMinimumSize(100, 30)
        self.button_uninstall.setProperty('class', 'Grapefruit')

        self.setCentralWidget(self.centralwidget)
        self.retranslateUi()
        QMetaObject.connectSlotsByName(self)

    def retranslateUi(self):
        QToolTip.setFont(self.font)

        self.setWindowTitle(QCoreApplication.translate("Title", "PyDebloatX"))
        self.label_info.setText(QCoreApplication.translate("Label", ""))

        self.app_name_list = list(
            (  # Convert tuple to list, because lupdate ignores initial lists
                QCoreApplication.translate("AppName", "3D Builder"),
                QCoreApplication.translate("AppName", "3D Viewer"),
                QCoreApplication.translate("AppName", "Alarms and Clock"),
                QCoreApplication.translate("AppName", "Calculator"),
                QCoreApplication.translate("AppName", "Calendar and Mail"),
                QCoreApplication.translate("AppName", "Camera"),
                QCoreApplication.translate("AppName", "Feedback Hub"),
                QCoreApplication.translate("AppName", "Get Help"),
                QCoreApplication.translate("AppName", "Groove Music"),
                QCoreApplication.translate("AppName", "Maps"),
                QCoreApplication.translate("AppName", "Messaging"),
                QCoreApplication.translate("AppName", "Mixed Reality Portal"),
                QCoreApplication.translate("AppName", "Mobile Plans"),
                QCoreApplication.translate("AppName", "Money"),
                QCoreApplication.translate("AppName", "Movies && TV"),
                QCoreApplication.translate("AppName", "News"),
                QCoreApplication.translate("AppName", "Office"),
                QCoreApplication.translate("AppName", "OneNote"),
                QCoreApplication.translate("AppName", "Paint 3D"),
                QCoreApplication.translate("AppName", "People"),
                QCoreApplication.translate("AppName", "Photos"),
                QCoreApplication.translate("AppName", "Print 3D"),
                QCoreApplication.translate("AppName", "Skype"),
                QCoreApplication.translate("AppName", "Snip && Sketch"),
                QCoreApplication.translate("AppName", "Solitaire"),
                QCoreApplication.translate("AppName", "Sports"),
                QCoreApplication.translate("AppName", "Spotify"),
                QCoreApplication.translate("AppName", "Sticky Notes"),
                QCoreApplication.translate("AppName", "Tips"),
                QCoreApplication.translate("AppName", "Translator"),
                QCoreApplication.translate("AppName", "Voice Recorder"),
                QCoreApplication.translate("AppName", "Weather"),
                QCoreApplication.translate("AppName", "Xbox"),
                QCoreApplication.translate("AppName", "Xbox Game Bar"),
                QCoreApplication.translate("AppName", "Your Phone")))
        self.tooltip_list = list((
            QCoreApplication.translate(
                "ToolTip", "View, create, and personalize 3D objects."),
            QCoreApplication.translate(
                "ToolTip", "View 3D models and animations in real-time."),
            QCoreApplication.translate(
                "ToolTip",
                "A combination of alarm clock, world clock, timer, and stopwatch."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "A calculator that includes standard, scientific, and programmer modes, as well as a unit converter."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Stay up to date with email and schedule managing."),
            QCoreApplication.translate(
                "ToolTip", "Point and shoot to take pictures on Windows 10."),
            QCoreApplication.translate(
                "ToolTip",
                "Provide feedback about Windows and apps by sharing suggestions or problems."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Provide a way to ask a question and get recommended solutions or contact assisted support."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Listen to music on Windows, iOS, and Android devices."),
            QCoreApplication.translate(
                "ToolTip",
                "Search for places to get directions, business info, and reviews."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Quick, reliable SMS, MMS and RCS messaging from your phone."),
            QCoreApplication.translate(
                "ToolTip",
                "Discover Windows Mixed Reality and dive into more than 3,000 games and VR experiences from Steam VR and Microsoft Store."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Sign up for a data plan and connect with mobile operators in your area. You will need a supported SIM card."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Finance calculators, currency exchange rates and commodity prices from around the world."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "All your movies and TV shows, all in one place, on all your devices."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Deliver breaking news and trusted, in-depth reporting from the world\'s best journalists."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Find all your Office apps and files in one place."),
            QCoreApplication.translate(
                "ToolTip",
                "Digital notebook for capturing and organizing everything across your devices."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Make 2D masterpieces or 3D models that you can play with from all angles."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Connect with all your friends, family, colleagues, and acquaintances in one place."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "View and edit your photos and videos, make movies, and create albums."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Quickly and easily prepare objects for 3D printing on your PC."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Instant message, voice or video call application."),
            QCoreApplication.translate(
                "ToolTip",
                "Quickly annotate screenshots, photos and other images and save, paste or share with other apps."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Solitaire is one of the most played computer card games of all time."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Live scores and in-depth game experiences for more than 150 leagues."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Play your favorite songs and albums free on Windows 10 with Spotify."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Create notes, type, ink or add a picture, add text formatting, or stick them to the desktop."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Provide users with information and tips about operating system features."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Translate text and speech, have translated conversations, and even download AI-powered language packs to use offline."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Record sounds, lectures, interviews, and other events."),
            QCoreApplication.translate(
                "ToolTip",
                "Latest weather conditions, accurate 10-day and hourly forecasts."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Browse the catalogue, view recommendations, and discover PC games with Xbox Game Pass."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Instant access to widgets for screen capture and sharing, and chatting with Xbox friends."
            ),
            QCoreApplication.translate(
                "ToolTip",
                "Link your Android phone and PC to view and reply to text messages, access mobile apps, and receive notifications."
            )))
        self.app_data_list = [{
            "name": "*Microsoft.3DBuilder*",
            "link": "/?PFN=Microsoft.3DBuilder_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.Microsoft3DViewer*",
            "link": "/?PFN=Microsoft.Microsoft3DViewer_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.WindowsAlarms*",
            "link": "/?PFN=Microsoft.WindowsAlarms_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.WindowsCalculator*",
            "link": "/?PFN=Microsoft.WindowsCalculator_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*microsoft.windowscommunicationsapps*",
            "link": "/?PFN=Microsoft.windowscommunicationsapps_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.WindowsCamera*",
            "link": "/?PFN=Microsoft.WindowsCamera_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.WindowsFeedbackHub*",
            "link": "/?PFN=Microsoft.WindowsFeedbackHub_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.GetHelp*",
            "link": "/?PFN=Microsoft.Gethelp_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.ZuneMusic*",
            "link": "/?PFN=Microsoft.ZuneMusic_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.WindowsMaps*",
            "link": "/?PFN=Microsoft.WindowsMaps_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.Messaging*",
            "link": "/?PFN=Microsoft.Messaging_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.MixedReality.Portal*",
            "link": "/?PFN=Microsoft.MixedReality.Portal_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.OneConnect*",
            "link": "/?PFN=Microsoft.OneConnect_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.BingFinance*",
            "link": "/?PFN=Microsoft.BingFinance_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.ZuneVideo*",
            "link": "/?PFN=Microsoft.ZuneVideo_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.BingNews*",
            "link": "/?PFN=Microsoft.BingNews_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.MicrosoftOfficeHub*",
            "link": "/?PFN=Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.Office.OneNote*",
            "link": "/?PFN=Microsoft.Office.OneNote_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.MSPaint*",
            "link": "/?PFN=Microsoft.MSPaint_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.People*",
            "link": "/?PFN=Microsoft.People_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.Windows.Photos*",
            "link": "/?PFN=Microsoft.Windows.Photos_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.Print3D*",
            "link": "/?PFN=Microsoft.Print3D_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.SkypeApp*",
            "link": "/?PFN=Microsoft.SkypeApp_kzf8qxf38zg5c",
            "size": 0
        }, {
            "name": "*Microsoft.ScreenSketch*",
            "link": "/?PFN=Microsoft.ScreenSketch_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.MicrosoftSolitaireCollection*",
            "link":
            "/?PFN=Microsoft.MicrosoftSolitaireCollection_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.BingSports*",
            "link": "/?PFN=Microsoft.BingSports_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*SpotifyAB.SpotifyMusic*",
            "link": "/?PFN=SpotifyAB.SpotifyMusic_zpdnekdrzrea0",
            "size": 0
        }, {
            "name": "*Microsoft.MicrosoftStickyNotes*",
            "link": "/?PFN=Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.Getstarted*",
            "link": "/?PFN=Microsoft.Getstarted_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.BingTranslator*",
            "link": "/?PFN=Microsoft.BingTranslator_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.WindowsSoundRecorder*",
            "link": "/?PFN=Microsoft.WindowsSoundRecorder_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.BingWeather*",
            "link": "/?PFN=Microsoft.BingWeather_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.GamingApp*",
            "link": "/?PFN=Microsoft.GamingApp_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Xbox*",
            "link": "/?PFN=Microsoft.XboxGameOverlay_8wekyb3d8bbwe",
            "size": 0
        }, {
            "name": "*Microsoft.YourPhone*",
            "link": "/?PFN=Microsoft.YourPhone_8wekyb3d8bbwe",
            "size": 0
        }]

        if version.parse(platform.version()) >= version.parse("10.0.19041"):
            insort(self.app_name_list,
                   QCoreApplication.translate("AppName", "Cortana"))
            cortana_index = self.app_name_list.index("Cortana")
            self.tooltip_list.insert(
                cortana_index,
                QCoreApplication.translate("ToolTip",
                                           "Personal intelligence assistant."))
            self.app_data_list.insert(
                cortana_index, {
                    "name": "*Microsoft.549981C3F5F10*",
                    "link": "/?PFN=Microsoft.549981C3F5F10_8wekyb3d8bbwe",
                    "size": 0
                })

        self.checkbox_list = []
        for i, _ in enumerate(self.app_name_list):
            self.checkbox_list.append(QCheckBox())
            if i % 3 == 2:
                self.layout_checkboxes_3.addWidget(self.checkbox_list[i])
            elif i % 3 == 1:
                self.layout_checkboxes_2.addWidget(self.checkbox_list[i])
            else:
                self.layout_checkboxes.addWidget(self.checkbox_list[i])

        self.apps_dict = {}
        for i, checkbox in enumerate(self.checkbox_list):
            checkbox.setText(self.app_name_list[i])
            checkbox.setToolTip(self.tooltip_list[i])
            checkbox.setFont(self.font)
            self.apps_dict[checkbox] = self.app_data_list[i]

        self.label_space.setText(
            QCoreApplication.translate("Label", "Total amount of disk space:"))
        self.label_size.setText(QCoreApplication.translate("Label", "0 MB"))

        self.button_select_all.setText(
            QCoreApplication.translate("Button", "Select All"))
        self.button_deselect_all.setText(
            QCoreApplication.translate("Button", "Deselect All"))

        self.button_uninstall.setText(
            QCoreApplication.translate("Button", "Uninstall"))
Beispiel #2
0
        pixmap = self.movie.currentPixmap()
        pixmap = pixmap.scaled(self.my_size)
        painter.drawPixmap(0, 0, pixmap)


if __name__ == '__main__':
    app = QApplication()
    progressbar_value = 30
    path_to_gif = 'loading_gifs/1.gif'

    splash = MovieSplashScreen(path_to_gif)
    progressbar = QProgressBar(splash)
    progressbar.setMaximum(progressbar_value)
    progressbar.setTextVisible(False)
    progressbar.setGeometry(0,
                            splash.my_size.height() - 50,
                            splash.my_size.width(), 20)

    splash.show()

    for i in range(progressbar_value):
        progressbar.setValue(i)
        t = time.time()
        while time.time() < t + 0.1:
            app.processEvents()

    time.sleep(1)

    window = MainWindow()
    window.show()
    splash.finish(window)
Beispiel #3
0
class GUI:
    class Window:
        statistics = 1
        options = 2

    app = QApplication([])
    statisticsWindow = QWidget(f=Qt.FramelessWindowHint)
    optionsWindow = QWidget(f=Qt.FramelessWindowHint)
    defaultSizeX = 800
    defaultSizeY = 600
    newSizeX = None
    newSizeY = None
    hypixelAPILoad = 0
    minecraftAPILoad = 0
    overlayLoad = 0
    currentWindow = Window.statistics

    def __init__(self, winx: int, winy: int, version: str,
                 statisticsTypes: list, statistics: dict):
        self.newSizeX = winx
        self.newSizeY = winy
        self.version = version
        self.stats = statistics
        self.statTypes = statisticsTypes
        self.buildStatistics()

    def buildWindow(self, window: QWidget):
        window.resize(self.newSizeX, self.newSizeY)
        font = QFont()
        font.setBold(False)
        font.setUnderline(False)
        font.setKerning(False)
        font.setWeight(QFont.Weight.Normal)
        window.setFont(font)
        window.setObjectName(u"background")
        window.setStyleSheet("QWidget#background {background-color: gray}")

    def buildOptions(self):
        self.buildWindow()
        QLabel("Options", self.optionsWindow)

    def buildStatistics(self):
        self.buildWindow(self.window())
        self.statTableMain = QTableView(self.window())
        self.statTableMain.setObjectName(u"statTableMain")
        statTableHeader = QHeaderView(Qt.Orientation.Vertical)
        # self.statTableMain.commitData()
        # https://doc.qt.io/qt-5/sql-model.html
        self.statTableMain.setVerticalHeader(statTableHeader)
        self.statTableMain.setGeometry(self.winw(5), self.winh(10),
                                       self.winw(90), self.winh(80))
        hypixelAPILabel = QLabel("Hypixel API Load:", self.window())
        hypixelAPILabel.setGeometry(self.winw(5), self.winh(90), self.winw(15),
                                    self.winh(5))
        minecraftAPILabel = QLabel("Minecraft API Load:", self.window())
        minecraftAPILabel.setGeometry(self.winw(20), self.winh(90),
                                      self.winw(15), self.winh(5))
        overlayProgressLabel = QLabel("Overlay Load:", self.window())
        overlayProgressLabel.setGeometry(self.winw(35), self.winh(90),
                                         self.winw(15), self.winh(5))
        self.hypixelProgressBar = QProgressBar(self.window())
        self.hypixelProgressBar.setValue(self.hypixelAPILoad)
        self.hypixelProgressBar.setGeometry(self.winw(5), self.winh(95),
                                            self.winw(15), self.winh(3))
        self.minecraftProgressBar = QProgressBar(self.window())
        self.minecraftProgressBar.setValue(self.minecraftAPILoad)
        self.minecraftProgressBar.setGeometry(self.winw(20), self.winh(95),
                                              self.winw(15), self.winh(3))
        self.overlayProgressBar = QProgressBar(self.window())
        self.overlayProgressBar.setValue(self.overlayLoad)
        self.overlayProgressBar.setGeometry(self.winw(35), self.winh(95),
                                            self.winw(15), self.winh(3))
        self.statisticsButton = QPushButton("&Stats", self.window())
        self.statisticsButton.setGeometry(self.winw(5), self.winh(4),
                                          self.winw(10), self.winh(4))
        self.statisticsButton.setObjectName(u"menuButton")
        self.optionsButton = QPushButton("&Options", self.window())
        self.optionsButton.setGeometry(self.winw(16), self.winh(4),
                                       self.winw(10), self.winh(4))
        self.optionsButton.setObjectName(u"menuButton")
        self.exitButton = QPushButton("&Exit", self.window())
        self.exitButton.setGeometry(self.winw(85), self.winh(4), self.winw(10),
                                    self.winh(4))
        self.exitButton.setObjectName(u"menuButton")

        self.statisticsButton.clicked.connect(
            lambda: self.statisticsButtonClick())
        self.optionsButton.clicked.connect(lambda: self.optionsButtonClick())
        self.exitButton.clicked.connect(lambda: self.exitButtonClick())

    def updateButtons(self):
        self.statisticsButton.setDisabled(
            self.currentWindow == self.Window.statistics)
        self.optionsButton.setDisabled(
            self.currentWindow == self.Window.options)

    def statisticsButtonClick(self):
        self.currentWindow = self.Window.statistics

    def optionsButtonClick(self):
        self.currentWindow = self.Window.options

    def exitButtonClick(self):
        self.app.exit()

    def winw(self, percent: int):
        return percent / 100 * self.defaultSizeX

    def winh(self, percent: int):
        return percent / 100 * self.defaultSizeY

    def scale(self, normal: int, dir="both"):
        size = self.window().size()
        xscale = size.width() / self.defaultSizeX
        yscale = size.height() / self.defaultSizeY
        normal *= xscale if dir == "both" or dir == "hor" else 1
        normal *= yscale if dir == "both" or dir == "ver" else 1
        return normal

    def window(self):
        if self.currentWindow == self.Window.statistics:
            return self.statisticsWindow
        else:
            return self.optionsWindow

    def run(self):
        self.window().show()
        self.app.exec_()
class ProgressBar(QWidget):
    # Incoming progress updates
    set_progress = Signal(int)

    def __init__(self, show_time=True):
        """Opens a progress bar widget
        :type show_time: bool
        :param show_time: If the time should be shown below the progress bar"""
        super().__init__()
        # Setup parameters
        self._show_time: bool = show_time
        self._timer_start: float = 0

        # General layout
        self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
        self._layout = QVBoxLayout()
        self.setLayout(self._layout)
        # The progress bar itself
        self._progress_bar = QProgressBar(self)
        self._progress_bar.setMaximum(100)
        self._progress_bar.setGeometry(0, 0, 350, 25)
        self._progress_bar.setValue(0)
        self._layout.addWidget(self._progress_bar)
        # Setup time display
        self._time_wrapper = QHBoxLayout()
        self._time_expired_label = QLabel("")
        self._time_expired_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
        self._time_left_label = QLabel("")
        self._time_left_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
        self._time_wrapper.addWidget(self._time_expired_label)
        self._time_wrapper.addWidget(self._time_left_label)
        self._layout.addLayout(self._time_wrapper)
        # Set Size
        self.resize(500, 80)
        # Register progress update handler
        # noinspection PyUnresolvedReferences
        self.set_progress.connect(self._set_progress)

    def startTimer(self):
        """Start the internal timer"""
        self._timer_start = timeit.default_timer()

    def _set_progress(self, percentage_done):
        """Handle incoming progress updates
        :type percentage_done: int
        :param percentage_done: The progress to set, from 0 to 100
        """
        self._progress_bar.setValue(percentage_done)
        if self._show_time:
            time_elapsed, time_remaining = self._get_progress_times(percentage_done)
            self._time_expired_label.setText("Time elapsed: " + str(time_elapsed) + "s")
            self._time_left_label.setText("Time remaining: " + str(time_remaining) + "s")

    def _get_progress_times(self, percentage_done):
        """Get the elapsed and remaining time
        :type percentage_done: float
        :param percentage_done: How much progress has been made
        :return float, float: Time elapsed, Time remaining"""
        time_elapsed = math.floor(timeit.default_timer() - self._timer_start)
        if 0 == percentage_done:
            percentage_done = 1
        time_remaining = math.floor(time_elapsed * (100 / percentage_done)) - time_elapsed
        return time_elapsed, time_remaining

    def close_with_delay(self):
        """Close the progress bar widget with a short delay"""
        sleep(0.8)
        self.close()
class TableClothGenerator(QMainWindow):
    def __init__(self, parent=None):

        super().__init__(parent)

        # Main UI settings
        self.setWindowTitle('Tablecloth Generator')
        self.setWindowIcon(QIcon('icon.ico'))
        self.centralWidget = QWidget()

        self.setCentralWidget(self.centralWidget)
        self.resize(350, 350)
        self.center()

        self._createMenuBar()

        self.MainUI()

    def MainUI(self):

        # Obtain the configs
        fp_config = open(THISDIR + "\\config\\config.json", "r",
                            encoding="utf-8")
        self.config = json.loads(fp_config.read())
        fp_config.close()

        # Obtain and List the teams
        fp_teams = open(THISDIR + "\\config\\teams.json", "r",
                            encoding="utf-8")
        conf_teams = json.loads(fp_teams.read())
        fp_teams.close()
        self.teams = conf_teams["teams"]
        self.players = conf_teams["players"]

        # Obtain all images needed to create the tablecloth
        self.background = Image.open(THISDIR + "\\images\\mat.png")
        self.table_border = Image.open(THISDIR + "\\images\\table_border.png")
        self.tech_lines = Image.open(THISDIR + "\\images\\technical_lines.png")

        # Check if there's no configuration set up
        # and prompt to create/import one
        if self.config["total_teams"] == 0:
            self.no_config = QMessageBox.question(self, "No configuration",
            "No configuration has been found. Do you wish to set up a new one?",
            QMessageBox.Yes | QMessageBox.No)

            if self.no_config == QMessageBox.Yes:
                self.CreateTeamsWindow()

        self.bg_image = self.config["image_route"]
        self.players_combobox = QComboBox()
        self.UpdatePlayersList()
        self.players_combobox.setEditable(True)
        self.players_combobox.completer()\
                             .setCompletionMode(QCompleter.PopupCompletion)
        self.players_combobox.setInsertPolicy(QComboBox.NoInsert)

        # Set up the GUI
        self.statusBar().showMessage("Remember: Rig responsibly.")
        # Bottom (EAST)
        self.label_east = QLabel(self)
        self.label_east.setText("<h1>East Seat</h1>")
        self.label_east.setAlignment(QtCore.Qt.AlignCenter)
        self.image_east = QLabel(self)
        self.image_east.setPixmap(QPixmap("images/logos/team1.png")\
                                  .scaled(100,100))
        self.image_east.setAlignment(QtCore.Qt.AlignCenter)
        self.search_east = QLineEdit()
        self.search_east.setAlignment(QtCore.Qt.AlignCenter)
        self.search_east.editingFinished.connect(
            lambda: self.searchPlayer(self.search_east.text(),
                                      self.cloth_east))
        self.cloth_east = QComboBox()
        self.cloth_east.setModel(self.players_combobox.model())
        self.cloth_east.currentIndexChanged.connect(
            lambda: self.SwitchImage(self.cloth_east, self.image_east))
        # Right (SOUTH)
        self.label_south = QLabel(self)
        self.label_south.setText("<h1>South Seat</h1>")
        self.label_south.setAlignment(QtCore.Qt.AlignCenter)
        self.image_south = QLabel(self)
        self.image_south.setPixmap(QPixmap("images/logos/team1.png")\
                                   .scaled(100,100))
        self.image_south.setAlignment(QtCore.Qt.AlignCenter)
        self.image_south.show()
        self.search_south = QLineEdit()
        self.search_south.setAlignment(QtCore.Qt.AlignCenter)
        self.search_south.editingFinished.connect(
            lambda: self.searchPlayer(self.search_south.text(),
                                      self.cloth_south))
        self.cloth_south = QComboBox()
        self.cloth_south.setModel(self.players_combobox.model())
        self.cloth_south.currentIndexChanged.connect(
            lambda: self.SwitchImage(self.cloth_south, self.image_south))
        # Top (WEST)
        self.label_west = QLabel(self)
        self.label_west.setText("<h1>West Seat</h1>")
        self.label_west.setAlignment(QtCore.Qt.AlignCenter)
        self.image_west = QLabel(self)
        self.image_west.setPixmap(QPixmap("images/logos/team1.png")\
                                  .scaled(100,100))
        self.image_west.setAlignment(QtCore.Qt.AlignCenter)
        self.image_west.show()
        self.cloth_west = QComboBox()
        self.search_west = QLineEdit()
        self.search_west.setAlignment(QtCore.Qt.AlignCenter)
        self.search_west.editingFinished.connect(
            lambda: self.searchPlayer(self.search_west.text(),
                                      self.cloth_west))
        self.cloth_west.setModel(self.players_combobox.model())
        self.cloth_west.currentIndexChanged.connect(
            lambda: self.SwitchImage(self.cloth_west, self.image_west))
        # Left (NORTH)
        self.label_north = QLabel(self)
        self.label_north.setText("<h1>North Seat</h1>")
        self.label_north.setAlignment(QtCore.Qt.AlignCenter)
        self.image_north = QLabel(self)
        self.image_north.setPixmap(QPixmap("images/logos/team1.png")\
                                   .scaled(100,100))
        self.image_north.setAlignment(QtCore.Qt.AlignCenter)
        self.image_north.show()
        self.cloth_north = QComboBox()
        self.search_north = QLineEdit()
        self.search_north.setAlignment(QtCore.Qt.AlignCenter)
        self.search_north.editingFinished.connect(
            lambda: self.searchPlayer(self.search_north.text(),
                                      self.cloth_north))
        self.cloth_north.setModel(self.players_combobox.model())
        self.cloth_north.currentIndexChanged.connect(
            lambda: self.SwitchImage(self.cloth_north, self.image_north))
        # Technical lines
        self.technical_lines = QCheckBox("Show Technical lines", self)
        # Generate button
        self.generate = QPushButton(self)
        self.generate.setText("Generate Tablecloth")
        self.generate.clicked.connect(self.GeneratePreview)
        # Add custom mat
        self.custom_mat = QPushButton(self)
        self.custom_mat.setText("Add Mat")
        self.custom_mat.clicked.connect(self.MatDialog)

        # Create the layout
        grid_layout = QGridLayout()
        grid_layout.setAlignment(QtCore.Qt.AlignCenter)
        grid_layout.setAlignment(QtCore.Qt.AlignTop)
        # Labels East, West
        grid_layout.addWidget(self.label_east, 1, 1)
        grid_layout.addWidget(self.label_west, 1, 2)
        # Image preview East, West
        grid_layout.addWidget(self.image_east, 2, 1)
        grid_layout.addWidget(self.image_west, 2, 2)
        # Search player East, West
        grid_layout.addWidget(self.search_east, 3, 1)
        grid_layout.addWidget(self.search_west, 3, 2)
        # Player combobox East, West
        grid_layout.addWidget(self.cloth_east, 4, 1)
        grid_layout.addWidget(self.cloth_west, 4, 2)
        # Labes South, North
        grid_layout.addWidget(self.label_south, 5, 1)
        grid_layout.addWidget(self.label_north, 5, 2)
        # Image preview South, North
        grid_layout.addWidget(self.image_south, 6, 1)
        grid_layout.addWidget(self.image_north, 6, 2)
        # Search player South, North
        grid_layout.addWidget(self.search_south, 7, 1)
        grid_layout.addWidget(self.search_north, 7, 2)
        # Player combobox South, North
        grid_layout.addWidget(self.cloth_south, 8, 1)
        grid_layout.addWidget(self.cloth_north, 8, 2)
        # Technical lines
        grid_layout.addWidget(self.technical_lines, 9, 1)
        # Custom mat/bg
        grid_layout.addWidget(self.custom_mat, 10, 1)
        # Generate
        grid_layout.addWidget(self.generate, 10, 2)

        self.centralWidget.setLayout(grid_layout)

        # Create the window
        self.show()

    def _createMenuBar(self):

        # Settings and stuff for the toolbar
        menubar = QMenuBar(self)

        file_menu = QMenu("&File", self)
        file_menu.addAction("Create Team(s)", self.CreateTeamsWindow)
        file_menu.addAction("Edit Team(s)", self.EditTeamsWindow)
        file_menu.addAction("Exit", self.close)
        settings_menu = QMenu("&Settings", self)
        settings_menu.addAction("Version", self.SeeVersion)
        settings_menu.addAction("Help", self.GetHelp)

        menubar.addMenu(file_menu)
        menubar.addMenu(settings_menu)

        self.setMenuBar(menubar)

    def _createProgressBar(self):

        self.progress_bar = QProgressBar()
        self.progress_bar.minimum = 0
        self.progress_bar.maximum = 100
        self.progress_bar.setValue(0)
        self.progress_bar.setTextVisible(False)
        self.progress_bar.setGeometry(50, 50, 10, 10)
        self.progress_bar.setAlignment(QtCore.Qt.AlignRight)
        self.progress_bar.adjustSize()
        self.statusBar().addPermanentWidget(self.progress_bar)
        self.ChangeAppStatus(False)

    def SwitchImage(self, cloth, image):
        # It shows you the team logo. No way you can miss those, right?
        team_id = self.SearchTeamID(cloth, True)
        image.setPixmap(QPixmap(
            "images/logos/team%d.png" % team_id).scaled(100,100))

    def searchPlayer(self, text, combobox):
        # It even searches the player for you. What more could you want?
        search_index = combobox.findText(text, QtCore.Qt.MatchContains)
        if search_index == -1:
            QMessageBox.warning(self, "Error", "No player found")
        else:
            combobox.setCurrentIndex(search_index)

    def CreateTeamsWindow(self):

        self.teamcreation_wid = EditionWidget()
        self.teamcreation_wid.resize(400, 200)
        self.teamcreation_wid.setWindowTitle("Teams configuration")

        self.new_config = {}

        id_label = QLabel(self)
        id_label.setText("Team ID: ")
        self.num_id = QLabel(self)
        current_id = str(self.config["total_teams"] + 1)
        self.num_id.setText(current_id)
        name_label = QLabel(self)
        name_label.setText("Team Name:")
        name_label.setFocus()
        self.name_input = QLineEdit(self)
        members_label = QLabel(self)
        members_label.setText("Members (write and press enter):")
        members_input = QLineEdit(self)
        members_input.editingFinished.connect(
            lambda: self.AddMember(members_input))
        self.members_list = QListWidget(self)

        import_image = QPushButton(self)
        import_image.setText("Import Team Image")
        import_image.clicked.connect(self.ImportTeamImage)

        add_team = QPushButton(self)
        add_team.setText("Add Team")
        add_team.clicked.connect(
            lambda: self.addTeamFunction(self.name_input.text(),
                self.members_list))
        import_config = QPushButton(self)
        import_config.setText("Import configuration")
        import_config.clicked.connect(self.importTeamFunction)

        config_lay = QGridLayout()
        config_lay.addWidget(id_label, 1, 0)
        config_lay.addWidget(self.num_id, 1, 1)
        config_lay.addWidget(name_label, 2, 0)
        config_lay.addWidget(self.name_input, 2, 1)
        config_lay.addWidget(members_label, 3, 0)
        config_lay.addWidget(members_input, 3, 1)
        config_lay.addWidget(self.members_list, 4, 0, 2, 2)
        config_lay.addWidget(add_team, 6, 0)
        config_lay.addWidget(import_image, 6, 1)
        config_lay.addWidget(import_config, 7, 0, 1, 2)
        self.teamcreation_wid.setLayout(config_lay)

        self.teamcreation_wid.setWindowModality(QtCore.Qt.ApplicationModal)
        self.teamcreation_wid.activateWindow()
        self.teamcreation_wid.raise_()
        self.teamcreation_wid.show()

    def addTeamFunction(self, name, members):
        fp_teams = open(THISDIR + "\\config\\teams.json", "r",
                            encoding="utf-8")
        current_teams = json.loads(fp_teams.read())
        fp_teams.close()
        team = {}
        current_teams["teams"].append(name)
        current_teams["players"][name] = [str(self.members_list.item(i).text())\
                                    for i in range(self.members_list.count())]
        new_team = open(THISDIR + "\\config\\teams.json", "w+",
                            encoding="utf-8")
        add_config = open(THISDIR + "\\config\\config.json", "w+",
                            encoding="utf-8")
        self.teams = current_teams["teams"]
        self.players = current_teams["players"]
        self.config["total_teams"] += 1
        new_id = self.config["total_teams"] + 1
        self.num_id.setText(str(new_id))
        add_config.write(json.dumps(self.config, indent=4))
        new_team.write(json.dumps(current_teams, indent=4))
        new_team.close()

        self.name_input.clear()

        self.members_list.clear()

        self.UpdatePlayersList()

    def ImportTeamImage(self):

        image_dialog = QFileDialog(self)
        image_dialog = QFileDialog.getOpenFileName(filter="Images (*.png)",
            selectedFilter="Images (*.png)")

        if image_dialog[0] != "":
            new_team_logo = Image.open(image_dialog[0]).convert("RGBA")
            if new_team_logo.size != (250, 250):
                new_team_logo.resize((250, 250))
            new_team_logo.save(THISDIR+"\\images\\logos\\team%s.png"\
                % self.num_id.text())

            QMessageBox.information(self, "Team Image", "Team image added.")

    def importTeamFunction(self):
        file_dialog = QFileDialog(self)
        file_dialog = QFileDialog.getOpenFileName(
                                    filter="Team Files (*.json *.zip)",
                                    selectedFilter="Team Files (*.json *.zip)")

        if file_dialog[0] != "":
            if is_zipfile(file_dialog[0]):
                with ZipFile(file_dialog[0]) as zip_import:
                    list_of_files = zip_import.namelist()
                    for fimp in list_of_files:
                        if fimp.startswith('logos'):
                            zip_import.extract(fimp, path=THISDIR+'\\images\\')
                    imported_teams = zip_import.read('teams.json')
                    imported_teams = imported_teams.decode('utf-8')
            else:
                imported_teams = open(file_dialog[0], "r",
                                encoding="utf-8").read()
            json_teams = json.loads(imported_teams)
            self.teams = json_teams["teams"]
            self.players = json_teams["players"]

            new_teams = open(THISDIR + "\\config\\teams.json", "w+",
                            encoding="utf-8")
            new_teams.write(json.dumps(json_teams, indent=4))
            new_teams.close()

            old_config = open(THISDIR + "\\config\\config.json", "r",
                                encoding="utf-8").read()
            old_config = json.loads(old_config)
            old_config["total_teams"] = len(json_teams["teams"])
            self.config = old_config
            new_config = open(THISDIR + "\\config\\config.json", "w+",
                                encoding="utf-8")
            new_config.write(json.dumps(self.config, indent=4))
            new_config.close()

            self.UpdatePlayersList()

            self.image_east.setPixmap(QPixmap("images/logos/team1.png")\
                                       .scaled(100,100))
            self.cloth_east.setModel(self.players_combobox.model())
            self.image_south.setPixmap(QPixmap("images/logos/team1.png")\
                                       .scaled(100,100))
            self.cloth_south.setModel(self.players_combobox.model())
            self.image_west.setPixmap(QPixmap("images/logos/team1.png")\
                                       .scaled(100,100))
            self.cloth_west.setModel(self.players_combobox.model())
            self.image_north.setPixmap(QPixmap("images/logos/team1.png")\
                                       .scaled(100,100))
            self.cloth_north.setModel(self.players_combobox.model())
            self.statusBar().showMessage("Teams imported successfully.")
            self.teamcreation_wid.close()


    def AddMember(self, member):
        self.members_list.addItem(member.text())
        member.clear()

    def EditTeamsWindow(self):

        self.teamedit_wid = EditionWidget()
        self.teamedit_wid.resize(400, 320)
        self.teamedit_wid.setWindowTitle("Edit Teams")

        self.teams_list = QComboBox(self)
        self.teams_list.addItem("--- Select a team ---")
        for team in self.teams:
            self.teams_list.addItem(team)
        self.teams_list.currentIndexChanged.connect(self.UpdateTeamInfo)

        team_id_label = QLabel(self)
        team_id_label.setText("Team ID: ")
        self.config_team_id = QLabel(self)
        team_name_label = QLabel(self)
        team_name_label.setText("Team name: ")
        self.config_team_name = QLabel(self)
        team_members_label = QLabel(self)
        team_members_label.setText("Team members: ")
        self.config_team_members = QListWidget(self)
        add_member_label = QLabel(self)
        add_member_label.setText("Add new member: ")
        add_member_input = QLineEdit(self)
        add_member_input.editingFinished.connect(self.AddNewMember)

        delete_member = QPushButton(self)
        delete_member.setText("Delete member")
        delete_member.clicked.connect(self.DeleteMember)
        delete_team = QPushButton(self)
        delete_team.setText("Delete Team")
        delete_team.clicked.connect(self.DeleteTeam)
        save_changes = QPushButton(self)
        save_changes.setText("Save changes")
        save_changes.clicked.connect(self.SaveEdits)
        export_config = QPushButton(self)
        export_config.setText("Export Configuration")
        export_config.clicked.connect(self.ExportTeams)

        config_lay = QGridLayout()
        config_lay.addWidget(self.teams_list, 1, 0)
        config_lay.addWidget(team_id_label, 2, 0)
        config_lay.addWidget(self.config_team_id, 2, 1)
        config_lay.addWidget(team_name_label, 3, 0)
        config_lay.addWidget(self.config_team_name, 3, 1, 1, 2)
        config_lay.addWidget(team_members_label, 4, 0)
        config_lay.addWidget(self.config_team_members, 5, 0)
        config_lay.addWidget(add_member_label, 6, 0)
        config_lay.addWidget(add_member_input, 6, 1, 1, 2)
        config_lay.addWidget(delete_member, 7, 0)
        config_lay.addWidget(delete_team, 7, 1)
        config_lay.addWidget(save_changes, 8, 0)
        config_lay.addWidget(export_config, 8, 1)

        self.teamedit_wid.setLayout(config_lay)
        self.teamedit_wid.setWindowModality(QtCore.Qt.ApplicationModal)
        self.teamedit_wid.activateWindow()
        self.teamedit_wid.raise_()
        self.teamedit_wid.show()

    def UpdateTeamInfo(self):

        sender = self.sender()
        if sender.currentIndex() > 0:
            team_id = sender.currentIndex()
            self.config_team_id.setText(str(team_id))
            self.config_team_name.setText(sender.currentText())
            if self.config_team_members.count() > 0:
                self.config_team_members.clear()
            self.config_team_members.addItems(
                self.players[sender.currentText()])

    def AddNewMember(self):

        sender = self.sender()
        self.config_team_members.addItem(sender.text())
        sender.clear()

    def DeleteMember(self):

        list_members = self.config_team_members.selectedItems()
        if len(list_members) == 0:
            QMessageBox.warning(self, "Error", "No player selected")
        else:
            for member in list_members:
                self.config_team_members.takeItem(
                                           self.config_team_members.row(member))

    def DeleteTeam(self):
        team_id = int(self.config_team_id.text())
        is_last_item = self.teams[self.teams.index(
            self.config_team_name.text())] == (self.teams[len(self.teams)-1])
        self.teams.pop(self.teams.index(self.config_team_name.text()))
        self.players.pop(self.config_team_name.text())
        new_teamlist = {}
        new_teamlist["teams"] = self.teams
        new_teamlist["players"] = self.players
        current_teams = open(THISDIR + "\\config\\teams.json", "w+",
                        encoding="utf-8")
        current_teams.write(json.dumps(new_teamlist, indent=4))
        current_teams.close()

        if is_last_item == True:
            self.teams_list.setCurrentIndex(1)
        else:
            self.teams_list.setCurrentIndex(team_id+1)
        self.teams_list.removeItem(team_id)
        self.UpdatePlayersList()
        self.cloth_east.setModel(self.players_combobox.model())
        self.cloth_south.setModel(self.players_combobox.model())
        self.cloth_west.setModel(self.players_combobox.model())
        self.cloth_north.setModel(self.players_combobox.model())

    def ExportTeams(self):

        export_dir = self.config["save_route"] if self.config["save_route"] \
                                                    is not None else THISDIR
        exported_file = QFileDialog.getSaveFileName(self, "Save File",
            export_dir, "Save files (*.zip)")

        if exported_file[0] != "":
            export_filename = exported_file[0]
            if export_filename.endswith(".zip") is False:
                export_filename += ".zip"
            files_to_export = []
            files_to_export.append("config\\teams.json")

            for root, directories, files in os.walk(THISDIR+"\\images\\logos"):
                for filename in files:
                    filepath = os.path.join(root, filename)
                    files_to_export.append(filepath)

            with ZipFile(export_filename, "w") as export_zip:
                for exp_file in files_to_export:
                    export_name = exp_file
                    if exp_file.endswith(".json"):
                        split_name = exp_file.split("\\")
                        export_name = split_name[-1]
                    if exp_file.endswith(".png"):
                        split_name = exp_file.split("\\")
                        export_name = "\\logos\\" + split_name[-1]
                    export_zip.write(exp_file, arcname=export_name)
                export_zip.close()

            if os.path.exists(export_filename):
                QMessageBox.information(self, "Export",
                    "The export was successful")

    def SaveEdits(self):

        list_members = [str(self.config_team_members.item(i).text()) for i in \
                                        range(self.config_team_members.count())]
        self.players[self.config_team_name.text()] = list_members
        new_teamlist = {}
        new_teamlist["teams"] = self.teams
        new_teamlist["players"] = self.players
        current_teams = open(THISDIR + "\\config\\teams.json", "w+",
                        encoding="utf-8")
        current_teams.write(json.dumps(new_teamlist, indent=4))
        current_teams.close()
        self.teamedit_wid.close()
        self.statusBar().showMessage("Settings saved.")

    def MatDialog(self):

        mat_dialog = QFileDialog(self)
        mat_dialog = QFileDialog.getOpenFileName(filter="Images (*.png *.jpg)",
            selectedFilter="Images (*.png *.jpg)")

        if mat_dialog[0] != "":
            self.GenerateMat(mat_dialog[0])

    def GenerateMat(self, image):

        self.background = image
        background = Image.open(self.background).resize((2048,2048))\
                                                .convert("RGBA")

        self.mat_thread = QThread()
        east_id = self.SearchTeamID(self.cloth_east, True)
        south_id = self.SearchTeamID(self.cloth_south, True)
        west_id = self.SearchTeamID(self.cloth_west, True)
        north_id = self.SearchTeamID(self.cloth_north, True)

        if self.config["save_route"] is None:
            save_to_route = THISDIR
        else:
            save_to_route = self.config["save_route"]
        self._createProgressBar()

        self.mat_worker = GenerateImageThread(background, self.table_border,
            east_id, south_id, west_id, north_id,
            self.technical_lines.isChecked(), save_to_route,
            self.bg_image, True)
        self.mat_worker.moveToThread(self.mat_thread)
        self.mat_thread.started.connect(self.mat_worker.run)
        self.mat_worker.update_progress.connect(self.UpdateStatus)
        self.mat_worker.finished.connect(self.mat_thread.quit)
        self.mat_worker.finished.connect(self.mat_worker.deleteLater)
        self.mat_thread.finished.connect(self.mat_thread.deleteLater)
        self.mat_thread.finished.connect(self.MatPreviewWindow)
        self.mat_thread.start()


    def MatPreviewWindow(self):

        self.statusBar().showMessage('Mat preview generated.')
        self.statusBar().removeWidget(self.progress_bar)
        # Now you can go back to rigging
        self.ChangeAppStatus(True)

        self.mat_wid = QWidget()
        self.mat_wid.resize(600, 600)
        self.mat_wid.setWindowTitle("Background preview")

        mat_preview_title = QLabel(self)
        mat_preview_title.setText("Selected image (1/4 scale)")
        mat_preview = QLabel(self)
        mat_preview.setPixmap(QPixmap(tempfile.gettempdir()+"\\Table_Dif.jpg")\
                                .scaled(512,512))
        confirm = QPushButton(self)
        confirm.setText("Confirm")
        confirm.clicked.connect(
            lambda: self.ChangeMatImage(self.background))

        vbox = QVBoxLayout()
        vbox.setAlignment(QtCore.Qt.AlignCenter)
        vbox.addWidget(mat_preview_title)
        vbox.addWidget(mat_preview)
        vbox.addWidget(confirm)
        self.mat_wid.setLayout(vbox)

        self.mat_wid.setWindowModality(QtCore.Qt.ApplicationModal)
        self.mat_wid.activateWindow()
        self.mat_wid.raise_()
        self.mat_wid.show()

    def ChangeMatImage(self, image):

        new_bg = Image.open(image)

        if new_bg.size != (2048, 2048):
            new_bg = new_bg.resize((2048, 2048))
        if new_bg.mode != "RGBA":
            new_bg = new_bg.convert("RGBA")

        if self.config["save_route"] is not None:
            new_bg.save(self.config["save_route"]+"\\images\\mat.png")
            self.bg_image = self.config["save_route"]+"\\images\\mat.png"
        else:
            new_bg.save(THISDIR+"\\images\\mat.png")
            self.bg_image = THISDIR+"\\images\\mat.png"

        self.background = new_bg
        self.config["image_route"] = self.bg_image

        new_file = open(THISDIR + "\\config\\config.json", "w+",
                                        encoding="utf-8")
        new_file.write(json.dumps(self.config, indent=4))
        new_file.close()

        self.statusBar().showMessage('New background added.')
        self.statusBar().removeWidget(self.progress_bar)
        self.ChangeAppStatus(True)

        self.mat_wid.close()

    def GeneratePreview(self):

        self.preview_thread = QThread()
        east_id = self.SearchTeamID(self.cloth_east, True)
        south_id = self.SearchTeamID(self.cloth_south, True)
        west_id = self.SearchTeamID(self.cloth_west, True)
        north_id = self.SearchTeamID(self.cloth_north, True)

        if self.config["save_route"] is None:
            save_to_route = THISDIR
        else:
            save_to_route = self.config["save_route"]
        self._createProgressBar()

        self.preview_worker = GenerateImageThread(self.background,
            self.table_border, east_id, south_id, west_id, north_id,
            self.technical_lines.isChecked(), save_to_route,
            self.bg_image, True)
        self.preview_worker.moveToThread(self.preview_thread)
        self.preview_thread.started.connect(self.preview_worker.run)
        self.preview_worker.update_progress.connect(self.UpdateStatus)
        self.preview_worker.finished.connect(self.preview_thread.quit)
        self.preview_worker.finished.connect(self.preview_worker.deleteLater)
        self.preview_thread.finished.connect(self.preview_thread.deleteLater)
        self.preview_thread.finished.connect(self.PreviewWindow)
        self.preview_thread.start()

    def PreviewWindow(self):

        self.statusBar().showMessage('Tablecloth preview generated.')
        self.statusBar().removeWidget(self.progress_bar)
        # Now you can go back to rigging
        self.ChangeAppStatus(True)

        self.preview_wid = QWidget()
        self.preview_wid.resize(600, 600)
        self.preview_wid.setWindowTitle("Tablecloth preview")

        tablecloth = QPixmap(tempfile.gettempdir()+"\\Table_Dif.jpg")

        tablecloth_preview_title = QLabel(self)
        tablecloth_preview_title.setText("Tablecloth preview (1/4 scale)")
        tablecloth_preview = QLabel(self)
        tablecloth_preview.setPixmap(tablecloth.scaled(512,512))
        confirm = QPushButton(self)
        confirm.setText("Confirm")
        confirm.clicked.connect(self.GenerateImage)
        confirm.clicked.connect(self.preview_wid.close)

        vbox = QVBoxLayout()
        vbox.setAlignment(QtCore.Qt.AlignCenter)
        vbox.addWidget(tablecloth_preview_title)
        vbox.addWidget(tablecloth_preview)
        vbox.addWidget(confirm)
        self.preview_wid.setLayout(vbox)

        self.preview_wid.setWindowModality(QtCore.Qt.ApplicationModal)
        self.preview_wid.activateWindow()
        self.preview_wid.raise_()
        self.preview_wid.show()

    def GeneratedDialog(self):

        self.statusBar().showMessage('Tablecloth generated. Happy rigging!')
        self.statusBar().removeWidget(self.progress_bar)
        # Now you can go back to rigging
        self.ChangeAppStatus(True)

        mbox = QMessageBox()

        mbox.setWindowTitle("Tablecloth Generator")
        mbox.setText("Tablecloth Generated!")
        mbox.setStandardButtons(QMessageBox.Ok)

        mbox.exec()

    def UpdateStatus(self, status):
        self.progress_bar.setValue(status)

    def GenerateImage(self):

        self.statusBar().showMessage('Generating image...')
        self._createProgressBar()

        if self.config["save_route"] is None:
            self.config["save_route"] = THISDIR

        save_to_route = QFileDialog.getExistingDirectory(self,
            "Where to save the image", self.config["save_route"],
            QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)

        if self.config["save_route"] != save_to_route:
            temp_file = open(THISDIR + "\\config\\config.json", "r",
                                            encoding="utf-8")
            fp_teams = json.loads(temp_file.read())
            fp_teams["save_route"] = save_to_route
            fp_teams["image_route"] = self.bg_image
            new_file = open(THISDIR + "\\config\\config.json", "w+",
                                            encoding="utf-8")
            new_file.write(json.dumps(fp_teams, indent=4))
            new_file.close()

        self.background = Image.open(THISDIR + "\\images\\mat.png")
        self.table_border = Image.open(THISDIR + "\\images\\table_border.png")
        self.tech_lines = Image.open(THISDIR + "\\images\\technical_lines.png")

        self.thread = QThread()
        east_id = self.SearchTeamID(self.cloth_east, True)
        south_id = self.SearchTeamID(self.cloth_south, True)
        west_id = self.SearchTeamID(self.cloth_west, True)
        north_id = self.SearchTeamID(self.cloth_north, True)
        self.worker = GenerateImageThread(self.background, self.table_border,
            east_id, south_id, west_id, north_id,
            self.technical_lines.isChecked(), save_to_route, self.bg_image)
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.run)
        self.worker.update_progress.connect(self.UpdateStatus)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.thread.finished.connect(self.GeneratedDialog)
        self.thread.start()

    def ChangeAppStatus(self, status):
        # True for enable, False for disable.
        self.cloth_east.setEnabled(status)
        self.search_east.setEnabled(status)
        self.cloth_south.setEnabled(status)
        self.search_south.setEnabled(status)
        self.cloth_west.setEnabled(status)
        self.search_west.setEnabled(status)
        self.cloth_north.setEnabled(status)
        self.search_north.setEnabled(status)
        self.generate.setEnabled(status)

    def SearchTeamID(self, cloth, plus_one=False):
        team_id = self.teams.index(cloth.itemData(cloth.currentIndex()))
        if plus_one:
            team_id += 1
        return team_id

    def UpdatePlayersList(self):
        for team, members in self.players.items():
            for member in members:
                self.players_combobox.addItem(member, team)

    def center(self):
        qr = self.frameGeometry()
        cp = QScreen().availableGeometry().center()
        qr.moveCenter(cp)

    def SeeVersion(self):

        git_url = "https://raw.githubusercontent.com/vg-mjg/tablecloth-"
        git_url += "generator/main/version.txt"
        with urllib.request.urlopen(git_url) as response:
            url_version = response.read().decode("utf-8")

        version = "Your version is up to date!"
        if url_version != VERSION:
            version = "Your version is outdated."
            version += "Please check the <a href='https://github.com/vg-mjg/"
            version += "tablecloth-generator/releases'>Github page</a>"
            version +=" for updates."
        version_message = QMessageBox(self)
        version_message.setWindowTitle("Checking version")
        version_message.setText("""<h1>Tablecloth generator</h1>
            <br>
            <b>Current Version:</b> %s<br>
            <b>Your Version:</b> %s<br>
            <i>%s</i>
            """ % (url_version, VERSION, version))

        version_message.exec()

    def GetHelp(self):
        webbrowser.open("https://github.com/vg-mjg/tablecloth-generator/wiki")