Пример #1
0
class MainFrame(QWidget):
    def __init__(self, parent=None):
        super(MainFrame, self).__init__(parent)

        # intialize the gui
        self.originalPalette = QApplication.palette()
        self.createTopGroupBox()
        self.createLeftGroupBox()
        self.createMiddleTabWidget()
        self.createProgressBar()
        self.createMenubar()
        self.createToolbar()

        # set gui layout
        mainLayout = QGridLayout()
        mainLayout.setMenuBar(self.menuBar)
        mainLayout.addWidget(self.toolbar, 0, 0, 1, 3)
        mainLayout.addWidget(self.topBox, 1, 0, 1, 3)
        mainLayout.addWidget(self.leftGroupBox, 2, 0)
        mainLayout.addWidget(self.middleGroupBox, 2, 1)
        mainLayout.addWidget(self.progressBar, 3, 0, 1, 3)
        mainLayout.setRowStretch(2, 2)
        mainLayout.setColumnStretch(0, 2)
        mainLayout.setColumnStretch(1, 6)
        self.setLayout(mainLayout)
        self.setWindowTitle("ISPAPI-CLI Tool")

        # set app gui style
        QApplication.setStyle(QStyleFactory.create('Fusion'))

        # create core login instnace
        self.coreLogic = Core()

        # check user session upon start
        self.checkLogin()

        # set focus on command input field
        self.cmdTxt.setFocus()

        # initilaize command line completer
        self.initialiseCommandCompleter()

        # command to execute
        self.commandToExecute = ''

        # set app icon
        self.setWindowIcon(QIcon(self.getIcon("logo-bgw.jpg")))

    def checkLogin(self):
        result = self.coreLogic.checkSession()
        if result == 'valid':
            self.sessionTime.setText("Your session is valid. ")
            self.sessionTime.setStyleSheet("color:green")
            self.loginBtn.setIcon(QIcon(self.getIcon("logout.png")))
            self.loginBtn.setText('Logout')
            self.loginBtn.clicked.connect(self.logout)
            self.reconnectBtnAction(self.loginBtn.clicked, self.logout)
            # enable gui
            self.disableEnableGui('enable')

        else:
            self.sessionTime.setText("Session expired! ")
            self.sessionTime.setStyleSheet("color:red")
            self.loginBtn.setIcon(QIcon(self.getIcon("login.png")))
            self.loginBtn.setText('Login')
            self.reconnectBtnAction(self.loginBtn.clicked,
                                    self.openLoginWindow)
            # diable gui
            self.disableEnableGui('disable')

    def reconnectBtnAction(self, signal, newhandler=None, oldhandler=None):
        """
        Reconnecting login btn action to either login or logout
        """
        while True:
            try:
                if oldhandler is not None:
                    signal.disconnect(oldhandler)
                else:
                    signal.disconnect()
            except TypeError:
                break
        if newhandler is not None:
            signal.connect(newhandler)

    def logout(self):
        msg = self.coreLogic.logout()
        alert = QMessageBox()
        alert.setText(msg)
        alert.exec_()
        # update login
        self.checkLogin()

    def disableEnableGui(self, status=None):
        """
        If session is expired then disable gui
        """
        if status is not None:
            if status == 'enable':
                self.leftGroupBox.setEnabled(True)
                self.topBox.setEnabled(True)
                # focus on command input field
                self.cmdTxt.setFocus()
            else:
                self.leftGroupBox.setDisabled(True)
                self.topBox.setDisabled(True)
        else:
            pass

    def advanceProgressBar(self):
        curVal = self.progressBar.value()
        if curVal <= 99:
            self.progressBar.setValue(curVal + 1)
        else:
            self.timer.stop()
            self.progressBar.setValue(0)

    def createProgressBar(self, ):
        self.progressBar = QProgressBar()
        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(0)
        self.progressBar.setMaximumHeight(5)
        self.progressBar.setTextVisible(False)

        # create a timer for the progress bar

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.advanceProgressBar)

        # call timer with speed of 5
        self.progressBarSpeed(5)

    def progressBarSpeed(self, speed):
        self.timer.start(speed)

    def onMyToolBarButtonClick(self, s):
        print("click", s)

    def executeCommand(self):
        # start progressbar
        self.progressBarSpeed(5)
        # get args from the GUI
        commandToExecute = self.commandText.toPlainText()
        if commandToExecute.startswith('-', 0, 1):
            original_args = commandToExecute.splitlines()
        else:
            original_args = ("--" + commandToExecute).splitlines()
        original_args = ' '.join(original_args)
        # remove extra spaces around the = cases are ' =', '= ', ' = '
        original_args = original_args.replace(" = ", "=")
        original_args = original_args.replace(" =", "=")
        original_args = original_args.replace("= ", "=")
        splitted_args = original_args.split()
        # intialize the parser
        core_obj = self.coreLogic
        parser = core_obj.initParser()
        # overwrite defualt error function with our local function to show on the GUI
        parser.error = self.errorFunction

        try:
            args = vars(parser.parse_args(splitted_args))
            reminderargs = args['args']
            # parse command args
            result, data = core_obj.parseArgs(args)
            # case gui started
            if result == 'gui':
                self.plainResponse.setText("GUI already started")
            # case of help command
            elif result == 'help':
                helpText = ''
                preHelp = textwrap.dedent('''\
                    ISPAPI - Commandline Tool
                    ------------------------------------------------------------
                    The tool can be used in two modes:
                    - By using '=' sign e.g. --command=QueryDomainList limit=5
                    - By using spaces e.g. --command QueryDomainList limit 5
                    ------------------------------------------------------------

                    ''')
                # redirect stdout
                stringio = StringIO()
                previous_stdout = sys.stdout
                sys.stdout = stringio

                # trigger parser help
                parser.print_help()

                # set back stdout
                sys.stdout = previous_stdout
                stdoutValue = stringio.getvalue()

                # show output on the GUI
                helpText = preHelp + stdoutValue
                self.plainResponse.setText(helpText)

            elif result == 'cmd':
                # append reminder args with the command
                params_list = core_obj.parseParameters(reminderargs)
                cmd = data
                # add them to data which is the command list
                cmd.update(params_list)
                self.response = core_obj.request(cmd)
                # set reult values to gui
                self.populateResults(self.response)

            # case update commands
            elif result == 'update':
                # create scrap object
                # scrap = Scrap()
                msg = "Please run this command in the terminal, use: ./ispapicli --update"
                self.plainResponse.setText(msg)
            else:
                self.plainResponse.setText(data)

            # 1 end the progress bar
            # self.progressBarSpeed(5)
            # 2
            # check user session, in case of sesssion is expired
            self.checkLogin()
        except Exception as e:
            self.plainResponse.setText("Command failed due to: " + str(e))

    def errorFunction(self, message):
        self.plainResponse.setText('An error happend: ' + message + '\n')

    def updateCommandView(self, e):
        cmdTxt = self.cmdTxt.text()
        # check if the command is related to other actions
        if cmdTxt.startswith('-', 0, 1):
            self.commandText.setText(cmdTxt)
            self.commandToExecute = cmdTxt
            return 0
        else:
            args = 'command '
            args += cmdTxt
            args = args.split()
            # clean extra spaces, leave only single spaces among commands
            original_args = ' '.join(args)
            # remove extra spaces around the = cases are ' =', '= ', ' = '
            original_args = original_args.replace(" = ", "=")
            original_args = original_args.replace(" =", "=")
            original_args = original_args.replace("= ", "=")
            # split args in an array
            parameters = original_args.split()
            # split commands if = used
            params_len = len(parameters)
            params = {}
            try:
                if params_len > 1:
                    i = 0
                    while i < params_len:
                        if '=' in parameters[i]:
                            key, value = parameters[i].split('=')
                            params[key] = value
                        else:
                            key = parameters[i]
                            i += 1
                            value = parameters[i]
                            params[key] = value
                        i += 1
                    self.commandText.setText()
            except Exception as e:
                pass
            commandView = "\n".join(
                ("{}={}".format(*i) for i in params.items()))
            self.commandText.setText(commandView)
            self.commandToExecute = '--' + commandView

    def createToolbar(self):
        self.toolbar = QToolBar("My main toolbar")
        self.toolbar.setIconSize(QSize(20, 20))
        saveAction = QAction(QIcon(self.getIcon("save.png")),
                             "Save results to a file", self)
        saveAction.triggered.connect(lambda: self.saveCommandToFile())

        copyAction = QAction(QIcon(self.getIcon("copy.png")),
                             "Copy the results to clipboard", self)
        copyAction.triggered.connect(self.copyToClipboard)

        helpAction = QAction(QIcon(self.getIcon("help.png")),
                             "See help documentation", self)
        helpAction.triggered.connect(self.showHelp)

        openAction = QAction(QIcon(self.getIcon("new.png")),
                             "Open another window", self)

        self.sessionTime = QLabel("Checking your session... ")
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

        self.loginBtn = QPushButton("Login")
        self.loginBtn.setIcon(QIcon(self.getIcon("login.png")))
        self.loginBtn.setStyleSheet("padding: 2px; padding-left: 6px")
        self.loginBtn.setIconSize(QSize(12, 12))
        self.loginBtn.setLayoutDirection(Qt.RightToLeft)

        seperator = QAction(self)
        seperator.setSeparator(True)
        # create a new window -TODO
        # self.toolbar.addAction(openAction)
        self.toolbar.addAction(saveAction)
        self.toolbar.addAction(copyAction)
        self.toolbar.addAction(seperator)
        self.toolbar.addAction(helpAction)
        self.toolbar.addWidget(spacer)
        self.toolbar.addWidget(self.sessionTime)
        self.toolbar.addWidget(self.loginBtn)

    def createMenubar(self):

        self.menuBar = QMenuBar()
        file = self.menuBar.addMenu("File")
        new = QAction("New window", self)
        new.setShortcut("Ctrl+n")
        save = QAction("Save to file", self)
        save.setShortcut("Ctrl+S")
        quit = QAction("Quit", self)
        quit.setShortcut("Ctrl+q")

        # create a new window - TODO
        # file.addAction(new)
        file.addAction(save)
        file.addAction(quit)

        edit = self.menuBar.addMenu("Edit")
        copy = QAction("Copy", self)
        copy.setShortcut("Ctrl+c")

        edit.addAction(copy)

        help = self.menuBar.addMenu("Help")
        help.addAction("About ISPAPI tool")
        help.addAction("How to start?")

        file.triggered[QAction].connect(self.menuBarActions)
        edit.triggered[QAction].connect(self.menuBarActions)
        help.triggered[QAction].connect(self.menuBarActions)

    def createTopGroupBox(self):
        self.topBox = QGroupBox((""))
        executeBtn = QPushButton("Execute")
        executeBtn.setIcon(QIcon(self.getIcon("execute.png")))
        executeBtn.clicked.connect(self.executeCommand)
        executeBtn.setIconSize(QSize(14, 14))
        # executeBtn.setLayoutDirection(Qt.RightToLeft)

        clearBtn = QPushButton("Clear")
        clearBtn.setIcon(QIcon(self.getIcon("cross.png")))
        clearBtn.setIconSize(QSize(14, 14))
        # clearBtn.setLayoutDirection(Qt.RightToLeft)
        clearBtn.clicked.connect(self.__clearCMDfield)

        self.cmdTxt = QLineEdit()
        self.cmdTxt.setPlaceholderText("Enter command here...")
        self.cmdTxt.textEdited.connect(self.updateCommandView)
        #qSpaceEvent = QKeyEvent(QEvent.KeyPress, Qt.Key_Backspace, Qt.NoModifier)
        # self.cmdTxt.keyPressEvent(qSpaceEvent)
        self.cmdTxt.installEventFilter(self)
        self.cmdTxt.returnPressed.connect(self.executeCommand)

        # set command completer
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.cmdTxt.setCompleter(self.completer)

        self.minParameter = QLabel(self)
        self.minParameter.setText('Min parameters: ')
        self.minParameter.setStyleSheet("color:gray")
        f = QFont("Arial", 9)
        self.minParameter.setFont(f)

        gridLayout = QGridLayout()
        gridLayout.addWidget(self.cmdTxt, 0, 1, 1, 1)
        gridLayout.addWidget(executeBtn, 0, 2, 1, 1)
        gridLayout.addWidget(clearBtn, 0, 3, 1, 1)
        gridLayout.addWidget(self.minParameter, 1, 1, 1, 1)
        gridLayout.setContentsMargins(5, 0, 5, 10)
        self.topLayout = gridLayout
        self.topBox.setLayout(gridLayout)

    def createLeftGroupBox(self):
        self.leftGroupBox = QGroupBox("Command extracted")
        self.commandText = QTextEdit()
        self.commandText.setPlaceholderText(
            "Extracted command will be shown here")

        tab2hbox = QHBoxLayout()
        tab2hbox.setContentsMargins(5, 5, 5, 5)
        tab2hbox.addWidget(self.commandText)

        self.leftGroupBox.setLayout(tab2hbox)

    def createMiddleTabWidget(self):
        self.middleGroupBox = QGroupBox("Results")
        middleTabWidget = QTabWidget()
        middleTabWidget.setSizePolicy(QSizePolicy.Preferred,
                                      QSizePolicy.Ignored)

        tab1 = QWidget()
        self.plainResponse = QTextEdit()
        tab1hbox = QHBoxLayout()
        tab1hbox.setContentsMargins(5, 5, 5, 5)
        tab1hbox.addWidget(self.plainResponse)
        tab1.setLayout(tab1hbox)

        tab2 = QWidget()
        self.tableResponse = QTableWidget(1, 2)
        self.tableResponse.setHorizontalHeaderLabels(['Property', 'Value'])
        self.tableResponse.horizontalHeader().setStretchLastSection(True)
        tableLayout = QGridLayout()
        tableLayout.setContentsMargins(5, 5, 5, 5)
        tableLayout.addWidget(self.tableResponse, 0, 0)
        tab2.setLayout(tableLayout)

        tab3 = QWidget()
        self.listResponse = QTextEdit()
        tab3hbox = QHBoxLayout()
        tab3hbox.addWidget(self.listResponse)
        tab3.setLayout(tab3hbox)

        middleTabWidget.addTab(tab1, "Plain")
        middleTabWidget.addTab(tab2, "Properties")
        middleTabWidget.addTab(tab3, 'List')

        layout = QGridLayout()
        layout.addWidget(middleTabWidget, 0, 0, 1, 1)

        self.middleGroupBox.setLayout(layout)

    def openLoginWindow(self):
        """
        Start login window
        """
        loginGui = LoginWindow(self)
        loginGui.startGui()

    def menuBarActions(self, q):
        action = q.text()
        if action == 'New Window':
            pass
        if action == 'Save to file':
            self.saveCommandToFile()
        if action == 'Quit':
            self.closeApplication()
        if action == 'Copy':
            self.copyToClipboard()
        if action == 'Help':
            self.showHelp()
        if action == 'About ISPAPI tool':
            self.showAbout()
        if action == 'How to start?':
            self.showHelp()

    def closeApplication(self):
        print("exiting")
        sys.exit()

    def startNewWindow(self):
        app = QApplication(sys.argv)
        appGui = MainFrame()
        appGui.startGui()
        sys.exit(app.exec_())

    def startGui(self):
        geo = QDesktopWidget().availableGeometry()

        screenWidth = geo.width()
        screenHeight = geo.height()
        width = int(screenWidth * 0.5)
        height = int(screenHeight * 0.5)
        self.resize(width, height)

        frameGeo = self.frameGeometry()
        cp = geo.center()
        frameGeo.moveCenter(cp)
        self.move(frameGeo.topLeft())

        # start gui
        self.show()

    def initialiseCommandCompleter(self):
        model = QStringListModel()
        # get all possible autocomplete strings
        stringsSuggestion = []
        stringsSuggestion = (self.coreLogic.getCommandList()).splitlines()
        # set suggestion to the model
        model.setStringList(stringsSuggestion)
        # set model to the completer
        self.completer.setModel(model)

    def __clearCMDfield(self):
        self.cmdTxt.clear()
        self.cmdTxt.setFocus(True)

    def populateResults(self, response):
        # get reulsts
        plainResult = response.getPlain()
        listResult = response.getListHash()

        # delete any previous content of the list
        self.listResponse.setText('')

        # set plain results
        self.plainResponse.setText(plainResult)

        # set properties and list
        resultLists = listResult['LIST']
        counter = 0
        for row in resultLists:
            for col in row:
                counter += 1
        # set the number of rows
        self.tableResponse.setRowCount(counter)

        # populate the table
        rownumber = 0
        for row in resultLists:
            for i, (key, value) in enumerate(row.items()):
                keyWidget = QTableWidgetItem(key)
                valueWidget = QTableWidgetItem(value)
                self.tableResponse.setItem(rownumber, 0, keyWidget)
                self.tableResponse.setItem(rownumber, 1, valueWidget)
                # update the list
                if key not in ('TOTAL', 'FIRST', 'LAST', 'LIMIT', 'COUNT'):
                    self.listResponse.append(value)
                # incerate rownumber
                rownumber += 1
        # order table content
        self.tableResponse.sortItems(Qt.AscendingOrder)

    def saveCommandToFile(self):
        try:
            textToWrite = self.commandAndResponsePlain()
            options = QFileDialog.Options()
            # options |= QFileDialog.DontUseNativeDialog # Qt's builtin File Dialogue
            fileName, _ = QFileDialog.getSaveFileName(self,
                                                      "Open",
                                                      "report.txt",
                                                      "All Files (*.*)",
                                                      options=options)
            if fileName:
                try:
                    with open(fileName, 'w') as file:
                        file.write(textToWrite)
                    alert = QMessageBox()
                    alert.setText("'" + fileName +
                                  "' \n\nFile Saved Successfully!")
                    alert.setIcon(QMessageBox.Information)
                    alert.exec_()
                except Exception as e:
                    alert = QMessageBox()
                    alert.setIcon(QMessageBox.Critical)
                    alert.setText("Couldn't save the file due to: " + str(e))
                    alert.exec_()
        except Exception as e:
            alert = QMessageBox()
            alert.setIcon(QMessageBox.Critical)
            alert.setText("Request a command first!")
            alert.setWindowTitle("Error")
            alert.exec_()

    def commandAndResponsePlain(self):
        result = self.plainResponse.toPlainText()
        command = self.response.getCommandPlain()
        textToWrite = command + '\n' + result
        return textToWrite

    def copyToClipboard(self):
        try:
            newText = self.commandAndResponsePlain()
            clipboard = QApplication.clipboard()
            clipboard.setText(newText)
        except Exception as e:
            print(e)
            pass  # in the case where there is not command requested

    def showHelp(self):
        box = QMessageBox(self)
        msg = """<p align='center'>
        <b style='font-size:20px'>Help Information</b>. <br><br><br>
        This window provides a simple help view, more detailed help can be found at: 
        <a href="https://hexonet.github.io/ispapicli/">ISPAPI CLI Tool Documentation</a>
        <br><br>
        Quick start:
        <br>
        To show help, type the command: -h | --help
        <br>
        From there you will find all information about using the command line in both the GUI and terminal
        <br><br>
        <span style="color:orange">Note</span>: Commands executed in terminal are similar to commands used in the GUI, except for the "--update" command which is only possible to trigger in the terminal
        <br><br><br>
        Copyright 2020 @Hexonet
        <br><br>
        </p>
        """
        box.setStandardButtons(QMessageBox.Ok)
        box.setIcon(QMessageBox.Information)
        box.setWindowTitle("Help")
        box.setText(msg)
        box.show()

    def showAbout(self):

        box = QMessageBox(self)
        msg = """<p align='center'>
        <b style='font-size:20px'>ISPAPI Tool</b>. <br><br><br>
        Version: %s <br><br>
        A simple command line interface to connect you to your account on Hexonet
        <br><br>
        Technical Support:
        <br>
        Email: [email protected] 
        <br>
        Website: <a href="https://hexonet.github.io/ispapicli/">ISPAPI CLI Tool</a>
        <br><br><br>
        Copyright 2020 @Hexonet
        <br><br>
        </p>
        """

        box.setStandardButtons(QMessageBox.Ok)
        # box.setIcon(QMessageBox.Information)
        box.setWindowTitle("About")
        box.setText(msg % __version__)
        box.show()

    def eventFilter(self, source, event):

        # this function to handle autocomplete for command line
        if (event.type() == QEvent.KeyRelease and source is self.cmdTxt):
            if event.key() == Qt.Key_Space:
                # show min paramters suggestions
                try:
                    cmd = self.cmdTxt.text()
                    m = re.match('^(\w+)\s$', cmd)
                    if m:
                        minParams = self.coreLogic.getMinParameters(
                            cmd.strip())
                        if len(minParams) > 0:
                            minParamsLabel = ', '.join(minParams)
                            minParamsInput = '= '.join(minParams)
                            cursorPosition = len(
                                self.cmdTxt.text() +
                                minParams[0]) + 1  # for the '=' char
                            self.cmdTxt.setText(cmd + minParamsInput + '=')
                            self.minParameter.setText('Min parameters: ' +
                                                      minParamsLabel)
                            self.cmdTxt.setCursorPosition(cursorPosition)
                        else:
                            self.minParameter.setText('Min parameters:')
                except Exception as e:
                    print(e)
        # must return bool value
        return super(MainFrame, self).eventFilter(source, event)

    def getIcon(self, iconName):
        ##
        # This function checks if the app is executable or in development and return the path

        if getattr(sys, 'frozen', False):
            self.absolute_dirpath = os.path.dirname(sys.executable)
        elif __file__:
            self.absolute_dirpath = os.path.dirname(__file__)

        path = self.command_path = os.path.join(self.absolute_dirpath,
                                                '../icons/' + iconName)
        return path
Пример #2
0
class MainFrame(QWidget):

    BATCH_COMMANDLINE_ID = 300
    BATCH_PARAMETER_ID = 400
    BATCH_LIST_ID = 500
    BATCH_PARAMS = [
        "Select",
        "CONTACT",
        "DNSZONE",
        "DOMAIN",
        "DOMAINAUTH",
        "HOST",
        "NAMESERVER",
        "OBJECTID",
        "SSLCERTID",
    ]

    def __init__(self, parent=None):
        super(MainFrame, self).__init__(parent)

        # intialize the gui
        self.originalPalette = QApplication.palette()
        self.createTopGroupBox()
        self.createLeftGroupBox()
        self.createMiddleTabWidget()
        self.createProgressBar()
        self.createMenubar()
        self.createToolbar()

        # set gui layout
        mainLayout = QGridLayout()
        mainLayout.setMenuBar(self.leftMenuBar)
        mainLayout.addWidget(self.toolbar, 0, 0, 1, 3)
        mainLayout.addWidget(self.topBox, 1, 0, 1, 3)
        mainLayout.addWidget(self.leftGroupBox, 2, 0)
        mainLayout.addWidget(self.middleGroupBox, 2, 1)
        mainLayout.addWidget(self.progressBar, 3, 0, 1, 3)
        mainLayout.setRowStretch(2, 2)
        mainLayout.setColumnStretch(0, 2)
        mainLayout.setColumnStretch(1, 6)
        self.setLayout(mainLayout)
        self.setWindowTitle("ISPAPI-CLI Tool")

        # set app gui style
        QApplication.setStyle(QStyleFactory.create("Fusion"))

        # create core login instnace
        self.coreLogic = Core()

        # scrap instance
        self.scrap = Scrap()

        # check user session upon start
        self.checkLogin()

        # set focus on command input field
        self.cmdTxt.setFocus()

        # initilaize command line completer
        self.initialiseCommandCompleter()

        # initialize subuser completer
        self.initialiseSubuserCompleter()

        # command to execute
        self.commandToExecute = ""

        # set app icon
        self.setWindowIcon(QIcon(self.getIcon("logo-bgw.jpg")))

    def checkLogin(self):
        result = self.coreLogic.checkSession()
        if result == "valid":
            self.sessionTime.setText("Your session is valid. ")
            self.sessionTime.setStyleSheet("color:green")
            self.loginBtn.setIcon(QIcon(self.getIcon("logout.png")))
            self.loginBtn.setText("Logout")
            self.loginBtn.clicked.connect(self.logout)
            self.reconnectBtnAction(self.loginBtn.clicked, self.logout)
            # enable gui
            self.disableEnableGui("enable")

        else:
            self.sessionTime.setText("Session expired! ")
            self.sessionTime.setStyleSheet("color:red")
            self.loginBtn.setIcon(QIcon(self.getIcon("login.png")))
            self.loginBtn.setText("Login")
            self.reconnectBtnAction(self.loginBtn.clicked,
                                    self.openLoginWindow)
            # diable gui
            self.disableEnableGui("disable")

    def reconnectBtnAction(self, signal, newhandler=None, oldhandler=None):
        """
        Reconnecting login btn action to either login or logout
        """
        while True:
            try:
                if oldhandler is not None:
                    signal.disconnect(oldhandler)
                else:
                    signal.disconnect()
            except TypeError:
                break
        if newhandler is not None:
            signal.connect(newhandler)

    def logout(self):
        msg = self.coreLogic.logout()
        alert = QMessageBox()
        alert.setText(msg)
        alert.exec_()
        # update login
        self.checkLogin()

    def disableEnableGui(self, status=None):
        """
        If session is expired then disable gui
        """
        if status is not None:
            if status == "enable":
                self.leftGroupBox.setEnabled(True)
                self.topBox.setEnabled(True)
                # focus on command input field
                self.cmdTxt.setFocus()
            else:
                self.leftGroupBox.setDisabled(True)
                self.topBox.setDisabled(True)
        else:
            pass

    def advanceProgressBar(self):
        curVal = self.progressBar.value()
        if curVal <= 99:
            self.progressBar.setValue(curVal + 1)
        else:
            self.timer.stop()
            self.progressBar.setValue(0)

    def createProgressBar(self, ):
        self.progressBar = QProgressBar()
        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(0)
        self.progressBar.setMaximumHeight(5)
        self.progressBar.setTextVisible(False)

        # create a timer for the progress bar

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.advanceProgressBar)

        # call timer with speed of 5
        self.progressBarSpeed(5)

    def progressBarSpeed(self, speed):
        self.timer.start(speed)

    def onMyToolBarButtonClick(self, s):
        print("click", s)

    def executeCommand(self):
        # start progressbar
        self.progressBarSpeed(5)
        # get args from the GUI
        commandToExecute = self.commandText.toPlainText().lower()
        if commandToExecute.startswith("-", 0, 1):
            original_args = commandToExecute.splitlines()
        else:
            original_args = ("--" + commandToExecute).splitlines()
        original_args = " ".join(original_args)
        # remove extra spaces around the = cases are ' =', '= ', ' = '
        original_args = original_args.replace(" = ", "=")
        original_args = original_args.replace(" =", "=")
        original_args = original_args.replace("= ", "=")
        splitted_args = original_args.split()
        # intialize the parser
        core_obj = self.coreLogic
        parser = core_obj.initParser()
        # overwrite defualt error function with our local function to show on the GUI
        parser.error = self.errorFunction

        try:
            args = vars(parser.parse_args(splitted_args))
            reminderargs = args["args"]
            # parse command args
            result, data = core_obj.parseArgs(args)
            # case gui started
            if result == "gui":
                self.plainResponse.setText("GUI already started")
            # case of help command
            elif result == "help":
                helpText = ""
                preHelp = textwrap.dedent("""\
                    ISPAPI - Commandline Tool
                    ------------------------------------------------------------
                    The tool can be used in two modes:
                    - By using '=' sign e.g. --command=QueryDomainList limit=5
                    - By using spaces e.g. --command QueryDomainList limit 5
                    ------------------------------------------------------------

                    """)
                # redirect stdout
                stringio = StringIO()
                previous_stdout = sys.stdout
                sys.stdout = stringio

                # trigger parser help
                parser.print_help()

                # set back stdout
                sys.stdout = previous_stdout
                stdoutValue = stringio.getvalue()

                # show output on the GUI
                helpText = preHelp + stdoutValue
                self.plainResponse.setText(helpText)

            elif result == "cmd":
                # append reminder args with the command
                params_list = core_obj.parseParameters(reminderargs)
                cmd = data
                # add them to data which is the command list
                cmd.update(params_list)
                # check if subuser
                subuser = self.subuser.text()
                if len(subuser) > 1:
                    core_obj.cl.setUserView(subuser)  # set subuser
                else:
                    core_obj.cl.resetUserView()  # remove subuser
                # check for batches
                batch_param = self.batchParams.currentText()
                batch_params_list = self.batchParamsList.toPlainText()
                if batch_param != "Select" and batch_params_list != "":
                    lines = batch_params_list.split("\n")
                    for line in lines:
                        if line != "":
                            cmd[batch_param] = line
                            # request call
                            self.response = core_obj.request(cmd)
                            # set reult values to gui
                            self.populateResults(self.response)
                else:
                    # request call
                    self.response = core_obj.request(cmd)
                    # set reult values to gui
                    self.populateResults(self.response)

            # case update commands
            elif result == "update":
                # create scrap object
                # msg = "Please run this command in the terminal, use: ./ispapicli --update"
                # self.plainResponse.setText(msg)
                self.showUpdating()
            else:
                self.plainResponse.setText(data)

            # 1 end the progress bar
            # self.progressBarSpeed(5)
            # 2
            # check user session, in case of sesssion is expired
            self.checkLogin()
        except Exception as e:
            self.plainResponse.setText("Command failed due to: " + str(e))

    def errorFunction(self, message):
        self.plainResponse.setText("An error happend: " + message + "\n")

    def updateCommandView(self, e):
        cmdTxt = self.cmdTxt.text()
        # check if the command is related to other actions
        if cmdTxt.startswith("-", 0, 1):
            self.commandText.setText(cmdTxt)
            self.commandToExecute = cmdTxt
            return 0
        else:
            args = "command "
            args += cmdTxt
            args = args.split()
            # clean extra spaces, leave only single spaces among commands
            original_args = " ".join(args)
            # remove extra spaces around the = cases are ' =', '= ', ' = '
            original_args = original_args.replace(" = ", "=")
            original_args = original_args.replace(" =", "=")
            original_args = original_args.replace("= ", "=")
            # split args in an array
            parameters = original_args.split()
            # split commands if = used
            params_len = len(parameters)
            params = {}
            try:
                if params_len > 1:
                    i = 0
                    while i < params_len:
                        if "=" in parameters[i]:
                            key, value = parameters[i].split("=")
                            params[key] = value
                        else:
                            key = parameters[i]
                            i += 1
                            value = parameters[i]
                            params[key] = value
                        i += 1
                    self.commandText.setText()
            except Exception as e:
                pass
            commandView = "\n".join(
                ("{}={}".format(*i) for i in params.items()))
            self.commandText.setText(commandView)
            self.commandToExecute = "--" + commandView

    def createToolbar(self):
        self.toolbar = QToolBar("My main toolbar")
        self.toolbar.setIconSize(QSize(20, 20))
        saveAction = QAction(QIcon(self.getIcon("save.png")),
                             "Save results to a file", self)
        saveAction.triggered.connect(lambda: self.saveCommandToFile())

        copyAction = QAction(QIcon(self.getIcon("copy.png")),
                             "Copy the results to clipboard", self)
        copyAction.triggered.connect(self.copyToClipboard)

        helpAction = QAction(QIcon(self.getIcon("help.png")),
                             "See help documentation", self)
        helpAction.triggered.connect(self.showHelp)

        updateAction = QAction(QIcon(self.getIcon("refresh.png")),
                               "Update the tool API's commands", self)
        updateAction.triggered.connect(self.showUpdating)

        updateToolAction = QAction(QIcon(self.getIcon("direct-download.png")),
                                   "Update the tool", self)
        updateToolAction.triggered.connect(self.checkForUpdate)

        self.sessionTime = QLabel("Checking your session... ")
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

        self.loginBtn = QPushButton("Login")
        self.loginBtn.setIcon(QIcon(self.getIcon("login.png")))
        self.loginBtn.setStyleSheet("padding: 2px; padding-left: 6px")
        self.loginBtn.setIconSize(QSize(12, 12))
        self.loginBtn.setLayoutDirection(Qt.RightToLeft)

        seperator = QAction(self)
        seperator.setSeparator(True)
        # create a new window -TODO
        # self.toolbar.addAction(openAction)
        self.toolbar.addAction(saveAction)
        self.toolbar.addAction(seperator)
        self.toolbar.addAction(copyAction)
        self.toolbar.addAction(seperator)
        self.toolbar.addAction(helpAction)
        self.toolbar.addAction(seperator)
        self.toolbar.addAction(updateAction)
        self.toolbar.addAction(updateToolAction)
        self.toolbar.addWidget(spacer)
        self.toolbar.addWidget(self.sessionTime)
        self.toolbar.addWidget(self.loginBtn)

    def createMenubar(self):
        self.rightMenuBar = QMenuBar()
        self.currentVersion = QLabel(__version__)

        self.leftMenuBar = QMenuBar()
        file = self.leftMenuBar.addMenu("File")
        new = QAction("New window", self)
        new.setShortcut("Ctrl+n")
        save = QAction("Save to file", self)
        save.setShortcut("Ctrl+S")
        quit = QAction("Quit", self)
        quit.setShortcut("Ctrl+q")

        # create a new window - TODO
        # file.addAction(new)
        file.addAction(save)
        file.addAction(quit)

        edit = self.leftMenuBar.addMenu("Edit")
        copy = QAction("Copy", self)
        copy.setShortcut("Ctrl+c")

        edit.addAction(copy)

        help = self.leftMenuBar.addMenu("Help")
        help.addAction("About ISPAPI tool")
        help.addAction("How to start?")

        file.triggered[QAction].connect(self.menuBarActions)
        edit.triggered[QAction].connect(self.menuBarActions)
        help.triggered[QAction].connect(self.menuBarActions)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

        check = QAction("Current version: " + __version__, self)
        self.rightMenuBar.addAction(check)

        self.leftMenuBar.setCornerWidget(self.rightMenuBar)
        self.leftMenuBar.setStyleSheet("padding: 0px 0px 0px 5px")

    def createTopGroupBox(self):
        self.topBox = QGroupBox((""))
        executeBtn = QPushButton("Execute")
        executeBtn.setIcon(QIcon(self.getIcon("execute.png")))
        executeBtn.clicked.connect(self.executeCommand)
        executeBtn.setIconSize(QSize(14, 14))
        # executeBtn.setLayoutDirection(Qt.RightToLeft)

        clearBtn = QPushButton("Clear")
        clearBtn.setIcon(QIcon(self.getIcon("cross.png")))
        clearBtn.setIconSize(QSize(14, 14))
        # clearBtn.setLayoutDirection(Qt.RightToLeft)
        clearBtn.clicked.connect(self.__clearCMDfield)

        self.cmdTxt = QLineEdit()
        self.cmdTxt.setPlaceholderText("Enter command here...")
        self.cmdTxt.textEdited.connect(self.updateCommandView)
        # qSpaceEvent = QKeyEvent(QEvent.KeyPress, Qt.Key_Backspace, Qt.NoModifier)
        # self.cmdTxt.keyPressEvent(qSpaceEvent)
        self.cmdTxt.installEventFilter(self)
        self.cmdTxt.returnPressed.connect(self.executeCommand)

        # set command completer
        self.completer = QCompleter()
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.cmdTxt.setCompleter(self.completer)

        # subuser
        self.subuser = QLineEdit()
        self.subuser.setPlaceholderText("Type a subuser")

        self.subuser.returnPressed.connect(self.executeCommand)

        # set command completer
        self.subUsercompleter = QCompleter()
        self.subUsercompleter.setCaseSensitivity(Qt.CaseInsensitive)
        self.subuser.setCompleter(self.subUsercompleter)

        self.minParameter = QLabel(self)
        self.minParameter.setText("Min parameters: ")
        self.minParameter.setStyleSheet("color:gray")
        f = QFont("Arial", 9)
        self.minParameter.setFont(f)

        gridLayout = QGridLayout()
        gridLayout.addWidget(self.cmdTxt, 0, 1, 1, 1)
        gridLayout.addWidget(self.subuser, 0, 2, 1, 1)
        gridLayout.addWidget(executeBtn, 0, 3, 1, 1)
        gridLayout.addWidget(clearBtn, 0, 4, 1, 1)
        gridLayout.addWidget(self.minParameter, 1, 1, 1, 1)
        gridLayout.setColumnStretch(1, 6)
        gridLayout.setColumnStretch(2, 2)
        gridLayout.setColumnStretch(3, 1)
        gridLayout.setColumnStretch(4, 1)
        gridLayout.setContentsMargins(5, 0, 5, 10)
        self.topLayout = gridLayout
        self.topBox.setLayout(gridLayout)

    def createLeftGroupBox(self):
        self.leftGroupBox = QGroupBox("Command")
        leftTabWidget = QTabWidget()
        leftTabWidget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Ignored)

        tab1 = QWidget()
        self.commandText = QTextEdit()
        self.commandText.setPlaceholderText(
            "Extracted command will be shown here")
        tab1hbox = QHBoxLayout()
        tab1hbox.setContentsMargins(5, 5, 5, 5)
        tab1hbox.addWidget(self.commandText)
        tab1.setLayout(tab1hbox)

        tab2 = QWidget()
        # params label
        self.batchParamsLabel = QLabel()
        self.batchParamsLabel.setText("Select parameter:")
        # params list
        self.batchParams = QComboBox()
        self.batchParams.addItems(self.BATCH_PARAMS)
        self.batchParams.setEditable(True)
        # params text label
        self.batchParamsListLabel = QLabel()
        self.batchParamsListLabel.setText("Insert the list:")
        self.batchParamsListLabel.setContentsMargins(0, 10, 0, 0)

        # params text
        self.batchParamsList = QTextEdit()
        self.batchParamsList.setPlaceholderText("Enter each item in new line")
        self.batchParamsList.setFrameStyle(QFrame.Box)
        tableLayout = QGridLayout()
        tableLayout.setContentsMargins(15, 5, 5, 5)
        tableLayout.addWidget(self.batchParamsLabel, 0, 0)
        tableLayout.addWidget(self.batchParams, 1, 0)
        tableLayout.addWidget(self.batchParamsListLabel, 2, 0)
        tableLayout.addWidget(self.batchParamsList, 3, 0)
        tab2.setLayout(tableLayout)

        leftTabWidget.addTab(tab1, "Extracted Command")
        leftTabWidget.addTab(tab2, "Batch")

        layout = QGridLayout()
        layout.addWidget(leftTabWidget, 0, 0, 1, 1)

        self.leftGroupBox.setLayout(layout)

    def createMiddleTabWidget(self):
        self.middleGroupBox = QGroupBox("Results")
        middleTabWidget = QTabWidget()
        middleTabWidget.setSizePolicy(QSizePolicy.Preferred,
                                      QSizePolicy.Ignored)

        tab1 = QWidget()
        self.plainResponse = QTextEdit()
        tab1hbox = QHBoxLayout()
        tab1hbox.setContentsMargins(5, 5, 5, 5)
        tab1hbox.addWidget(self.plainResponse)
        tab1.setLayout(tab1hbox)

        tab2 = QWidget()
        self.tableResponse = QTableWidget(1, 2)
        self.tableResponse.setHorizontalHeaderLabels(["Property", "Value"])
        self.tableResponse.horizontalHeader().setStretchLastSection(True)
        tableLayout = QGridLayout()
        tableLayout.setContentsMargins(5, 5, 5, 5)
        tableLayout.addWidget(self.tableResponse, 0, 0)
        tab2.setLayout(tableLayout)

        tab3 = QWidget()
        self.listResponse = QTextEdit()
        tab3hbox = QHBoxLayout()
        tab3hbox.addWidget(self.listResponse)
        tab3.setLayout(tab3hbox)

        middleTabWidget.addTab(tab1, "Plain")
        middleTabWidget.addTab(tab2, "Properties")
        middleTabWidget.addTab(tab3, "List")

        layout = QGridLayout()
        layout.addWidget(middleTabWidget, 0, 0, 1, 1)

        self.middleGroupBox.setLayout(layout)

    def openLoginWindow(self):
        """
        Start login window
        """
        loginGui = LoginWindow(self)
        loginGui.startGui()

    def menuBarActions(self, q):
        action = q.text()
        if action == "New Window":
            pass
        if action == "Save to file":
            self.saveCommandToFile()
        if action == "Quit":
            self.closeApplication()
        if action == "Copy":
            self.copyToClipboard()
        if action == "Help":
            self.showHelp()
        if action == "About ISPAPI tool":
            self.showAbout()
        if action == "How to start?":
            self.showHelp()

    def closeApplication(self):
        print("exiting")
        sys.exit()

    def startNewWindow(self):
        app = QApplication(sys.argv)
        appGui = MainFrame()
        appGui.startGui()
        sys.exit(app.exec_())

    def startGui(self):
        geo = QDesktopWidget().availableGeometry()

        screenWidth = geo.width()
        screenHeight = geo.height()
        width = int(screenWidth * 0.5)
        height = int(screenHeight * 0.5)
        self.resize(width, height)

        frameGeo = self.frameGeometry()
        cp = geo.center()
        frameGeo.moveCenter(cp)
        self.move(frameGeo.topLeft())

        # start gui
        self.show()

    def initialiseCommandCompleter(self):
        model = QStringListModel()
        # get all possible autocomplete strings
        stringsSuggestion = []
        stringsSuggestion = (self.coreLogic.getCommandList()).splitlines()
        # set suggestion to the model
        model.setStringList(stringsSuggestion)
        # set model to the completer
        self.completer.setModel(model)

    def initialiseSubuserCompleter(self):
        model = QStringListModel()
        # get all possible autocomplete strings
        stringsSuggestion = []
        stringsSuggestion = (self.coreLogic.getSubUserList()).splitlines()
        # set suggestion to the model
        model.setStringList(stringsSuggestion)
        # set model to the completer
        self.subUsercompleter.setModel(model)

    def __clearCMDfield(self):
        self.cmdTxt.clear()
        self.cmdTxt.setFocus(True)

    def populateResults(self, response, mode="normal"):
        # get reulsts
        plainResult = response.getPlain()
        listResult = response.getListHash()

        # set plain results
        if mode == "iterative":
            self.plainResponse.append(plainResult)
            print("iternative")
        else:
            self.plainResponse.setText(plainResult)
            # delete any previous content of the list
            self.listResponse.setText("")

        # set properties and list
        resultLists = listResult["LIST"]
        counter = 0
        for row in resultLists:
            for col in row:
                counter += 1
        # set the number of rows
        self.tableResponse.setRowCount(counter)

        # populate the table
        rownumber = 0
        for row in resultLists:
            for i, (key, value) in enumerate(row.items()):
                keyWidget = QTableWidgetItem(key)
                valueWidget = QTableWidgetItem(value)
                self.tableResponse.setItem(rownumber, 0, keyWidget)
                self.tableResponse.setItem(rownumber, 1, valueWidget)
                # update the list
                if key not in ("TOTAL", "FIRST", "LAST", "LIMIT", "COUNT"):
                    self.listResponse.append(value)
                # incerate rownumber
                rownumber += 1
        # order table content
        self.tableResponse.sortItems(Qt.AscendingOrder)

    def saveCommandToFile(self):
        try:
            textToWrite = self.commandAndResponsePlain()
            options = QFileDialog.Options()
            # options |= QFileDialog.DontUseNativeDialog # Qt's builtin File Dialogue
            fileName, _ = QFileDialog.getSaveFileName(self,
                                                      "Open",
                                                      "report.txt",
                                                      "All Files (*.*)",
                                                      options=options)
            if fileName:
                try:
                    with open(fileName, "w") as file:
                        file.write(textToWrite)
                    alert = QMessageBox()
                    alert.setText("'" + fileName +
                                  "' \n\nFile Saved Successfully!")
                    alert.setIcon(QMessageBox.Information)
                    alert.exec_()
                except Exception as e:
                    alert = QMessageBox()
                    alert.setIcon(QMessageBox.Critical)
                    alert.setText("Couldn't save the file due to: " + str(e))
                    alert.exec_()
        except Exception as e:
            alert = QMessageBox()
            alert.setIcon(QMessageBox.Critical)
            alert.setText("Request a command first!")
            alert.setWindowTitle("Error")
            alert.exec_()

    def commandAndResponsePlain(self):
        result = self.plainResponse.toPlainText()
        command = self.response.getCommandPlain()
        textToWrite = command + "\n" + result
        return textToWrite

    def copyToClipboard(self):
        try:
            newText = self.commandAndResponsePlain()
            clipboard = QApplication.clipboard()
            clipboard.setText(newText)
        except Exception as e:
            print(e)
            pass  # in the case where there is not command requested

    def showHelp(self):
        box = QMessageBox(self)
        msg = """<p align='center'>
        <b style='font-size:20px'>Help Information</b>. <br><br><br>
        This window provides a simple help view, more detailed help can be found at: 
        <a href="https://hexonet.github.io/ispapicli/">ISPAPI CLI Tool Documentation</a>
        <br><br>
        Quick start:
        <br>
        To show help, type the command: -h | --help
        <br>
        From there you will find all information about using the command line in both the GUI and terminal
        <br><br>
        <span style="color:orange">Note</span>: Commands executed in terminal are similar to commands used in the GUI, except for the "--update" command which is only possible to trigger in the terminal
        <br><br><br>
        Copyright 2020 @Hexonet
        <br><br>
        </p>
        """
        box.setStandardButtons(QMessageBox.Ok)
        box.setIcon(QMessageBox.Information)
        box.setWindowTitle("Help")
        box.setText(msg)
        box.show()

    def showUpdating(self):
        box = QMessageBox(self)
        msg = """
        <p>Updating is done!</p>
        """
        box.setStandardButtons(QMessageBox.Ok)
        box.setIcon(QMessageBox.Information)
        box.setWindowTitle("Updating...")
        box.setText(msg)
        box.show()
        self.scrap.scrapCommands()
        # init tool dropdown autocomplete
        self.initialiseCommandCompleter()

    def Handle_Progress(self, blocknum, blocksize, totalsize):

        ## calculate the progress
        readed_data = blocknum * blocksize

        if totalsize > 0:
            download_percentage = readed_data * 100 / totalsize
            self.progressBar.setValue(download_percentage)
            QApplication.processEvents()

    def checkForUpdate(self):
        try:
            preBox = QMessageBox(self)
            msgNo = """<p align='center'>
                            Checking for update...
                        </p>
                    """
            # preBox.setStandardButtons(QMessageBox.Ok)
            preBox.setWindowTitle("Checking...")
            preBox.setText(msgNo)
            preBox.show()
            QApplication.processEvents()
            currentVersion = __version__
            url = "https://github.com/hexonet/ispapicli/releases/latest"
            r = requests.get(url)
            if r.ok:
                preBox.close()
                box = QMessageBox(self)
                # check if there is a new version available
                # increase the current version by 1 as it was not added in the semantic versioning
                # the bin generated before modifying the version files
                latestVersion = r.url.split("/")[-1]
                latestVersion = version.parse(latestVersion[1:])
                currentVersion = currentVersion.split(".")
                currentVersion[2] = str(int(currentVersion[2]) + 1)
                currentVersion = ".".join(currentVersion)
                currentVersion = version.parse(currentVersion)
                if currentVersion == latestVersion:
                    msgNo = """<p align='center'>
                            You have the latest version installed.
                            </p>
                            """
                    box.setStandardButtons(QMessageBox.Ok)
                    box.setWindowTitle("Updating")
                    box.setText(msgNo)
                    box.show()
                elif latestVersion > currentVersion:
                    msgYes = """<p align='center'>
                        New version available, update now?
                    </p>
                    """
                    ret = box.question(self, "Updating", msgYes,
                                       box.No | box.Yes, box.Yes)
                    if ret == box.Yes:
                        # updating the tool
                        self.updateTool(latestVersion)
                    else:
                        box.close()
                else:
                    return
            else:
                raise Exception
        except Exception:
            preBox = QMessageBox(self)
            msgNo = """<p align='center'>
                            Please check your internet connection.
                        </p>
                    """
            # preBox.setStandardButtons(QMessageBox.Ok)
            preBox.setWindowTitle("No Internet")
            preBox.setText(msgNo)
            preBox.show()

    def updateTool(self, latestVersion):
        fileName = ""
        if sys.platform == "win32":
            fileName = "win-binary-%s.zip" % str(latestVersion)
        elif sys.platform == "linux" or sys.platform == "darwin":
            fileName = "linux-binary-%s.zip" % str(latestVersion)
        else:
            return

        # init download
        url = "https://github.com/hexonet/ispapicli/releases/download/v%s/%s" % (
            latestVersion,
            fileName,
        )
        print(url)
        import urllib

        # Copy a network object to a local file
        try:
            # dwonload our zipped tool
            fileDownloaded, response = urllib.request.urlretrieve(
                url, fileName, self.Handle_Progress)
            if response and fileDownloaded:
                # unzip the tool
                import zipfile

                with zipfile.ZipFile(fileName, "r") as zip_ref:
                    result = zip_ref.extractall("tmp")
                    # start the new tool
                    if sys.platform == "win32" and result is None:
                        # updating the tool
                        newToolName = "ispapicli-%s" % str(
                            latestVersion) + ".exe"
                        # rename the newly donwloaded tool
                        os.rename(r"tmp/ispapicli.exe", newToolName)
                        # clean the directoy
                        os.remove(fileDownloaded)
                        os.rmdir("tmp")
                        # start the new tool
                        os.system("" + newToolName)
                        self.closeApplication()
                    elif (sys.platform == "linux"
                          or sys.platform == "darwin") and result is None:
                        newToolName = "ispapicli-%s" % str(latestVersion)
                        # rename the newly donwloaded tool
                        os.rename(r"tmp/ispapicli", newToolName)
                        # clean the directoy
                        os.remove(fileDownloaded)
                        os.rmdir("tmp")
                        # updating the tool
                        os.system("sudo chmod +x " + newToolName)
                        os.system("./" + newToolName + " &")
                        self.closeApplication()
                        # TODO clean the old version by sending an argument
                        # process = subprocess.Popen(
                        #    ["sudo chmod +x " + newToolName, "./" + newToolName]
                        # )
                    else:
                        return

                    # upon success
                    # finalBox = QMessageBox(self)
                    # msgYes = """<p align='center'>
                    #     Update finished, close now?
                    # </p>
                    # """
                    # ret = finalBox.question(
                    #     self,
                    #     "Updating",
                    #     msgYes,
                    #     finalBox.No | finalBox.Yes,
                    #     finalBox.Yes,
                    # )
                    # if ret == finalBox.Yes:
                    #     # updating the tool
                    #     self.closeApplication()
                    # else:
                    #     finalBox.close()
            else:
                raise Exception
        except Exception as e:
            msgBox = QMessageBox(self)
            msgNo = ("""<p align='center'>
                            Problem to download: %s
                        </p>
                    """ % e)
            # preBox.setStandardButtons(QMessageBox.Ok)
            msgBox.setWindowTitle("Download")
            msgBox.setText(msgNo)
            msgBox.show()
            # os.system(
            #     "gnome-terminal -- bash -c './" + scriptPath + latestVersion + ";bash'"
            # )

    def showAbout(self):

        box = QMessageBox(self)
        msg = """<p align='center'>
        <b style='font-size:20px'>ISPAPI Tool</b>. <br><br><br>
        Version: %s <br><br>
        A simple command line interface to connect you to your account on Hexonet
        <br><br>
        Technical Support:
        <br>
        Email: [email protected] 
        <br>
        Website: <a href="https://hexonet.github.io/ispapicli/">ISPAPI CLI Tool</a>
        <br><br><br>
        Copyright 2020 @Hexonet
        <br><br>
        </p>
        """

        box.setStandardButtons(QMessageBox.Ok)
        # box.setIcon(QMessageBox.Information)
        box.setWindowTitle("About")
        box.setText(msg % __version__)
        box.show()

    def eventFilter(self, source, event):

        # this function to handle autocomplete for command line
        if event.type() == QEvent.KeyRelease and source is self.cmdTxt:
            if event.key() == Qt.Key_Space:
                # show min paramters suggestions
                try:
                    cmd = self.cmdTxt.text()
                    m = re.match("^(\w+)\s$", cmd)
                    if m:
                        minParams = self.coreLogic.getMinParameters(
                            cmd.strip())
                        if len(minParams) > 0:
                            minParamsLabel = ", ".join(minParams)
                            minParamsInput = "= ".join(minParams)
                            cursorPosition = (
                                len(self.cmdTxt.text() + minParams[0]) + 1
                            )  # for the '=' char
                            self.cmdTxt.setText(cmd + minParamsInput + "=")
                            self.minParameter.setText("Min parameters: " +
                                                      minParamsLabel)
                            self.cmdTxt.setCursorPosition(cursorPosition)
                        else:
                            self.minParameter.setText("Min parameters:")
                except Exception as e:
                    print(e)
        # must return bool value
        return super(MainFrame, self).eventFilter(source, event)

    def getIcon(self, iconName):
        ##
        # This function checks if the app is executable or in development and return the path

        if getattr(sys, "frozen", False):
            self.absolute_dirpath = os.path.dirname(sys.executable)
            try:
                self.absolute_dirpath = sys._MEIPASS
            except Exception:
                self.absolute_dirpath = os.path.abspath(".")
            path = self.command_path = os.path.join(self.absolute_dirpath,
                                                    "data/icons/" + iconName)
        elif __file__:
            self.absolute_dirpath = os.path.dirname(__file__)
            path = self.command_path = os.path.join(self.absolute_dirpath,
                                                    "../icons/" + iconName)
        return path

    def getScriptsPath(self, system):
        """
        Return the script path
        """
        path = "scripts/"
        # scripts/linux-download.sh
        # check which platform
        if system == "linux":
            path = path + "linux-download.sh"
        elif system == "windows":
            path = path + "win-download.ps1"
        else:
            raise Exception
        return path