Ejemplo n.º 1
0
    def updateHWstatus(self, ctrl):
        if self.hwdevice is not None:
            if hasattr(self.hwdevice, 'dongle'):
                self.hwdevice.dongle.close()

        self.hwdevice = HWdevice()

        statusCode, statusMess = self.hwdevice.getStatus()
        printDbg("mess: %s" % statusMess)
        if statusCode != 2:
            # If is not connected try again
            try:
                if hasattr(self.hwdevice, 'dongle'):
                    self.hwdevice.dongle.close()
                self.hwdevice = HWdevice()
                self.hwdevice.initDevice()
                statusCode, statusMess = self.hwdevice.getStatus()

            except Exception as e:
                err_msg = "error in checkHw"
                printException(getCallerName(), getFunctionName(), err_msg,
                               e.args)

        self.hwStatus = statusCode
        self.hwStatusMess = statusMess
Ejemplo n.º 2
0
    def updateHWstatus(self, ctrl):
        if self.hwdevice is not None:
            if hasattr(self.hwdevice, 'dongle'):
                self.hwdevice.dongle.close()

        self.hwdevice = HWdevice()

        statusCode, statusMess = self.hwdevice.getStatus()
        printDbg("mess: %s" % statusMess)
        if statusCode != 2:
            # If is not connected try again
            try:
                if hasattr(self.hwdevice, 'dongle'):
                    self.hwdevice.dongle.close()
                self.hwdevice = HWdevice()
                self.hwdevice.initDevice()
                statusCode, statusMess = self.hwdevice.getStatus()

            except Exception as e:
                err_msg = "error in checkHw"
                printException(getCallerName(), getFunctionName(), err_msg, e.args)

        self.hwStatus = statusCode
        self.hwStatusMess = statusMess

        # if all is good connect the signals
        if statusCode == 2:
            self.hwdevice.sigTxdone.connect(self.t_rewards.FinishSend)
            self.hwdevice.sigTxabort.connect(self.t_rewards.onCancel)
            self.hwdevice.tx_progress.connect(self.t_rewards.updateProgressPercent)
Ejemplo n.º 3
0
 def setUp(self):
     self.device = HWdevice()
     self.rpcClient = RpcClient()
     hwStatus = self.device.getStatusCode()
     rpcStatus, _ = self.rpcClient.getStatus()
     if hwStatus != 2:
         self.skipTest("Ledger not connected or pivx app closed")
     if not rpcStatus:
         self.skipTest("RPC not connected")
Ejemplo n.º 4
0
    def updateHWstatus(self, ctrl):          
        if self.hwdevice is None:
            self.hwdevice = HWdevice()
        
        device = self.hwdevice
        statusCode = device.getStatusCode()
        statusMess = device.getStatusMess(statusCode)
        printDbg("code: %s - mess: %s" % (statusCode, statusMess))
        if statusCode != 2:
            try:
                if getattr(self.hwdevice, 'dongle', None) is not None:
                    self.hwdevice.dongle.close()
                self.hwdevice.initDevice()
                device = self.hwdevice
                statusCode = device.getStatusCode()
                statusMess = device.getStatusMess(statusCode)

            except Exception as e:
                err_msg = "error in checkHw"
                printException(getCallerName(), getFunctionName(), err_msg, e.args)
                    
        self.hwStatus = statusCode
        self.hwStatusMess = statusMess
Ejemplo n.º 5
0
class MainWindow(QWidget):
    def __init__(self, parent, imgDir):
        super(QWidget, self).__init__(parent)
        self.parent = parent
        self.imgDir = imgDir
        self.runInThread = ThreadFuns.runInThread
        ###-- Create clients and statuses
        self.hwdevice = None
        self.hwStatus = 0
        self.hwStatusMess = "Not Connected"
        self.rpcClient = None
        self.rpcConnected = False
        self.rpcStatusMess = "Not Connected"
        ###-- Load icons & images
        self.loadIcons()
        ###-- Create main layout
        self.layout = QVBoxLayout()
        self.header = GuiHeader(self)
        self.initConsole()
        self.layout.addWidget(self.header)
        ###-- Create RPC Whatchdog
        self.rpc_watchdogThread = QThread()
        self.myRpcWd = RpcWatchdog(self)
        self.myRpcWd.moveToThread(self.rpc_watchdogThread)
        self.rpc_watchdogThread.started.connect(self.myRpcWd.run)
        self.rpc_watchdogThread.start()

        ###-- Create Queues and redirect stdout and stderr (eventually)
        self.queue = Queue()
        self.queue2 = Queue()
        sys.stdout = WriteStream(self.queue)
        sys.stderr = WriteStream(self.queue2)

        ###-- Init last logs
        logFile = open(log_File, 'w+')
        timestamp = strftime('%Y-%m-%d %H:%M:%S', gmtime(now()))
        log_line = '<b style="color: blue">{}</b><br>'.format(
            'STARTING PET4L at ' + timestamp)
        logFile.write(log_line)
        logFile.close()

        ###-- Create the thread to update console log for stdout
        self.consoleLogThread = QThread()
        self.myWSReceiver = WriteStreamReceiver(self.queue)
        self.myWSReceiver.mysignal.connect(self.append_to_console)
        self.myWSReceiver.moveToThread(self.consoleLogThread)
        self.consoleLogThread.started.connect(self.myWSReceiver.run)
        self.consoleLogThread.start()
        printDbg("Console Log thread started")
        ###-- Create the thread to update console log for stderr
        self.consoleLogThread2 = QThread()
        self.myWSReceiver2 = WriteStreamReceiver(self.queue2)
        self.myWSReceiver2.mysignal.connect(self.append_to_console)
        self.myWSReceiver2.moveToThread(self.consoleLogThread2)
        self.consoleLogThread2.started.connect(self.myWSReceiver2.run)
        self.consoleLogThread2.start()
        printDbg("Console Log thread 2 started")

        ###-- Initialize tabs
        self.tabs = QTabWidget()
        self.t_rewards = TabRewards(self)
        ###-- Add tabs
        self.tabs.addTab(self.tabRewards, "Spend from Ledger")
        ###-- Draw Tabs
        self.splitter = QSplitter(Qt.Vertical)
        ###-- Add tabs and console to Layout
        self.splitter.addWidget(self.tabs)
        self.splitter.addWidget(self.console)
        self.splitter.setStretchFactor(0, 0)
        self.splitter.setStretchFactor(1, 1)
        self.splitter.setSizes([2, 1])
        self.layout.addWidget(self.splitter)
        ###-- Set Layout
        self.setLayout(self.layout)
        ###-- Let's go
        self.mnode_to_change = None
        printOK("Hello! Welcome to " + parent.title)

    @pyqtSlot(str)
    def append_to_console(self, text):
        self.consoleArea.moveCursor(QTextCursor.End)
        self.consoleArea.insertHtml(text)
        # update last logs
        logFile = open(log_File, 'a+')
        logFile.write(text)
        logFile.close()

    def initConsole(self):
        self.console = QGroupBox()
        self.console.setTitle("Console Log")
        layout = QVBoxLayout()
        self.btn_consoleToggle = QPushButton('Hide')
        self.btn_consoleToggle.setToolTip('Show/Hide console')
        self.btn_consoleToggle.clicked.connect(lambda: self.onToggleConsole())
        consoleHeader = QHBoxLayout()
        consoleHeader.addWidget(self.btn_consoleToggle)
        self.consoleSaveButton = QPushButton('Save')
        self.consoleSaveButton.clicked.connect(lambda: self.onSaveConsole())
        consoleHeader.addWidget(self.consoleSaveButton)
        self.btn_consoleClean = QPushButton('Clean')
        self.btn_consoleClean.setToolTip('Clean console log area')
        self.btn_consoleClean.clicked.connect(lambda: self.onCleanConsole())
        consoleHeader.addWidget(self.btn_consoleClean)
        consoleHeader.addStretch(1)
        layout.addLayout(consoleHeader)
        self.consoleArea = QTextEdit()
        almostBlack = QColor(40, 40, 40)
        palette = QPalette()
        palette.setColor(QPalette.Base, almostBlack)
        green = QColor(0, 255, 0)
        palette.setColor(QPalette.Text, green)
        self.consoleArea.setPalette(palette)
        layout.addWidget(self.consoleArea)
        self.console.setLayout(layout)

    def loadIcons(self):
        # Load Icons
        self.ledPurpleH_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_purpleLedH.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledGrayH_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_grayLedH.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledHalfPurpleH_icon = QPixmap(
            os.path.join(self.imgDir,
                         'icon_halfPurpleLedH.png')).scaledToHeight(
                             17, Qt.SmoothTransformation)
        self.ledRedV_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_redLedV.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledGrayV_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_grayLedV.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledGreenV_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_greenLedV.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledgerImg = QPixmap(os.path.join(self.imgDir, 'ledger.png'))

    def myPopUp(self,
                messType,
                messTitle,
                messText,
                defaultButton=QMessageBox.No):
        mess = QMessageBox(messType,
                           messTitle,
                           messText,
                           defaultButton,
                           parent=self)
        mess.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        mess.setDefaultButton(defaultButton)
        return mess.exec_()

    def myPopUp2(self,
                 messType,
                 messTitle,
                 messText,
                 singleButton=QMessageBox.Ok):
        mess = QMessageBox(messType,
                           messTitle,
                           messText,
                           singleButton,
                           parent=self)
        mess.setStandardButtons(singleButton | singleButton)
        return mess.exec_()

    @pyqtSlot()
    def onCheckHw(self):
        printDbg("Checking for HW device...")
        self.runInThread(self.updateHWstatus, (), self.showHWstatus)

    @pyqtSlot()
    def onCheckRpc(self):
        printDbg("Checking RPC server...")
        self.runInThread(self.updateRPCstatus, (), self.showRPCstatus)

    @pyqtSlot()
    def onCleanConsole(self):
        self.consoleArea.clear()

    @pyqtSlot()
    def onSaveConsole(self):
        timestamp = strftime('%Y-%m-%d_%H-%M-%S', gmtime(now()))
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getSaveFileName(
            self,
            "Save Logs to file",
            "PET4L_Logs_%s.txt" % timestamp,
            "All Files (*);; Text Files (*.txt)",
            options=options)
        try:
            if fileName:
                printOK("Saving logs to %s" % fileName)
                log_file = open(fileName, 'w+')
                log_text = self.consoleArea.toPlainText()
                log_file.write(log_text)
                log_file.close()

        except Exception as e:
            err_msg = "error writing Log file"
            printException(getCallerName(), getFunctionName(), err_msg, e.args)

    @pyqtSlot()
    def onToggleConsole(self):
        if self.btn_consoleToggle.text() == 'Hide':
            self.btn_consoleToggle.setText('Show')
            self.consoleArea.hide()
            self.previousH = self.splitter.sizes()[1]
            self.console.setMaximumHeight(70)
        else:
            self.console.setMinimumHeight(self.previousH)
            self.console.setMaximumHeight(starting_height)
            self.btn_consoleToggle.setText('Hide')
            self.consoleArea.show()

    def showHWstatus(self):
        self.updateHWleds()
        self.myPopUp2(QMessageBox.Information, 'PET4L - hw check',
                      "STATUS: %s" % self.hwStatusMess, QMessageBox.Ok)

    def showRPCstatus(self):
        self.updateRPCled()
        self.myPopUp2(QMessageBox.Information, 'PET4L - rpc check',
                      "STATUS: %s" % self.rpcStatusMess, QMessageBox.Ok)

    def updateHWleds(self):
        if self.hwStatus == 1:
            self.header.hwLed.setPixmap(self.ledHalfPurpleH_icon)
        elif self.hwStatus == 2:
            self.header.hwLed.setPixmap(self.ledPurpleH_icon)
        else:
            self.header.hwLed.setPixmap(self.ledGrayH_icon)
        self.header.hwLed.setToolTip(self.hwStatusMess)

    def updateHWstatus(self, ctrl):
        if self.hwdevice is None:
            self.hwdevice = HWdevice()

        device = self.hwdevice
        statusCode = device.getStatusCode()
        statusMess = device.getStatusMess(statusCode)
        printDbg("code: %s - mess: %s" % (statusCode, statusMess))
        if statusCode != 2:
            try:
                if getattr(self.hwdevice, 'dongle', None) is not None:
                    self.hwdevice.dongle.close()
                self.hwdevice.initDevice()
                device = self.hwdevice
                statusCode = device.getStatusCode()
                statusMess = device.getStatusMess(statusCode)

            except Exception as e:
                err_msg = "error in checkHw"
                printException(getCallerName(), getFunctionName(), err_msg,
                               e.args)

        self.hwStatus = statusCode
        self.hwStatusMess = statusMess

    def updateLastBlockLabel(self):
        text = '--'
        if self.rpcLastBlock == 1:
            text = "Loading block index..."
        elif self.rpcLastBlock > 0 and self.rpcConnected:
            text = str(self.rpcLastBlock)

        self.header.lastBlockLabel.setText(text)

    def updateRPCled(self):
        if self.rpcConnected:
            self.header.rpcLed.setPixmap(self.ledPurpleH_icon)
        else:
            if self.rpcLastBlock == 1:
                self.header.rpcLed.setPixmap(self.ledHalfPurpleH_icon)
            else:
                self.header.rpcLed.setPixmap(self.ledGrayH_icon)

        self.header.rpcLed.setToolTip(self.rpcStatusMess)
        self.updateLastBlockLabel()

    def updateRPCstatus(self, ctrl):
        if self.rpcClient is None:
            try:
                self.rpcClient = RpcClient()
            except Exception as e:
                print(e)
        status, lastBlock = self.rpcClient.getStatus()
        statusMess = self.rpcClient.getStatusMess(status)
        if not status and lastBlock == 0:
            try:
                self.rpcClient = RpcClient()
                status, lastBlock = self.rpcClient.getStatus()
                statusMess = self.rpcClient.getStatusMess(status)
            except Exception as e:
                err_msg = "error in checkRpc"
                printException(getCallerName(), getFunctionName(), err_msg, e)

        elif lastBlock == 1:
            statusMess = "PIVX wallet is connected but still synchronizing / verifying blocks"

        self.rpcConnected = status
        self.rpcLastBlock = lastBlock
        self.rpcStatusMess = statusMess
Ejemplo n.º 6
0
    def __init__(self, parent, imgDir):
        super(QWidget, self).__init__(parent)
        self.parent = parent
        self.imgDir = imgDir
        self.runInThread = ThreadFuns.runInThread
        self.lock = threading.Lock()

        # -- Create clients and statuses
        self.hwStatus = 0
        self.hwModel = 0
        self.hwStatusMess = "Not Connected"
        self.rpcClient = None
        self.rpcConnected = False
        self.updatingRPCbox = False
        self.rpcStatusMess = "Not Connected"
        self.isBlockchainSynced = False
        # Changes when an RPC client is connected (affecting API client)
        self.isTestnetRPC = self.parent.cache['isTestnetRPC']

        # -- Load icons & images
        self.loadIcons()
        # -- Create main layout
        self.layout = QVBoxLayout()
        self.header = GuiHeader(self)
        self.initConsole()
        self.layout.addWidget(self.header)

        # -- Load RPC Servers list (init selection and self.isTestnet)
        self.updateRPClist()

        # -- Init HW selection
        self.header.hwDevices.setCurrentIndex(
            self.parent.cache['selectedHW_index'])

        # -- init HW Client
        self.hwdevice = HWdevice(self)

        # -- init Api Client
        self.apiClient = ApiClient(self.isTestnetRPC)

        # -- Create Queue to redirect stdout
        self.queue = wqueue

        # -- Init last logs
        logging.debug("STARTING PET4L")

        # -- Create the thread to update console log for stdout
        self.consoleLogThread = QThread()
        self.myWSReceiver = WriteStreamReceiver(self.queue)
        self.myWSReceiver.mysignal.connect(self.append_to_console)
        self.myWSReceiver.moveToThread(self.consoleLogThread)
        self.consoleLogThread.started.connect(self.myWSReceiver.run)
        self.consoleLogThread.start()
        printDbg("Console Log thread started")

        # -- Initialize tabs (single QLayout here)
        self.tabs = QTabWidget()
        self.t_rewards = TabRewards(self)
        # -- Add tabs
        self.tabs.addTab(self.tabRewards, self.parent.spmtIcon, "Spend")
        # -- Draw Tabs
        self.splitter = QSplitter(Qt.Vertical)
        # -- Add tabs and console to Layout
        self.splitter.addWidget(self.tabs)
        self.splitter.addWidget(self.console)
        self.splitter.setStretchFactor(0, 0)
        self.splitter.setStretchFactor(1, 1)
        self.splitter.setSizes([2, 1])
        self.layout.addWidget(self.splitter)

        # -- Set Layout
        self.setLayout(self.layout)

        # -- Init Settings
        self.initSettings()

        # -- Connect buttons/signals
        self.connButtons()

        # -- Create RPC Whatchdog
        self.rpc_watchdogThread = QThread()
        self.myRpcWd = RpcWatchdog(self)
        self.myRpcWd.moveToThread(self.rpc_watchdogThread)
        self.rpc_watchdogThread.started.connect(self.myRpcWd.run)

        # -- Let's go
        self.mnode_to_change = None
        printOK("Hello! Welcome to " + parent.title)
Ejemplo n.º 7
0
class MainWindow(QWidget):
    # signal: clear RPC status label and icons (emitted by updateRPCstatus)
    sig_clearRPCstatus = pyqtSignal()

    # signal: RPC status (for server id) is changed (emitted by updateRPCstatus)
    sig_RPCstatusUpdated = pyqtSignal(int, bool)

    # signal: RPC list has been reloaded (emitted by updateRPClist)
    sig_RPClistReloaded = pyqtSignal()

    # signal: UTXO list loading percent (emitted by load_utxos_thread in tabRewards)
    sig_UTXOsLoading = pyqtSignal(int)

    def __init__(self, parent, imgDir):
        super(QWidget, self).__init__(parent)
        self.parent = parent
        self.imgDir = imgDir
        self.runInThread = ThreadFuns.runInThread
        self.lock = threading.Lock()

        # -- Create clients and statuses
        self.hwStatus = 0
        self.hwModel = 0
        self.hwStatusMess = "Not Connected"
        self.rpcClient = None
        self.rpcConnected = False
        self.updatingRPCbox = False
        self.rpcStatusMess = "Not Connected"
        self.isBlockchainSynced = False
        # Changes when an RPC client is connected (affecting API client)
        self.isTestnetRPC = self.parent.cache['isTestnetRPC']

        # -- Load icons & images
        self.loadIcons()
        # -- Create main layout
        self.layout = QVBoxLayout()
        self.header = GuiHeader(self)
        self.initConsole()
        self.layout.addWidget(self.header)

        # -- Load RPC Servers list (init selection and self.isTestnet)
        self.updateRPClist()

        # -- Init HW selection
        self.header.hwDevices.setCurrentIndex(
            self.parent.cache['selectedHW_index'])

        # -- init HW Client
        self.hwdevice = HWdevice(self)

        # -- init Api Client
        self.apiClient = ApiClient(self.isTestnetRPC)

        # -- Create Queue to redirect stdout
        self.queue = wqueue

        # -- Init last logs
        logging.debug("STARTING PET4L")

        # -- Create the thread to update console log for stdout
        self.consoleLogThread = QThread()
        self.myWSReceiver = WriteStreamReceiver(self.queue)
        self.myWSReceiver.mysignal.connect(self.append_to_console)
        self.myWSReceiver.moveToThread(self.consoleLogThread)
        self.consoleLogThread.started.connect(self.myWSReceiver.run)
        self.consoleLogThread.start()
        printDbg("Console Log thread started")

        # -- Initialize tabs (single QLayout here)
        self.tabs = QTabWidget()
        self.t_rewards = TabRewards(self)
        # -- Add tabs
        self.tabs.addTab(self.tabRewards, self.parent.spmtIcon, "Spend")
        # -- Draw Tabs
        self.splitter = QSplitter(Qt.Vertical)
        # -- Add tabs and console to Layout
        self.splitter.addWidget(self.tabs)
        self.splitter.addWidget(self.console)
        self.splitter.setStretchFactor(0, 0)
        self.splitter.setStretchFactor(1, 1)
        self.splitter.setSizes([2, 1])
        self.layout.addWidget(self.splitter)

        # -- Set Layout
        self.setLayout(self.layout)

        # -- Init Settings
        self.initSettings()

        # -- Connect buttons/signals
        self.connButtons()

        # -- Create RPC Whatchdog
        self.rpc_watchdogThread = QThread()
        self.myRpcWd = RpcWatchdog(self)
        self.myRpcWd.moveToThread(self.rpc_watchdogThread)
        self.rpc_watchdogThread.started.connect(self.myRpcWd.run)

        # -- Let's go
        self.mnode_to_change = None
        printOK("Hello! Welcome to " + parent.title)

    def append_to_console(self, text):
        self.consoleArea.moveCursor(QTextCursor.End)
        self.consoleArea.insertHtml(text)

    def clearHWstatus(self, message=''):
        self.hwStatus = 0
        self.hwStatusMess = "Not Connected"
        self.header.hwLed.setPixmap(self.ledGrayH_icon)
        if message != '':
            self.hwStatus = 1
            myPopUp_sb(self, "crit", "hw device Disconnected", message)

    def clearRPCstatus(self):
        with self.lock:
            self.rpcConnected = False
            self.header.lastPingBox.setHidden(False)
            self.header.rpcLed.setPixmap(self.ledGrayH_icon)
            self.header.lastBlockLabel.setText("<em>Connecting...</em>")
            self.header.lastPingIcon.setPixmap(self.connRed_icon)
            self.header.responseTimeLabel.setText("--")
            self.header.responseTimeLabel.setStyleSheet("color: red")
            self.header.lastPingIcon.setStyleSheet("color: red")

    def connButtons(self):
        self.header.button_checkRpc.clicked.connect(lambda: self.onCheckRpc())
        self.header.button_checkHw.clicked.connect(lambda: self.onCheckHw())
        self.header.rpcClientsBox.currentIndexChanged.connect(
            self.onChangeSelectedRPC)
        self.header.hwDevices.currentIndexChanged.connect(
            self.onChangeSelectedHW)
        # -- Connect signals
        self.sig_clearRPCstatus.connect(self.clearRPCstatus)
        self.sig_RPCstatusUpdated.connect(self.showRPCstatus)
        self.parent.sig_changed_rpcServers.connect(self.updateRPClist)

    def getRPCserver(self):
        itemData = self.header.rpcClientsBox.itemData(
            self.header.rpcClientsBox.currentIndex())
        rpc_index = self.header.rpcClientsBox.currentIndex()
        rpc_protocol = itemData["protocol"]
        rpc_host = itemData["host"]
        rpc_user = itemData["user"]
        rpc_password = itemData["password"]

        return rpc_index, rpc_protocol, rpc_host, rpc_user, rpc_password

    def getServerListIndex(self, server):
        return self.header.rpcClientsBox.findData(server)

    def initConsole(self):
        self.console = QGroupBox()
        self.console.setTitle("Console Log")
        layout = QVBoxLayout()
        self.btn_consoleToggle = QPushButton('Hide')
        self.btn_consoleToggle.setToolTip('Show/Hide console')
        self.btn_consoleToggle.clicked.connect(lambda: self.onToggleConsole())
        consoleHeader = QHBoxLayout()
        consoleHeader.addWidget(self.btn_consoleToggle)
        self.consoleSaveButton = QPushButton('Save')
        self.consoleSaveButton.clicked.connect(lambda: self.onSaveConsole())
        consoleHeader.addWidget(self.consoleSaveButton)
        self.btn_consoleClean = QPushButton('Clean')
        self.btn_consoleClean.setToolTip('Clean console log area')
        self.btn_consoleClean.clicked.connect(lambda: self.onCleanConsole())
        consoleHeader.addWidget(self.btn_consoleClean)
        consoleHeader.addStretch(1)
        self.versionLabel = QLabel("--")
        self.versionLabel.setOpenExternalLinks(True)
        consoleHeader.addWidget(self.versionLabel)
        self.btn_checkVersion = QPushButton("Check PET4L version")
        self.btn_checkVersion.setToolTip(
            "Check latest stable release of PET4L")
        self.btn_checkVersion.clicked.connect(lambda: self.onCheckVersion())
        consoleHeader.addWidget(self.btn_checkVersion)
        layout.addLayout(consoleHeader)
        self.consoleArea = QTextEdit()
        self.consoleArea.setReadOnly(True)
        almostBlack = QColor(40, 40, 40)
        palette = QPalette()
        palette.setColor(QPalette.Base, almostBlack)
        green = QColor(0, 255, 0)
        palette.setColor(QPalette.Text, green)
        self.consoleArea.setPalette(palette)
        layout.addWidget(self.consoleArea)
        self.console.setLayout(layout)

    def initSettings(self):
        self.splitter.setSizes([
            self.parent.cache.get("splitter_x"),
            self.parent.cache.get("splitter_y")
        ])
        # -- Hide console if it was previously hidden
        if self.parent.cache.get("console_hidden"):
            self.onToggleConsole()

    def loadIcons(self):
        # Load Icons
        self.ledPurpleH_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_purpleLedH.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledGrayH_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_grayLedH.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledHalfPurpleH_icon = QPixmap(
            os.path.join(self.imgDir,
                         'icon_halfPurpleLedH.png')).scaledToHeight(
                             17, Qt.SmoothTransformation)
        self.lastBlock_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_lastBlock.png')).scaledToHeight(
                15, Qt.SmoothTransformation)
        self.connGreen_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_greenConn.png')).scaledToHeight(
                15, Qt.SmoothTransformation)
        self.connRed_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_redConn.png')).scaledToHeight(
                15, Qt.SmoothTransformation)
        self.connOrange_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_orangeConn.png')).scaledToHeight(
                15, Qt.SmoothTransformation)
        self.removeMN_icon = QIcon(os.path.join(self.imgDir,
                                                'icon_delete.png'))
        self.editMN_icon = QIcon(os.path.join(self.imgDir, 'icon_edit.png'))
        self.ledgerImg = QPixmap(os.path.join(self.imgDir, 'ledger.png'))
        self.trezorImg = QPixmap(os.path.join(self.imgDir, 'trezorModT.png'))
        self.trezorOneImg = QPixmap(os.path.join(self.imgDir, 'trezorOne.png'))
        self.coldStaking_icon = QIcon(
            os.path.join(self.imgDir, 'icon_coldstaking.png'))
        self.copy_icon = QIcon(os.path.join(self.imgDir, 'icon_copy.png'))

    def onCheckHw(self):
        printDbg("Checking for HW device...")
        self.updateHWstatus(None)
        self.showHWstatus()

    def onCheckRpc(self):
        self.runInThread(
            self.updateRPCstatus,
            (True, ),
        )

    def onCheckVersion(self):
        printDbg("Checking PET4L version...")
        self.versionLabel.setText("--")
        self.runInThread(self.checkVersion, (), self.updateVersion)

    def checkVersion(self, ctrl):
        local_version = self.parent.version['number'].split('.')
        self.gitVersion = getRemotePET4Lversion()
        remote_version = self.gitVersion.split('.')

        if (remote_version[0] > local_version[0]) or \
                (remote_version[0] == local_version[0] and remote_version[1] > local_version[1]) or \
                (remote_version[0] == local_version[0] and remote_version[1] == local_version[1] and remote_version[2] >
                 local_version[2]):
            self.versionMess = '<b style="color:red">New Version Available:</b> %s  ' % (
                self.gitVersion)
            self.versionMess += '(<a href="https://github.com/PIVX-Project/PET4L/releases/">download</a>)'
        else:
            self.versionMess = "You have the latest version of PET4L"

    def updateVersion(self):
        if self.versionMess is not None:
            self.versionLabel.setText(self.versionMess)
        printOK("Remote version: %s" % str(self.gitVersion))

    def onChangeSelectedHW(self, i):
        # Clear status
        self.clearHWstatus()

        # Persist setting
        self.parent.cache['selectedHW_index'] = persistCacheSetting(
            'cache_HWindex', i)

    def onChangeSelectedRPC(self, i):
        # Don't update when we are clearing the box
        if not self.updatingRPCbox:
            # persist setting
            self.parent.cache['selectedRPC_index'] = persistCacheSetting(
                'cache_RPCindex', i)
            self.runInThread(
                self.updateRPCstatus,
                (True, ),
            )

    def onCleanConsole(self):
        self.consoleArea.clear()

    def onSaveConsole(self):
        timestamp = strftime('%Y-%m-%d_%H-%M-%S', gmtime(now()))
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getSaveFileName(
            self,
            "Save Logs to file",
            "PET4L_Logs_%s.txt" % timestamp,
            "All Files (*);; Text Files (*.txt)",
            options=options)
        try:
            if fileName:
                printOK("Saving logs to %s" % fileName)
                log_file = open(fileName, 'w+', encoding="utf-8")
                log_text = self.consoleArea.toPlainText()
                log_file.write(log_text)
                log_file.close()

        except Exception as e:
            err_msg = "error writing Log file"
            printException(getCallerName(), getFunctionName(), err_msg, e.args)

    def onToggleConsole(self):
        if self.btn_consoleToggle.text() == 'Hide':
            self.btn_consoleToggle.setText('Show')
            self.consoleArea.hide()
            self.console.setMinimumHeight(70)
            self.console.setMaximumHeight(70)
        else:
            self.console.setMinimumHeight(70)
            self.console.setMaximumHeight(starting_height)
            self.btn_consoleToggle.setText('Hide')
            self.consoleArea.show()

    def showHWstatus(self):
        self.updateHWleds()
        myPopUp_sb(self, "info", 'PET4L - hw check', "%s" % self.hwStatusMess)

    def showRPCstatus(self, server_index, fDebug):
        # Update displayed status only if selected server is not changed
        if server_index == self.header.rpcClientsBox.currentIndex():
            self.updateRPCled(fDebug)
            if fDebug:
                myPopUp_sb(self, "info", 'PET4L - rpc check',
                           "%s" % self.rpcStatusMess)

    def updateHWleds(self):
        if self.hwStatus == 1:
            self.header.hwLed.setPixmap(self.ledHalfPurpleH_icon)
        elif self.hwStatus == 2:
            self.header.hwLed.setPixmap(self.ledPurpleH_icon)
        else:
            self.header.hwLed.setPixmap(self.ledGrayH_icon)
        self.header.hwLed.setToolTip(self.hwStatusMess)

    def updateHWstatus(self, ctrl):
        # re-initialize device
        try:
            self.hwdevice.initDevice(self.header.hwDevices.currentIndex())
            self.hwModel, self.hwStatus, self.hwStatusMess = self.hwdevice.getStatus(
            )
        except Exception as e:
            printDbg(str(e))
            pass

        printDbg("status:%s - mess: %s" % (self.hwStatus, self.hwStatusMess))

    def updateLastBlockLabel(self):
        text = '--'
        if self.rpcLastBlock == 1:
            text = "Loading block index..."
        elif self.rpcConnected and self.rpcLastBlock > 0:
            text = str(self.rpcLastBlock)
            if not self.isBlockchainSynced:
                text += " (Synchronizing)"

        self.header.lastBlockLabel.setText(text)

    def updateLastBlockPing(self):
        if not self.rpcConnected:
            self.header.lastPingBox.setHidden(True)
        else:
            self.header.lastPingBox.setHidden(False)
            if self.rpcResponseTime > 2:
                color = "red"
                self.header.lastPingIcon.setPixmap(self.connRed_icon)
            elif self.rpcResponseTime > 1:
                color = "orange"
                self.header.lastPingIcon.setPixmap(self.connOrange_icon)
            else:
                color = "green"
                self.header.lastPingIcon.setPixmap(self.connGreen_icon)
            if self.rpcResponseTime is not None:
                self.header.responseTimeLabel.setText("%.3f" %
                                                      self.rpcResponseTime)
                self.header.responseTimeLabel.setStyleSheet("color: %s" %
                                                            color)
                self.header.lastPingIcon.setStyleSheet("color: %s" % color)

    def updateRPCled(self, fDebug=False):
        if self.rpcConnected:
            self.header.rpcLed.setPixmap(self.ledPurpleH_icon)
            if fDebug:
                printDbg("Connected to RPC server.")
        else:
            if self.rpcLastBlock == 1:
                self.header.rpcLed.setPixmap(self.ledHalfPurpleH_icon)
                if fDebug:
                    printDbg("Connected to RPC server - Still syncing...")
            else:
                self.header.rpcLed.setPixmap(self.ledGrayH_icon)
                if fDebug:
                    printDbg("Connection to RPC server failed.")

        self.header.rpcLed.setToolTip(self.rpcStatusMess)
        self.updateLastBlockLabel()
        self.updateLastBlockPing()

    def updateRPClist(self):
        # Clear old stuff
        self.updatingRPCbox = True
        self.header.rpcClientsBox.clear()
        public_servers = self.parent.db.getRPCServers(custom=False)
        custom_servers = self.parent.db.getRPCServers(custom=True)
        self.rpcServersList = public_servers + custom_servers
        # Add public servers (italics)
        italicsFont = QFont("Times", italic=True)
        for s in public_servers:
            url = s["protocol"] + "://" + s["host"].split(':')[0]
            self.header.rpcClientsBox.addItem(url, s)
            self.header.rpcClientsBox.setItemData(self.getServerListIndex(s),
                                                  italicsFont, Qt.FontRole)
        # Add Local Wallet (bold)
        boldFont = QFont("Times")
        boldFont.setBold(True)
        self.header.rpcClientsBox.addItem("Local Wallet", custom_servers[0])
        self.header.rpcClientsBox.setItemData(
            self.getServerListIndex(custom_servers[0]), boldFont, Qt.FontRole)
        # Add custom servers
        for s in custom_servers[1:]:
            url = s["protocol"] + "://" + s["host"].split(':')[0]
            self.header.rpcClientsBox.addItem(url, s)
        # reset index
        if self.parent.cache[
                'selectedRPC_index'] >= self.header.rpcClientsBox.count():
            # (if manually removed from the config files) replace default index
            self.parent.cache['selectedRPC_index'] = persistCacheSetting(
                'cache_RPCindex', DefaultCache["selectedRPC_index"])

        self.header.rpcClientsBox.setCurrentIndex(
            self.parent.cache['selectedRPC_index'])
        self.updatingRPCbox = False
        # reload servers in configure dialog
        self.sig_RPClistReloaded.emit()

    def updateRPCstatus(self, ctrl, fDebug=False):
        rpc_index, rpc_protocol, rpc_host, rpc_user, rpc_password = self.getRPCserver(
        )
        if fDebug:
            printDbg("Trying to connect to RPC %s://%s..." %
                     (rpc_protocol, rpc_host))

        try:
            rpcClient = RpcClient(rpc_protocol, rpc_host, rpc_user,
                                  rpc_password)
            status, statusMess, lastBlock, r_time1, isTestnet = rpcClient.getStatus(
            )
            isBlockchainSynced, r_time2 = rpcClient.isBlockchainSynced()
        except Exception as e:
            printException(getCallerName(), getFunctionName(),
                           "exception updating RPC status:", str(e))
            # clear status
            self.rpcClient = None
            self.sig_clearRPCstatus.emit()
            return

        rpcResponseTime = None
        if r_time1 is not None and r_time2 != 0:
            rpcResponseTime = round((r_time1 + r_time2) / 2, 3)

        # Do not update status if the user has selected a different server since the start of updateRPCStatus()
        if rpc_index != self.header.rpcClientsBox.currentIndex():
            return

        with self.lock:
            self.rpcClient = rpcClient
            self.rpcConnected = status
            self.rpcLastBlock = lastBlock
            self.rpcStatusMess = statusMess
            self.isBlockchainSynced = isBlockchainSynced
            self.rpcResponseTime = rpcResponseTime
            # if testnet flag is changed, update api client and persist setting
            if isTestnet != self.isTestnetRPC:
                self.isTestnetRPC = isTestnet
                self.parent.cache['isTestnetRPC'] = persistCacheSetting(
                    'isTestnetRPC', isTestnet)
                self.apiClient = ApiClient(isTestnet)
        self.sig_RPCstatusUpdated.emit(rpc_index, fDebug)
Ejemplo n.º 8
0
class MainWindow(QWidget):
    
    def __init__(self, parent, masternode_list, imgDir):
        super(QWidget, self).__init__(parent)
        self.parent = parent
        self.imgDir = imgDir 
        self.runInThread = ThreadFuns.runInThread
        ###-- Masternode list 
        self.masternode_list = masternode_list      
        ###-- Create clients and statuses
        self.hwdevice = None
        self.hwStatus = 0
        self.hwStatusMess = "Not Connected"
        self.rpcClient = None
        self.rpcConnected = False
        self.rpcStatusMess = "Not Connected"
        self.isBlockchainSynced = False      
        ###-- Load icons & images
        self.loadIcons()        
        ###-- Create main layout
        self.layout = QVBoxLayout()
        self.header = GuiHeader(self)
        self.initConsole()
        self.layout.addWidget(self.header)       
        ###-- Create RPC Whatchdog
        self.rpc_watchdogThread = QThread()
        self.myRpcWd = RpcWatchdog(self)
        self.myRpcWd.moveToThread(self.rpc_watchdogThread)
        self.rpc_watchdogThread.started.connect(self.myRpcWd.run)
        self.rpc_watchdogThread.start()       
        
        ###-- Create Queues and redirect stdout and stderr (eventually)
        self.queue = Queue()
        self.queue2 = Queue()
        sys.stdout = WriteStream(self.queue)
        sys.stderr = WriteStream(self.queue2)  
      
        
        ###-- Init last logs
        logFile = open(log_File, 'w+')
        timestamp = strftime('%Y-%m-%d %H:%M:%S', gmtime(now()))
        log_line = '<b style="color: blue">{}</b><br>'.format('STARTING SPMT at '+ timestamp)
        logFile.write(log_line)
        logFile.close()
        
        ###-- Create the thread to update console log for stdout
        self.consoleLogThread = QThread()
        self.myWSReceiver = WriteStreamReceiver(self.queue)
        self.myWSReceiver.mysignal.connect(self.append_to_console)
        self.myWSReceiver.moveToThread(self.consoleLogThread)
        self.consoleLogThread.started.connect(self.myWSReceiver.run)
        self.consoleLogThread.start()
        printDbg("Console Log thread started")
        ###-- Create the thread to update console log for stderr
        self.consoleLogThread2 = QThread()
        self.myWSReceiver2 = WriteStreamReceiver(self.queue2)
        self.myWSReceiver2.mysignal.connect(self.append_to_console)
        self.myWSReceiver2.moveToThread(self.consoleLogThread2)
        self.consoleLogThread2.started.connect(self.myWSReceiver2.run)
        self.consoleLogThread2.start()
        printDbg("Console Log thread 2 started")       
        
        ###-- Initialize tabs
        self.tabs = QTabWidget()
        self.t_main = TabMain(self)
        self.t_mnconf = TabMNConf(self)
        self.t_rewards = TabRewards(self)
        
        ###-- Add tabs
        self.tabs.addTab(self.tabMain, "Masternode Control")
        #self.tabs.addTab(self.tabMNConf, "MN Configuration")
        self.tabs.addTab(self.tabRewards, "Transfer Rewards")              
        ###-- Connect change action
        self.tabs.currentChanged.connect(lambda: self.onTabChange())                    
        ###-- Draw Tabs 
        self.splitter = QSplitter(Qt.Vertical)
        ###-- Add tabs and console to Layout        
        self.splitter.addWidget(self.tabs)
        self.splitter.addWidget(self.console)
        self.splitter.setStretchFactor(0,0)
        self.splitter.setStretchFactor(1,1)
        self.splitter.setSizes(self.parent.cache.get("splitter_sizes"))
        self.layout.addWidget(self.splitter)
        
        ###-- Set Layout
        self.setLayout(self.layout)
        ###-- Let's go
        self.mnode_to_change = None
        printOK("Hello! Welcome to " + parent.title)
        
        ###-- Hide console if it was previously hidden
        if self.parent.cache.get("console_hidden"):
            self.onToggleConsole()
            
        ##-- Check version
        self.onCheckVersion()
        
        
    
        
    @pyqtSlot(str)    
    def append_to_console(self, text):
        self.consoleArea.moveCursor(QTextCursor.End)
        self.consoleArea.insertHtml(text)
        # update last logs
        logFile = open(log_File, 'a+')
        logFile.write(text)
        logFile.close()
            
            
            
            
    def initConsole(self):
        self.console = QGroupBox()
        self.console.setTitle("Console Log")
        layout = QVBoxLayout()
        self.btn_consoleToggle = QPushButton('Hide')
        self.btn_consoleToggle.setToolTip('Show/Hide console')
        self.btn_consoleToggle.clicked.connect(lambda: self.onToggleConsole())
        consoleHeader = QHBoxLayout()
        consoleHeader.addWidget(self.btn_consoleToggle)
        self.consoleSaveButton = QPushButton('Save')
        self.consoleSaveButton.clicked.connect(lambda: self.onSaveConsole())
        consoleHeader.addWidget(self.consoleSaveButton)
        self.btn_consoleClean = QPushButton('Clean')
        self.btn_consoleClean.setToolTip('Clean console log area')
        self.btn_consoleClean.clicked.connect(lambda: self.onCleanConsole())
        consoleHeader.addWidget(self.btn_consoleClean)
        consoleHeader.addStretch(1)
        self.versionLabel = QLabel("--")
        self.versionLabel.setOpenExternalLinks(True)
        consoleHeader.addWidget(self.versionLabel)
        self.btn_checkVersion = QPushButton("Check SPMT version")
        self.btn_checkVersion.setToolTip("Check latest stable release of SPMT")
        self.btn_checkVersion.clicked.connect(lambda: self.onCheckVersion())
        consoleHeader.addWidget(self.btn_checkVersion)
        layout.addLayout(consoleHeader)
        self.consoleArea = QTextEdit()
        almostBlack = QColor(40, 40, 40)
        palette = QPalette()
        palette.setColor(QPalette.Base, almostBlack)
        green = QColor(0, 255, 0)
        palette.setColor(QPalette.Text, green)
        self.consoleArea.setPalette(palette)
        layout.addWidget(self.consoleArea)
        self.console.setLayout(layout) 
    

        
        
    def loadIcons(self):
        # Load Icons        
        self.ledPurpleH_icon = QPixmap(os.path.join(self.imgDir, 'icon_purpleLedH.png')).scaledToHeight(17, Qt.SmoothTransformation)
        self.ledGrayH_icon = QPixmap(os.path.join(self.imgDir, 'icon_grayLedH.png')).scaledToHeight(17, Qt.SmoothTransformation)
        self.ledHalfPurpleH_icon = QPixmap(os.path.join(self.imgDir, 'icon_halfPurpleLedH.png')).scaledToHeight(17, Qt.SmoothTransformation)
        self.ledRedV_icon = QPixmap(os.path.join(self.imgDir, 'icon_redLedV.png')).scaledToHeight(17, Qt.SmoothTransformation)
        self.ledGrayV_icon = QPixmap(os.path.join(self.imgDir, 'icon_grayLedV.png')).scaledToHeight(17, Qt.SmoothTransformation)
        self.ledGreenV_icon = QPixmap(os.path.join(self.imgDir, 'icon_greenLedV.png')).scaledToHeight(17, Qt.SmoothTransformation)
       
        
        
        
    def myPopUp(self, messType, messTitle, messText, defaultButton=QMessageBox.No):
        mess = QMessageBox(messType, messTitle, messText, defaultButton, parent=self)
        mess.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        mess.setDefaultButton(defaultButton)
        return mess.exec_()
    
        
     
    def myPopUp2(self, messType, messTitle, messText, singleButton=QMessageBox.Ok):
        mess = QMessageBox(messType, messTitle, messText, singleButton, parent=self)
        mess.setStandardButtons(singleButton | singleButton)
        return mess.exec_()
        
        
        
    
    @pyqtSlot()        
    def onCheckHw(self):
        printDbg("Checking for HW device...")
        self.updateHWstatus(None)
        self.showHWstatus()


        
    
    @pyqtSlot()
    def onCheckRpc(self):
        printDbg("Checking RPC server...")      
        self.runInThread(self.updateRPCstatus, (), self.showRPCstatus) 
        
        
        
    @pyqtSlot()
    def onCheckVersion(self):
        printDbg("Checking SPMT version...")
        self.versionLabel.setText("--")      
        self.runInThread(self.checkVersion, (), self.updateVersion) 
        
        
    def checkVersion(self, ctrl):
        local_version = self.parent.version['number'].split('.')
        remote_version = getRemoteSPMTversion().split('.')
        
        if (remote_version[0] > local_version[0]) or \
        (remote_version[0] == local_version[0] and remote_version[1] > local_version[1]) or \
        (remote_version[0] == local_version[0] and remote_version[1] == local_version[1] and remote_version[2] > local_version[2]):
            self.versionMess = '<b style="color:red">New Version Available:</b> %s.%s.%s  ' % (remote_version[0], remote_version[1], remote_version[2])
            self.versionMess += '(<a href="https://github.com/PIVX-Project/PIVX-SPMT/releases/">download</a>)'
        else:
            self.versionMess = "You have the latest version of SPMT"
            
            
    def updateVersion(self):
        if self.versionMess is not None:
            self.versionLabel.setText(self.versionMess)
        
        
        
    @pyqtSlot()
    def onCleanConsole(self):
        self.consoleArea.clear()
        
      
      
      
    @pyqtSlot()
    def onSaveConsole(self):
        timestamp = strftime('%Y-%m-%d_%H-%M-%S', gmtime(now()))
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getSaveFileName(self,"Save Logs to file","SPMT_Logs_%s.txt" % timestamp,"All Files (*);; Text Files (*.txt)", options=options)
        try:
            if fileName:
                printOK("Saving logs to %s" % fileName)
                log_file = open(fileName, 'w+')
                log_text = self.consoleArea.toPlainText()
                log_file.write(log_text)
                log_file.close()
                
        except Exception as e:
            err_msg = "error writing Log file"
            printException(getCallerName(), getFunctionName(), err_msg, e.args)
                
            
            
            
    @pyqtSlot()
    def onTabChange(self):
        # reload (and re-sort)masternode list in tabs
        if self.tabs.currentWidget() == self.tabRewards:
            # reload last used address
            self.tabRewards.destinationLine.setText(self.parent.cache.get("lastAddress"))
            # get new order
            mnOrder = {}
            mnList = self.tabMain.myList
            for i in range(mnList.count()):
                mnName = mnList.itemWidget(mnList.item(i)).alias
                mnOrder[mnName] = i
            self.parent.cache['mnList_order'] = mnOrder
            # Sort masternode list (by alias if no previous order set)
            if self.parent.cache.get('mnList_order') != {}:
                self.masternode_list.sort(key=self.parent.extract_order)
            self.t_rewards.loadMnSelect()
            self.t_rewards.selectedRewards = None
            
        
        
        
    @pyqtSlot()
    def onToggleConsole(self):
        if self.btn_consoleToggle.text() == 'Hide':
            self.btn_consoleToggle.setText('Show')
            self.consoleArea.hide()
            self.console.setMinimumHeight(70)
            self.console.setMaximumHeight(70)
        else:
            self.console.setMinimumHeight(70)
            self.console.setMaximumHeight(starting_height)
            self.btn_consoleToggle.setText('Hide')
            self.consoleArea.show()  
            
            
    
    
    
    
    def showHWstatus(self):
        self.updateHWleds()
        self.myPopUp2(QMessageBox.Information, 'SPMT - hw check', "%s" % self.hwStatusMess, QMessageBox.Ok)
        
        
    
        
    def showRPCstatus(self):
        self.updateRPCled()
        self.myPopUp2(QMessageBox.Information, 'SPMT - rpc check', "%s" % self.rpcStatusMess, QMessageBox.Ok)

            
            
            
    def updateHWleds(self):
        if self.hwStatus == 1:
            self.header.hwLed.setPixmap(self.ledHalfPurpleH_icon)
        elif self.hwStatus == 2:
            self.header.hwLed.setPixmap(self.ledPurpleH_icon)
        else:
            self.header.hwLed.setPixmap(self.ledGrayH_icon)
        self.header.hwLed.setToolTip(self.hwStatusMess)
        
        
 
        
    def updateHWstatus(self, ctrl):          
        if self.hwdevice is None:
            self.hwdevice = HWdevice()
        
        device = self.hwdevice
        statusCode = device.getStatusCode()
        statusMess = device.getStatusMess(statusCode)
        printDbg("code: %s - mess: %s" % (statusCode, statusMess))
        if statusCode != 2:
            try:
                if getattr(self.hwdevice, 'dongle', None) is not None:
                    self.hwdevice.dongle.close()
                self.hwdevice.initDevice()
                device = self.hwdevice
                statusCode = device.getStatusCode()
                statusMess = device.getStatusMess(statusCode)

            except Exception as e:
                err_msg = "error in checkHw"
                printException(getCallerName(), getFunctionName(), err_msg, e.args)
                    
        self.hwStatus = statusCode
        self.hwStatusMess = statusMess
        
        
  
        
    def updateLastBlockLabel(self):
        text = '--'
        if self.rpcLastBlock == 1:
            text = "Loading block index..."
        elif self.rpcLastBlock > 0 and self.rpcConnected:
            text = str(self.rpcLastBlock)
            text += " ("       
            if not self.isBlockchainSynced:
                text += "Synchronizing"
            else:
                text += "Synced"
            text += ")"
                
        self.header.lastBlockLabel.setText(text)
        
       
        

                  
    def updateRPCled(self):
        if self.rpcConnected:
            self.header.rpcLed.setPixmap(self.ledPurpleH_icon)
        else:
            if self.rpcLastBlock == 1:
                self.header.rpcLed.setPixmap(self.ledHalfPurpleH_icon)
            else:
                self.header.rpcLed.setPixmap(self.ledGrayH_icon)
            
        self.header.rpcLed.setToolTip(self.rpcStatusMess)
        self.updateLastBlockLabel()
        

    
        
    def updateRPCstatus(self, ctrl):
        if self.rpcClient is None:
            try:
                self.rpcClient = RpcClient()
            except Exception as e:
                print(e)
        status, lastBlock = self.rpcClient.getStatus()
        statusMess = self.rpcClient.getStatusMess(status)
        if not status and lastBlock==0:
            try:
                self.rpcClient = RpcClient()
                status, lastBlock = self.rpcClient.getStatus()
                statusMess = self.rpcClient.getStatusMess(status)
            except Exception as e:
                err_msg = "error in checkRpc"
                printException(getCallerName(), getFunctionName(), err_msg, e)
        
        elif lastBlock == 1:
            statusMess = "PIVX wallet is connected but still synchronizing / verifying blocks"
        
        self.rpcConnected = status
        self.rpcLastBlock = lastBlock
        self.rpcStatusMess = statusMess
        self.isBlockchainSynced = self.rpcClient.isBlockchainSynced()
Ejemplo n.º 9
0
    def __init__(self, parent, masternode_list, imgDir):
        super(QWidget, self).__init__(parent)
        self.parent = parent
        self.imgDir = imgDir
        self.runInThread = ThreadFuns.runInThread
        self.lock = threading.Lock()

        ###-- Masternode list
        self.masternode_list = masternode_list

        ###-- Create clients and statuses
        self.hwStatus = 0
        self.hwStatusMess = "Not Connected"
        self.rpcClient = None
        self.rpcConnected = False
        self.updatingRPCbox = False
        self.rpcStatusMess = "Not Connected"
        self.isBlockchainSynced = False

        ###-- Load icons & images
        self.loadIcons()
        ###-- Create main layout
        self.layout = QVBoxLayout()
        self.header = GuiHeader(self)
        self.initConsole()
        self.layout.addWidget(self.header)

        ##-- Load RPC Servers list
        self.updateRPClist()

        ##-- init HW Client
        self.hwdevice = HWdevice()

        ##-- init Api Client
        self.apiClient = ApiClient()

        ###-- Create Queues and redirect stdout
        self.queue = Queue()
        sys.stdout = WriteStream(self.queue)

        ###-- Init last logs
        logFile = open(log_File, 'w+')
        timestamp = strftime('%Y-%m-%d %H:%M:%S', gmtime(now()))
        log_line = '<b style="color: blue">{}</b><br>'.format(
            'STARTING SPMT at ' + timestamp)
        logFile.write(log_line)
        logFile.close()

        ###-- Create the thread to update console log for stdout
        self.consoleLogThread = QThread()
        self.myWSReceiver = WriteStreamReceiver(self.queue)
        self.myWSReceiver.mysignal.connect(self.append_to_console)
        self.myWSReceiver.moveToThread(self.consoleLogThread)
        self.consoleLogThread.started.connect(self.myWSReceiver.run)
        self.consoleLogThread.start()
        printDbg("Console Log thread started")

        ###-- Initialize tabs
        self.tabs = QTabWidget()
        self.t_main = TabMain(self)
        self.t_mnconf = TabMNConf(self)
        self.t_rewards = TabRewards(self)
        self.t_governance = TabGovernance(self)
        ###-- Add tabs
        self.tabs.setTabPosition(QTabWidget.West)
        self.tabs.addTab(self.tabMain, "Masternode List")
        #self.tabs.addTab(self.tabMNConf, "MN Configuration")
        self.tabs.addTab(self.tabRewards, "Rewards")
        self.tabs.addTab(self.tabGovernance, "Governance")
        ###-- Connect change action
        self.tabs.currentChanged.connect(lambda: self.onTabChange())
        ###-- Draw Tabs
        self.splitter = QSplitter(Qt.Vertical)
        ###-- Add tabs and console to Layout
        self.splitter.addWidget(self.tabs)
        self.splitter.addWidget(self.console)
        self.splitter.setStretchFactor(0, 0)
        self.splitter.setStretchFactor(1, 1)
        self.layout.addWidget(self.splitter)

        ###-- Set Layout
        self.setLayout(self.layout)

        ###-- Init Settings
        self.initSettings()

        ###-- Connect buttons/signals
        self.connButtons()

        ##-- Check version
        self.onCheckVersion()

        ###-- Create RPC Whatchdog
        self.rpc_watchdogThread = QThread()
        self.myRpcWd = RpcWatchdog(self)
        self.myRpcWd.moveToThread(self.rpc_watchdogThread)
        self.rpc_watchdogThread.started.connect(self.myRpcWd.run)

        ###-- Let's go
        self.mnode_to_change = None
        printOK("Hello! Welcome to " + parent.title)
Ejemplo n.º 10
0
class MainWindow(QWidget):

    # signal: clear RPC status label and icons (emitted by updateRPCstatus)
    sig_clearRPCstatus = pyqtSignal()

    # signal: RPC status (for server id) is changed (emitted by updateRPCstatus)
    sig_RPCstatusUpdated = pyqtSignal(int, bool)

    # signal: RPC list has been reloaded (emitted by updateRPClist)
    sig_RPClistReloaded = pyqtSignal()

    # signal: UTXO list loading percent (emitted by load_utxos_thread in tabRewards)
    sig_UTXOsLoading = pyqtSignal(int)

    # signal: UTXO list has been reloaded (emitted by load_utxos_thread in tabRewards)
    sig_UTXOsLoaded = pyqtSignal()

    # signal: Proposals list has been reloaded (emitted by loadProposals_thread in tabGovernance)
    sig_ProposalsLoaded = pyqtSignal()

    def __init__(self, parent, masternode_list, imgDir):
        super(QWidget, self).__init__(parent)
        self.parent = parent
        self.imgDir = imgDir
        self.runInThread = ThreadFuns.runInThread
        self.lock = threading.Lock()

        ###-- Masternode list
        self.masternode_list = masternode_list

        ###-- Create clients and statuses
        self.hwStatus = 0
        self.hwStatusMess = "Not Connected"
        self.rpcClient = None
        self.rpcConnected = False
        self.updatingRPCbox = False
        self.rpcStatusMess = "Not Connected"
        self.isBlockchainSynced = False

        ###-- Load icons & images
        self.loadIcons()
        ###-- Create main layout
        self.layout = QVBoxLayout()
        self.header = GuiHeader(self)
        self.initConsole()
        self.layout.addWidget(self.header)

        ##-- Load RPC Servers list
        self.updateRPClist()

        ##-- init HW Client
        self.hwdevice = HWdevice()

        ##-- init Api Client
        self.apiClient = ApiClient()

        ###-- Create Queues and redirect stdout
        self.queue = Queue()
        sys.stdout = WriteStream(self.queue)

        ###-- Init last logs
        logFile = open(log_File, 'w+')
        timestamp = strftime('%Y-%m-%d %H:%M:%S', gmtime(now()))
        log_line = '<b style="color: blue">{}</b><br>'.format(
            'STARTING SPMT at ' + timestamp)
        logFile.write(log_line)
        logFile.close()

        ###-- Create the thread to update console log for stdout
        self.consoleLogThread = QThread()
        self.myWSReceiver = WriteStreamReceiver(self.queue)
        self.myWSReceiver.mysignal.connect(self.append_to_console)
        self.myWSReceiver.moveToThread(self.consoleLogThread)
        self.consoleLogThread.started.connect(self.myWSReceiver.run)
        self.consoleLogThread.start()
        printDbg("Console Log thread started")

        ###-- Initialize tabs
        self.tabs = QTabWidget()
        self.t_main = TabMain(self)
        self.t_mnconf = TabMNConf(self)
        self.t_rewards = TabRewards(self)
        self.t_governance = TabGovernance(self)
        ###-- Add tabs
        self.tabs.setTabPosition(QTabWidget.West)
        self.tabs.addTab(self.tabMain, "Masternode List")
        #self.tabs.addTab(self.tabMNConf, "MN Configuration")
        self.tabs.addTab(self.tabRewards, "Rewards")
        self.tabs.addTab(self.tabGovernance, "Governance")
        ###-- Connect change action
        self.tabs.currentChanged.connect(lambda: self.onTabChange())
        ###-- Draw Tabs
        self.splitter = QSplitter(Qt.Vertical)
        ###-- Add tabs and console to Layout
        self.splitter.addWidget(self.tabs)
        self.splitter.addWidget(self.console)
        self.splitter.setStretchFactor(0, 0)
        self.splitter.setStretchFactor(1, 1)
        self.layout.addWidget(self.splitter)

        ###-- Set Layout
        self.setLayout(self.layout)

        ###-- Init Settings
        self.initSettings()

        ###-- Connect buttons/signals
        self.connButtons()

        ##-- Check version
        self.onCheckVersion()

        ###-- Create RPC Whatchdog
        self.rpc_watchdogThread = QThread()
        self.myRpcWd = RpcWatchdog(self)
        self.myRpcWd.moveToThread(self.rpc_watchdogThread)
        self.rpc_watchdogThread.started.connect(self.myRpcWd.run)

        ###-- Let's go
        self.mnode_to_change = None
        printOK("Hello! Welcome to " + parent.title)

    def append_to_console(self, text):
        self.consoleArea.moveCursor(QTextCursor.End)
        self.consoleArea.insertHtml(text)

    def clearHWstatus(self, message):
        self.hwStatus = 1
        self.hwStatusMess = 'Unable to connect to the device. Please check that the PIVX app on the device is open, and try again.'
        self.header.hwLed.setPixmap(self.ledGrayH_icon)
        if message != '':
            myPopUp_sb(self, "crit", "Ledger Disconnected", message)

    def clearRPCstatus(self):
        self.rpcConnected = False
        self.header.lastPingBox.setHidden(False)
        self.header.rpcLed.setPixmap(self.ledGrayH_icon)
        self.header.lastBlockLabel.setText("<em>Connecting...</em>")
        self.header.lastPingIcon.setPixmap(self.connRed_icon)
        self.header.responseTimeLabel.setText("--")
        self.header.responseTimeLabel.setStyleSheet("color: red")
        self.header.lastPingIcon.setStyleSheet("color: red")

    def connButtons(self):
        self.header.button_checkRpc.clicked.connect(lambda: self.onCheckRpc())
        self.header.button_checkHw.clicked.connect(lambda: self.onCheckHw())
        self.header.rpcClientsBox.currentIndexChanged.connect(
            self.onChangeSelectedRPC)
        ##-- Connect signals
        self.sig_clearRPCstatus.connect(self.clearRPCstatus)
        self.sig_RPCstatusUpdated.connect(self.showRPCstatus)
        self.parent.sig_changed_rpcServers.connect(self.updateRPClist)
        self.hwdevice.sig_ledger_disconnected.connect(self.clearHWstatus)
        self.tabMain.myList.model().rowsMoved.connect(self.saveMNListOrder)

    def getRPCserver(self):
        itemData = self.header.rpcClientsBox.itemData(
            self.header.rpcClientsBox.currentIndex())
        rpc_index = self.header.rpcClientsBox.currentIndex()
        rpc_protocol = itemData["protocol"]
        rpc_host = itemData["host"]
        rpc_user = itemData["user"]
        rpc_password = itemData["password"]

        return rpc_index, rpc_protocol, rpc_host, rpc_user, rpc_password

    def getServerListIndex(self, server):
        return self.header.rpcClientsBox.findData(server)

    def initConsole(self):
        self.console = QGroupBox()
        self.console.setTitle("Console Log")
        layout = QVBoxLayout()
        self.btn_consoleToggle = QPushButton('Hide')
        self.btn_consoleToggle.setToolTip('Show/Hide console')
        self.btn_consoleToggle.clicked.connect(lambda: self.onToggleConsole())
        consoleHeader = QHBoxLayout()
        consoleHeader.addWidget(self.btn_consoleToggle)
        self.consoleSaveButton = QPushButton('Save')
        self.consoleSaveButton.clicked.connect(lambda: self.onSaveConsole())
        consoleHeader.addWidget(self.consoleSaveButton)
        self.btn_consoleClean = QPushButton('Clean')
        self.btn_consoleClean.setToolTip('Clean console log area')
        self.btn_consoleClean.clicked.connect(lambda: self.onCleanConsole())
        consoleHeader.addWidget(self.btn_consoleClean)
        consoleHeader.addStretch(1)
        self.versionLabel = QLabel("--")
        self.versionLabel.setOpenExternalLinks(True)
        consoleHeader.addWidget(self.versionLabel)
        self.btn_checkVersion = QPushButton("Check SPMT version")
        self.btn_checkVersion.setToolTip("Check latest stable release of SPMT")
        self.btn_checkVersion.clicked.connect(lambda: self.onCheckVersion())
        consoleHeader.addWidget(self.btn_checkVersion)
        layout.addLayout(consoleHeader)
        self.consoleArea = QTextEdit()
        almostBlack = QColor(40, 40, 40)
        palette = QPalette()
        palette.setColor(QPalette.Base, almostBlack)
        green = QColor(0, 255, 0)
        palette.setColor(QPalette.Text, green)
        self.consoleArea.setPalette(palette)
        layout.addWidget(self.consoleArea)
        self.console.setLayout(layout)

    def initSettings(self):
        self.splitter.setSizes([
            self.parent.cache.get("splitter_x"),
            self.parent.cache.get("splitter_y")
        ])
        ###-- Hide console if it was previously hidden
        if self.parent.cache.get("console_hidden"):
            self.onToggleConsole()

    def isMasternodeInList(self, mn_alias):
        return (mn_alias in [x['name'] for x in self.masternode_list])

    def loadIcons(self):
        # Load Icons
        self.ledPurpleH_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_purpleLedH.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledGrayH_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_grayLedH.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledHalfPurpleH_icon = QPixmap(
            os.path.join(self.imgDir,
                         'icon_halfPurpleLedH.png')).scaledToHeight(
                             17, Qt.SmoothTransformation)
        self.ledRedV_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_redLedV.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledGrayV_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_grayLedV.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.ledGreenV_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_greenLedV.png')).scaledToHeight(
                17, Qt.SmoothTransformation)
        self.lastBlock_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_lastBlock.png')).scaledToHeight(
                15, Qt.SmoothTransformation)
        self.connGreen_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_greenConn.png')).scaledToHeight(
                15, Qt.SmoothTransformation)
        self.connRed_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_redConn.png')).scaledToHeight(
                15, Qt.SmoothTransformation)
        self.connOrange_icon = QPixmap(
            os.path.join(self.imgDir, 'icon_orangeConn.png')).scaledToHeight(
                15, Qt.SmoothTransformation)

    def loadMNConf(self, fileName):
        hot_masternodes = loadMNConfFile(fileName)
        if hot_masternodes == None:
            messText = "Unable to load data from file '%s'" % fileName
            myPopUp_sb(self, "warn", "SPMT - Load MN Conf", messText)
        else:
            new_masternodes = []
            skip_masternodes = []
            for x in hot_masternodes:
                # If masternode name is not in list
                if not self.isMasternodeInList(x['name']):
                    # Add to cache, QListWidget and database
                    appendMasternode(self, x)
                    new_masternodes.append(x)
                # Otherwise skip it
                else:
                    skip_masternodes.append(x)

            # Print number of nodes added
            new_nodes = len(new_masternodes)
            final_message = ""
            if new_nodes == 0:
                final_message = "No External Masternode "
            elif new_nodes == 1:
                final_message = "1 External Masternode "
            else:
                final_message = "%d External Masternodes " % new_nodes
            final_message += "added to the list."
            if new_nodes > 0:
                final_message += "<br>" + str(
                    [x['name'] for x in new_masternodes]) + ".  "
            printOK(final_message)
            if len(skip_masternodes) > 0:
                final_message = "Following entries skipped due to duplicate names:<br>"
                final_message += str([x['name']
                                      for x in skip_masternodes]) + ".  "
                printOK(final_message)

    def onCheckHw(self):
        printDbg("Checking for HW device...")
        self.updateHWstatus(None)
        self.showHWstatus()

    def onCheckRpc(self):
        self.runInThread(
            self.updateRPCstatus,
            (True, ),
        )

    def onCheckVersion(self):
        printDbg("Checking SPMT version...")
        self.versionLabel.setText("--")
        self.runInThread(self.checkVersion, (), self.updateVersion)

    def checkVersion(self, ctrl):
        local_version = self.parent.version['number'].split('.')
        self.gitVersion = getRemoteSPMTversion()
        remote_version = self.gitVersion.split('.')

        if (remote_version[0] > local_version[0]) or \
        (remote_version[0] == local_version[0] and remote_version[1] > local_version[1]) or \
        (remote_version[0] == local_version[0] and remote_version[1] == local_version[1] and remote_version[2] > local_version[2]):
            self.versionMess = '<b style="color:red">New Version Available:</b> %s  ' % (
                self.gitVersion)
            self.versionMess += '(<a href="https://github.com/PIVX-Project/PIVX-SPMT/releases/">download</a>)'
        else:
            self.versionMess = "You have the latest version of SPMT"

    def updateVersion(self):
        if self.versionMess is not None:
            self.versionLabel.setText(self.versionMess)
        printOK("Remote version: %s" % str(self.gitVersion))

    def onChangeSelectedRPC(self, i):
        # Don't update when we are clearing the box
        if not self.updatingRPCbox:
            # persist setting
            self.parent.cache['selectedRPC_index'] = persistCacheSetting(
                'cache_RPCindex', i)

            self.runInThread(
                self.updateRPCstatus,
                (True, ),
            )

    def onCleanConsole(self):
        self.consoleArea.clear()

    def onSaveConsole(self):
        timestamp = strftime('%Y-%m-%d_%H-%M-%S', gmtime(now()))
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getSaveFileName(
            self,
            "Save Logs to file",
            "SPMT_Logs_%s.txt" % timestamp,
            "All Files (*);; Text Files (*.txt)",
            options=options)
        try:
            if fileName:
                printOK("Saving logs to %s" % fileName)
                log_file = open(fileName, 'w+')
                log_text = self.consoleArea.toPlainText()
                log_file.write(log_text)
                log_file.close()

        except Exception as e:
            err_msg = "error writing Log file"
            printException(getCallerName(), getFunctionName(), err_msg, e.args)

    def onTabChange(self):
        # tabRewards
        if self.tabs.currentWidget() == self.tabRewards:
            # reload last used address
            self.tabRewards.destinationLine.setText(
                self.parent.cache.get("lastAddress"))

        # tabGovernace
        if self.tabs.currentWidget() == self.tabGovernance:
            # update selectedMNlabel (since we might have edited them)
            self.t_governance.updateSelectedMNlabel()

    def onToggleConsole(self):
        if self.btn_consoleToggle.text() == 'Hide':
            self.btn_consoleToggle.setText('Show')
            self.consoleArea.hide()
            self.console.setMinimumHeight(70)
            self.console.setMaximumHeight(70)
        else:
            self.console.setMinimumHeight(70)
            self.console.setMaximumHeight(starting_height)
            self.btn_consoleToggle.setText('Hide')
            self.consoleArea.show()

    def saveMNListOrder(self):
        # Update mnList order to cache settings and sort
        mnOrder = {}
        mnList = self.tabMain.myList
        for i in range(mnList.count()):
            mnName = mnList.itemWidget(mnList.item(i)).alias
            mnOrder[mnName] = i
        self.parent.cache['mnList_order'] = persistCacheSetting(
            'cache_mnOrder', mnOrder)
        self.masternode_list.sort(key=self.parent.extract_order)
        # reload MnSelect in tabRewards
        self.t_rewards.loadMnSelect()

    def showHWstatus(self):
        self.updateHWleds()
        myPopUp_sb(self, "info", 'SPMT - hw check', "%s" % self.hwStatusMess)

    def showRPCstatus(self, server_index, fDebug):
        # Update displayed status only if selected server is not changed
        if server_index == self.header.rpcClientsBox.currentIndex():
            self.updateRPCled(fDebug)
            if fDebug:
                myPopUp_sb(self, "info", 'SPMT - rpc check',
                           "%s" % self.rpcStatusMess)

    def updateHWleds(self):
        if self.hwStatus == 1:
            self.header.hwLed.setPixmap(self.ledHalfPurpleH_icon)
        elif self.hwStatus == 2:
            self.header.hwLed.setPixmap(self.ledPurpleH_icon)
        else:
            self.header.hwLed.setPixmap(self.ledGrayH_icon)
        self.header.hwLed.setToolTip(self.hwStatusMess)

    def updateHWstatus(self, ctrl):
        # re-initialize device
        try:
            self.hwdevice.initDevice()
            self.hwStatus, self.hwStatusMess = self.hwdevice.getStatus()
            printDbg("mess: %s" % statusMess)
        except:
            pass

        printDbg("status:%s - mess: %s" % (self.hwStatus, self.hwStatusMess))

    def updateLastBlockLabel(self):
        text = '--'
        if self.rpcLastBlock == 1:
            text = "Loading block index..."
        elif self.rpcConnected and self.rpcLastBlock > 0:
            text = str(self.rpcLastBlock)
            if not self.isBlockchainSynced:
                text += " (Synchronizing)"

        self.header.lastBlockLabel.setText(text)

    def updateLastBlockPing(self):
        if not self.rpcConnected:
            self.header.lastPingBox.setHidden(True)
        else:
            self.header.lastPingBox.setHidden(False)
            if self.rpcResponseTime > 2:
                color = "red"
                self.header.lastPingIcon.setPixmap(self.connRed_icon)
            elif self.rpcResponseTime > 1:
                color = "orange"
                self.header.lastPingIcon.setPixmap(self.connOrange_icon)
            else:
                color = "green"
                self.header.lastPingIcon.setPixmap(self.connGreen_icon)
            if self.rpcResponseTime is not None:
                self.header.responseTimeLabel.setText("%.3f" %
                                                      self.rpcResponseTime)
                self.header.responseTimeLabel.setStyleSheet("color: %s" %
                                                            color)
                self.header.lastPingIcon.setStyleSheet("color: %s" % color)

    def updateRPCled(self, fDebug=False):
        if self.rpcConnected:
            self.header.rpcLed.setPixmap(self.ledPurpleH_icon)
            if fDebug:
                printDbg("Connected to RPC server.")
        else:
            if self.rpcLastBlock == 1:
                self.header.rpcLed.setPixmap(self.ledHalfPurpleH_icon)
                if fDebug:
                    printDbg("Connected to RPC server - Still syncing...")
            else:
                self.header.rpcLed.setPixmap(self.ledGrayH_icon)
                if fDebug:
                    printDbg("Connection to RPC server failed.")

        self.header.rpcLed.setToolTip(self.rpcStatusMess)
        self.updateLastBlockLabel()
        self.updateLastBlockPing()

    def updateRPClist(self):
        # Clear old stuff
        self.updatingRPCbox = True
        self.header.rpcClientsBox.clear()
        public_servers = self.parent.db.getRPCServers(custom=False)
        custom_servers = self.parent.db.getRPCServers(custom=True)
        self.rpcServersList = public_servers + custom_servers
        # Add public servers (italics)
        italicsFont = QFont("Times", italic=True)
        for s in public_servers:
            url = s["protocol"] + "://" + s["host"].split(':')[0]
            self.header.rpcClientsBox.addItem(url, s)
            self.header.rpcClientsBox.setItemData(self.getServerListIndex(s),
                                                  italicsFont, Qt.FontRole)
        # Add Local Wallet (bold)
        boldFont = QFont("Times")
        boldFont.setBold(True)
        self.header.rpcClientsBox.addItem("Local Wallet", custom_servers[0])
        self.header.rpcClientsBox.setItemData(
            self.getServerListIndex(custom_servers[0]), boldFont, Qt.FontRole)
        # Add custom servers
        for s in custom_servers[1:]:
            url = s["protocol"] + "://" + s["host"].split(':')[0]
            self.header.rpcClientsBox.addItem(url, s)
        # reset index
        if self.parent.cache[
                'selectedRPC_index'] >= self.header.rpcClientsBox.count():
            # (if manually removed from the config files) replace default index
            self.parent.cache['selectedRPC_index'] = persistCacheSetting(
                'cache_RPCindex', DefaultCache["selectedRPC_index"])
        self.header.rpcClientsBox.setCurrentIndex(
            self.parent.cache['selectedRPC_index'])
        self.updatingRPCbox = False
        # reload servers in configure dialog
        self.sig_RPClistReloaded.emit()

    def updateRPCstatus(self, ctrl, fDebug=False):
        self.sig_clearRPCstatus.emit()
        self.rpcClient = None

        rpc_index, rpc_protocol, rpc_host, rpc_user, rpc_password = self.getRPCserver(
        )

        rpc_url = "%s://%s:%s@%s" % (rpc_protocol, rpc_user, rpc_password,
                                     rpc_host)
        rpcClient = RpcClient(rpc_protocol, rpc_host, rpc_user, rpc_password)

        if fDebug:
            printDbg("Trying to connect to RPC %s://%s..." %
                     (rpc_protocol, rpc_host))

        status, statusMess, lastBlock, r_time1 = rpcClient.getStatus()

        isBlockchainSynced, r_time2 = rpcClient.isBlockchainSynced()

        rpcResponseTime = None
        if r_time1 is not None and r_time2 is not None:
            rpcResponseTime = round((r_time1 + r_time2) / 2, 3)

        # Update status and client only if selected server is not changed
        if rpc_index != self.header.rpcClientsBox.currentIndex():
            return

        with self.lock:
            self.rpcClient = rpcClient
            self.rpcConnected = status
            self.rpcLastBlock = lastBlock
            self.rpcStatusMess = statusMess
            self.isBlockchainSynced = isBlockchainSynced
            self.rpcResponseTime = rpcResponseTime

        self.sig_RPCstatusUpdated.emit(rpc_index, fDebug)
Ejemplo n.º 11
0
class TestHwDeviceMethods(unittest.TestCase):
    def setUp(self):
        self.device = HWdevice()
        self.rpcClient = RpcClient()
        hwStatus = self.device.getStatusCode()
        rpcStatus, _ = self.rpcClient.getStatus()
        if hwStatus != 2:
            self.skipTest("Ledger not connected or pivx app closed")
        if not rpcStatus:
            self.skipTest("RPC not connected")

    def tearDown(self):
        if hasattr(self.device, 'dongle'):
            self.device.dongle.close()
            self.device.parent = None
            print("Dongle Closed")
        if hasattr(self.rpcClient, 'conn'):
            self.rpcClient.parent = None

    def test_transaction(self):
        # Read input data from file
        import simplejson as json
        with open('test_transaction.data.json', encoding="utf-8") as data_file:
            input_data = json.load(data_file)
        data_file.close()

        # Rename input data
        path = input_data['path']
        pivx_address_to = input_data['address_from']
        fee = input_data['fee']
        utxos = input_data['unspent_outputs']
        rawtransactions = input_data['raw_transactions']
        print("=================================")
        print("   Press 'OK' on Ledger device   ")
        print("---------------------------------")
        txraw, amount = self.signTx(self.device, path, utxos, pivx_address_to,
                                    fee, rawtransactions)

        # Check total amount
        total = sum([int(utxo['value']) for utxo in utxos], 0)
        amount = round(float(amount) * 1e8)
        self.assertEqual(total - fee, amount)

        # Decode Raw Tx to inspect and check inputs
        inputs = [utxo["tx_hash"] for utxo in utxos]
        decodedTx = self.rpcClient.decodeRawTx(txraw.hex())
        decoded_inputs = [
            decoded_input["txid"] for decoded_input in decodedTx["vin"]
        ]
        while len(inputs) > 0:
            input_tx = inputs.pop()
            self.assertIn(input_tx, decoded_inputs)
            decoded_inputs.remove(input_tx)

    def test_scanForBip32(self):
        # Get accounts obtained from seed outside ledger
        # (5 accounts. 5 addresses per account)
        with open('accounts.data.txt', encoding="utf-8") as datafile:
            # datafile has 4 lines of header (lines_offset)
            for _ in range(4):
                datafile.readline()
            for account_n in range(5):
                for address_n in range(5):
                    address = datafile.readline().split()[0]

                    result, _ = self.device.scanForBip32(
                        account_n,
                        address,
                        starting_spath=address_n,
                        spath_count=1)
                    # Address found in account_n  with index.
                    self.assertTrue(result)

    def test_scanForPubKey(self):
        # Get accounts obtained from seed outside ledger
        # (5 accounts. 5 addresses per account)
        with open('accounts.data.txt', encoding="utf-8") as datafile:
            # datafile has 4 lines of header (lines_offset)
            for _ in range(4):
                datafile.readline()
            for account_n in range(5):
                for address_n in range(5):
                    pubkey = datafile.readline().split()[1]

                    result = self.device.scanForPubKey(account_n, address_n)
                    # Pubkey checks out
                    self.assertEqual(result, pubkey)

    def test_signature(self):
        # Get message and path from datafile
        import simplejson as json
        with open('test_signature.data.json', encoding="utf-8") as data_file:
            input_data = json.load(data_file)

        # Rename input data
        message = input_data['message']
        path = input_data['path']
        pivx_address = self.device.chip.getWalletPublicKey(path).get(
            'address')[12:-2]

        # sign message on ledger
        print("=================================")
        print("   Press 'OK' on Ledger device   ")
        print("---------------------------------")
        signature = self.signMess(path, message)

        # verify with rpc client
        result = self.rpcClient.verifyMessage(pivx_address, signature, message)
        print("sig = %s\naddress=%s" % (signature, pivx_address))
        self.assertTrue(result)

    # -----------------------------------------------------------------------------------
    # from:
    # -- hwdevice.signMess
    # -- hwdevice.signMessSign
    # -- hwdevice.signMessFinish
    # without gui
    def signMess(self, path, message):
        from utils import b64encode
        # Ledger doesn't accept characters other that ascii printable:
        # https://ledgerhq.github.io/btchip-doc/bitcoin-technical.html#_sign_message
        message = message.encode('ascii', 'ignore')
        self.device.chip.signMessagePrepare(path, message)
        signature = self.device.chip.signMessageSign(None)
        if signature is not None:
            if len(signature) > 4:
                rLength = signature[3]
                r = signature[4:4 + rLength]
                if len(signature) > 4 + rLength + 1:
                    sLength = signature[4 + rLength + 1]
                    if len(signature) > 4 + rLength + 2:
                        s = signature[4 + rLength + 2:]
                        if rLength == 33:
                            r = r[1:]
                        if sLength == 33:
                            s = s[1:]

                        work = bytes(chr(27 + 4 + (signature[0] & 0x01)),
                                     "utf-8") + r + s
                        print("Message signed")
                        sig1 = work.hex()
                    else:
                        print(
                            'client.signMessageSign() returned invalid response (code 3): '
                            + signature.hex())
                        sig1 = "None"
                else:
                    print(
                        'client.signMessageSign() returned invalid response (code 2): '
                        + signature.hex())
                    sig1 = "None"
            else:
                print(
                    'client.signMessageSign() returned invalid response (code 1): '
                    + signature.hex())
                sig1 = "None"
        else:
            print("Signature refused by the user")
            sig1 = "None"

        return b64encode(sig1)

    # from:
    # -- hwdevice.prepare_transfer_tx
    # -- hwdevice.signTxSign
    # -- hwdevice.signTxFinish
    # without gui
    def signTx(self, device, bip32_path, utxos_to_spend, dest_address, tx_fee,
               rawtransactions):
        # For each UTXO create a Ledger 'trusted input'
        self.trusted_inputs = []
        #    https://klmoney.wordpress.com/bitcoin-dissecting-transactions-part-2-building-a-transaction-by-hand)
        self.arg_inputs = []

        self.amount = 0
        for idx, utxo in enumerate(utxos_to_spend):

            self.amount += int(utxo['value'])

            raw_tx = bytearray.fromhex(rawtransactions[utxo['tx_hash']])

            if not raw_tx:
                raise Exception("Can't find raw transaction for txid: " +
                                rawtransactions[utxo['tx_hash']])

            # parse the raw transaction, so that we can extract the UTXO locking script we refer to
            prev_transaction = bitcoinTransaction(raw_tx)

            utxo_tx_index = utxo['tx_ouput_n']
            if utxo_tx_index < 0 or utxo_tx_index > len(
                    prev_transaction.outputs):
                raise Exception('Incorrect value of outputIndex for UTXO %s' %
                                str(idx))

            trusted_input = self.device.chip.getTrustedInput(
                prev_transaction, utxo_tx_index)
            self.trusted_inputs.append(trusted_input)

            # Hash check
            curr_pubkey = compress_public_key(
                device.chip.getWalletPublicKey(bip32_path)['publicKey'])
            pubkey_hash = bin_hash160(curr_pubkey)
            pubkey_hash_from_script = extract_pkh_from_locking_script(
                prev_transaction.outputs[utxo_tx_index].script)
            if pubkey_hash != pubkey_hash_from_script:
                text = "Error: different public key hashes for the BIP32 path and the UTXO"
                text += "locking script. Your signed transaction will not be validated by the network.\n"
                text += "pubkey_hash: %s\n" % str(pubkey_hash)
                text += "pubkey_hash_from_script: %s\n" % str(
                    pubkey_hash_from_script)
                print(text)

            self.arg_inputs.append({
                'locking_script':
                prev_transaction.outputs[utxo['tx_ouput_n']].script,
                'pubkey':
                curr_pubkey,
                'bip32_path':
                bip32_path,
                'outputIndex':
                utxo['tx_ouput_n'],
                'txid':
                utxo['tx_hash']
            })

        self.amount -= int(tx_fee)
        self.amount = int(self.amount)
        arg_outputs = [{
            'address': dest_address,
            'valueSat': self.amount
        }]  # there will be multiple outputs soon
        self.new_transaction = bitcoinTransaction(
        )  # new transaction object to be used for serialization at the last stage
        self.new_transaction.version = bytearray([0x01, 0x00, 0x00, 0x00])
        try:
            for o in arg_outputs:
                output = bitcoinOutput()
                output.script = compose_tx_locking_script(o['address'])
                output.amount = int.to_bytes(o['valueSat'],
                                             8,
                                             byteorder='little')
                self.new_transaction.outputs.append(output)
        except Exception:
            raise
        # join all outputs - will be used by Ledger for signing transaction
        self.all_outputs_raw = self.new_transaction.serializeOutputs()

        starting = True
        # sign all inputs on Ledger and add inputs in the self.new_transaction object for serialization
        for idx, new_input in enumerate(self.arg_inputs):
            device.chip.startUntrustedTransaction(starting, idx,
                                                  self.trusted_inputs,
                                                  new_input['locking_script'])

            device.chip.finalizeInputFull(self.all_outputs_raw)

            sig = device.chip.untrustedHashSign(new_input['bip32_path'],
                                                lockTime=0)

            new_input['signature'] = sig
            inputTx = bitcoinInput()
            inputTx.prevOut = bytearray.fromhex(
                new_input['txid'])[::-1] + int.to_bytes(
                    new_input['outputIndex'], 4, byteorder='little')

            inputTx.script = bytearray([len(sig)]) + sig + bytearray(
                [0x21]) + new_input['pubkey']

            inputTx.sequence = bytearray([0xFF, 0xFF, 0xFF, 0xFF])

            self.new_transaction.inputs.append(inputTx)

            starting = False

            self.new_transaction.lockTime = bytearray([0, 0, 0, 0])
            self.tx_raw = bytearray(self.new_transaction.serialize())

        if self.tx_raw is not None:
            return (self.tx_raw, str(round(self.amount / 1e8, 8)))
        else:
            # transaction refused by user
            return (None, "")

    if __name__ == '__main__':
        unittest.main(verbosity=2)
Ejemplo n.º 12
0
class MainWindow(QWidget):

    def __init__(self, parent, masternode_list, imgDir):
        super(QWidget, self).__init__(parent)
        self.parent = parent
        self.imgDir = imgDir
        self.runInThread = ThreadFuns.runInThread
        ###-- Masternode list 
        self.masternode_list = masternode_list
        ###-- Create clients and statuses
        self.hwdevice = None
        self.hwStatus = 0
        self.hwStatusMess = "Not Connected"
        self.rpcClient = None
        self.rpcConnected = False
        self.rpcStatusMess = "Not Connected"
        self.isBlockchainSynced = False

        ###-- Load icons & images
        self.loadIcons()
        ###-- Create main layout
        self.layout = QVBoxLayout()
        self.header = GuiHeader(self)
        self.initConsole()
        self.layout.addWidget(self.header)
        ###-- Create RPC Whatchdog
        self.rpc_watchdogThread = QThread()
        self.myRpcWd = RpcWatchdog(self)
        self.myRpcWd.moveToThread(self.rpc_watchdogThread)
        self.rpc_watchdogThread.started.connect(self.myRpcWd.run)

        ###-- Create Queues and redirect stdout and stderr
        self.queue = Queue()
        self.queue2 = Queue()
        sys.stdout = WriteStream(self.queue)
        sys.stderr = WriteStream(self.queue2)

        ###-- Init last logs
        logFile = open(log_File, 'w+')
        timestamp = strftime('%Y-%m-%d %H:%M:%S', gmtime(now()))
        log_line = '<b style="color: blue">{}</b><br>'.format('STARTING QMT at ' + timestamp)
        logFile.write(log_line)
        logFile.close()

        ###-- Create the thread to update console log for stdout
        self.consoleLogThread = QThread()
        self.myWSReceiver = WriteStreamReceiver(self.queue)
        self.myWSReceiver.mysignal.connect(self.append_to_console)
        self.myWSReceiver.moveToThread(self.consoleLogThread)
        self.consoleLogThread.started.connect(self.myWSReceiver.run)
        self.consoleLogThread.start()
        printDbg("Console Log thread started")
        ###-- Create the thread to update console log for stderr
        self.consoleLogThread2 = QThread()
        self.myWSReceiver2 = WriteStreamReceiver(self.queue2)
        self.myWSReceiver2.mysignal.connect(self.append_to_console)
        self.myWSReceiver2.moveToThread(self.consoleLogThread2)
        self.consoleLogThread2.started.connect(self.myWSReceiver2.run)
        self.consoleLogThread2.start()
        printDbg("Console Log thread 2 started")

        ###-- Initialize tabs
        self.tabs = QTabWidget()
        self.t_main = TabMain(self)
        self.t_mnconf = TabMNConf(self)
        self.t_rewards = TabRewards(self)
        self.t_governance = TabGovernance(self)
        self.t_add_torrent = TabAddTorrent(self)

        ###-- Add tabs
        self.tabs.addTab(self.tabGovernance, "Search Torrents")
        self.tabs.addTab(self.tabAddTorrent, "Add Torrents")
#        self.tabs.addTab(self.tabMain, "Masternode Control")
#        self.tabs.addTab(self.tabMNConf, "MN Configuration")   # We will put these back later, just with RPC instead of messy key handling which we don't need or want anyway !
#        self.tabs.addTab(self.tabRewards, "Transfer Rewards")

        ###-- Connect change action
        self.tabs.currentChanged.connect(lambda: self.onTabChange())
        ###-- Draw Tabs 
        self.splitter = QSplitter(Qt.Vertical)
        ###-- Add tabs and console to Layout        
        self.splitter.addWidget(self.tabs)
        self.splitter.addWidget(self.console)
        self.splitter.setStretchFactor(0, 0)
        self.splitter.setStretchFactor(1, 1)
        self.splitter.setSizes(self.parent.cache.get("splitter_sizes"))
        self.layout.addWidget(self.splitter)

        ###-- Set Layout
        self.setLayout(self.layout)
        ###-- Let's go
        self.mnode_to_change = None
        printOK("Hello! Welcome to " + parent.title)

        ###-- Hide console if it was previously hidden
        if self.parent.cache.get("console_hidden"):
            self.onToggleConsole()

        ##-- Check version
        self.onCheckVersion()

        ##-- init Api Client
        self.apiClient = ApiClient()

    @pyqtSlot(str)
    def append_to_console(self, text):
        self.consoleArea.moveCursor(QTextCursor.End)
        self.consoleArea.insertHtml(text)

    def initConsole(self):
        self.console = QGroupBox()
        self.console.setTitle("Console Log")
        layout = QVBoxLayout()
        self.btn_consoleToggle = QPushButton('Hide')
        self.btn_consoleToggle.setToolTip('Show/Hide console')
        self.btn_consoleToggle.clicked.connect(lambda: self.onToggleConsole())
        consoleHeader = QHBoxLayout()
        consoleHeader.addWidget(self.btn_consoleToggle)
        self.consoleSaveButton = QPushButton('Save')
        self.consoleSaveButton.clicked.connect(lambda: self.onSaveConsole())
        consoleHeader.addWidget(self.consoleSaveButton)
        self.btn_consoleClean = QPushButton('Clean')
        self.btn_consoleClean.setToolTip('Clean console log area')
        self.btn_consoleClean.clicked.connect(lambda: self.onCleanConsole())
        consoleHeader.addWidget(self.btn_consoleClean)
        consoleHeader.addStretch(1)
        self.versionLabel = QLabel("--")
        self.versionLabel.setOpenExternalLinks(True)
        consoleHeader.addWidget(self.versionLabel)
        self.btn_checkVersion = QPushButton("Check QMT version")
        self.btn_checkVersion.setToolTip("Check latest stable release of QMT")
        self.btn_checkVersion.clicked.connect(lambda: self.onCheckVersion())
        consoleHeader.addWidget(self.btn_checkVersion)
        layout.addLayout(consoleHeader)
        self.consoleArea = QTextEdit()
        almostBlack = QColor(40, 40, 40)
        palette = QPalette()
        palette.setColor(QPalette.Base, almostBlack)
        green = QColor(0, 255, 0)
        palette.setColor(QPalette.Text, green)
        self.consoleArea.setPalette(palette)
        layout.addWidget(self.consoleArea)
        self.console.setLayout(layout)

    def isMasternodeInList(self, mn_alias):
        return (mn_alias in [x['name'] for x in self.masternode_list])

    def loadIcons(self):
        # Load Icons        
        self.ledPurpleH_icon = QPixmap(os.path.join(self.imgDir, 'icon_purpleLedH.png')).scaledToHeight(17,
                                                                                                        Qt.SmoothTransformation)
        self.ledGrayH_icon = QPixmap(os.path.join(self.imgDir, 'icon_grayLedH.png')).scaledToHeight(17,
                                                                                                    Qt.SmoothTransformation)
        self.ledHalfPurpleH_icon = QPixmap(os.path.join(self.imgDir, 'icon_halfPurpleLedH.png')).scaledToHeight(17,
                                                                                                                Qt.SmoothTransformation)
        self.ledRedV_icon = QPixmap(os.path.join(self.imgDir, 'icon_redLedV.png')).scaledToHeight(17,
                                                                                                  Qt.SmoothTransformation)
        self.ledGrayV_icon = QPixmap(os.path.join(self.imgDir, 'icon_grayLedV.png')).scaledToHeight(17,
                                                                                                    Qt.SmoothTransformation)
        self.ledGreenV_icon = QPixmap(os.path.join(self.imgDir, 'icon_greenLedV.png')).scaledToHeight(17,
                                                                                                      Qt.SmoothTransformation)

    def loadMNConf(self, fileName):
        hot_masternodes = loadMNConfFile(fileName)
        if hot_masternodes == None:
            messText = "Unable to load data from file '%s'" % fileName
            self.myPopUp2(QMessageBox.Warning, "QMT - warning", messText)
        else:
            # Append new masternodes to list
            new_masternodes = []
            skip_masternodes = []
            for x in hot_masternodes:
                if not self.isMasternodeInList(x['name']):
                    self.masternode_list.append(x)
                    new_masternodes.append(x)
                else:
                    skip_masternodes.append(x)

            # Show new list
            for new_masternode in new_masternodes:
                name = new_masternode['name']
                self.tabMain.insert_mn_list(name, new_masternode['ip'], new_masternode['port'], None, isHardware=False)
                self.tabMain.btn_remove[name].clicked.connect(lambda: self.t_main.onRemoveMN())

            # print number of nodes added
            new_nodes = len(new_masternodes)
            final_message = ""
            if new_nodes == 0:
                final_message = "No External Masternode "
            elif new_nodes == 1:
                final_message = "1 External Masternode "
            else:
                final_message = "%d External Masternodes " % new_nodes
            final_message += "added to the list. "
            if new_nodes > 0:
                final_message += str([x['name'] for x in new_masternodes]) + ".  "
            if len(skip_masternodes) > 0:
                final_message += "Following entries skipped due to duplicate names:"
                final_message += str([x['name'] for x in skip_masternodes]) + ".  "
            printDbg(final_message)

            if new_nodes > 0:
                # update files
                printDbg("saving MN configuration file")
                writeToFile(self.masternode_list, masternodes_File)
                printDbg("saved")
                # Clear voting masternodes configuration and update cache
                self.t_governance.clear()

    def myPopUp(self, messType, messTitle, messText, defaultButton=QMessageBox.No):
        mess = QMessageBox(messType, messTitle, messText, defaultButton, parent=self)
        mess.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        mess.setDefaultButton(defaultButton)
        return mess.exec_()

    def myPopUp2(self, messType, messTitle, messText, singleButton=QMessageBox.Ok):
        mess = QMessageBox(messType, messTitle, messText, singleButton, parent=self)
        mess.setStandardButtons(singleButton | singleButton)
        return mess.exec_()

    @pyqtSlot()
    def onCheckHw(self):
        printDbg("Checking for HW device...")
        self.updateHWstatus(None)
        self.showHWstatus()

    @pyqtSlot()
    def onCheckRpc(self):
        printDbg("Checking RPC server...")
        self.runInThread(self.updateRPCstatus, (), self.showRPCstatus)

    @pyqtSlot()
    def onCheckVersion(self):
        printDbg("Checking QMT version...")
        self.versionLabel.setText("--")
        self.runInThread(self.checkVersion, (), self.updateVersion)

    def checkVersion(self, ctrl):
        local_version = self.parent.version['number'].split('.')
        remote_version = getRemoteQMTversion().split('.')

        if (remote_version[0] > local_version[0]) or \
                (remote_version[0] == local_version[0] and remote_version[1] > local_version[1]) or \
                (remote_version[0] == local_version[0] and remote_version[1] == local_version[1] and remote_version[2] >
                 local_version[2]):
            self.versionMess = '<b style="color:red">New Version Available:</b> %s.%s.%s  ' % (
            remote_version[0], remote_version[1], remote_version[2])
            self.versionMess += '(<a href="https://github.com/project-qmc/QMT/releases/">download</a>)'
        else:
            self.versionMess = "You have the latest version of QMT"

    def updateVersion(self):
        if self.versionMess is not None:
            self.versionLabel.setText(self.versionMess)

    @pyqtSlot()
    def onCleanConsole(self):
        self.consoleArea.clear()

    @pyqtSlot()
    def onSaveConsole(self):
        timestamp = strftime('%Y-%m-%d_%H-%M-%S', gmtime(now()))
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getSaveFileName(self, "Save Logs to file", "QMT_Logs_%s.txt" % timestamp,
                                                  "All Files (*);; Text Files (*.txt)", options=options)
        try:
            if fileName:
                printOK("Saving logs to %s" % fileName)
                log_file = open(fileName, 'w+')
                log_text = self.consoleArea.toPlainText()
                log_file.write(log_text)
                log_file.close()

        except Exception as e:
            err_msg = "error writing Log file"
            printException(getCallerName(), getFunctionName(), err_msg, e.args)

    @pyqtSlot()
    def onTabChange(self):
        # reload (and re-sort)masternode list in tabs
        if self.tabs.currentWidget() == self.tabRewards:
            # reload last used address
            self.tabRewards.destinationLine.setText(self.parent.cache.get("lastAddress"))
            # get new order
            mnOrder = {}
            mnList = self.tabMain.myList
            for i in range(mnList.count()):
                mnName = mnList.itemWidget(mnList.item(i)).alias
                mnOrder[mnName] = i
            self.parent.cache['mnList_order'] = mnOrder
            # Sort masternode list (by alias if no previous order set)
            if self.parent.cache.get('mnList_order') != {}:
                self.masternode_list.sort(key=self.parent.extract_order)
            self.t_rewards.loadMnSelect()
            self.t_rewards.selectedRewards = None

        # reload torrent and voting masternode list
        if self.tabs.currentWidget() == self.tabGovernance:
            self.t_governance.onRefreshTorrents()
            self.t_governance.updateSelectedMNlabel()

    @pyqtSlot()
    def onToggleConsole(self):
        if self.btn_consoleToggle.text() == 'Hide':
            self.btn_consoleToggle.setText('Show')
            self.consoleArea.hide()
            self.console.setMinimumHeight(70)
            self.console.setMaximumHeight(70)
        else:
            self.console.setMinimumHeight(70)
            self.console.setMaximumHeight(starting_height)
            self.btn_consoleToggle.setText('Hide')
            self.consoleArea.show()

    def showHWstatus(self):
        self.updateHWleds()
        self.myPopUp2(QMessageBox.Information, 'QMT - hw check', "%s" % self.hwStatusMess, QMessageBox.Ok)

    def showRPCstatus(self):
        self.updateRPCled()
        self.myPopUp2(QMessageBox.Information, 'QMT - rpc check', "%s" % self.rpcStatusMess, QMessageBox.Ok)

    def updateHWleds(self):
        if self.hwStatus == 1:
            self.header.hwLed.setPixmap(self.ledHalfPurpleH_icon)
        elif self.hwStatus == 2:
            self.header.hwLed.setPixmap(self.ledPurpleH_icon)
        else:
            self.header.hwLed.setPixmap(self.ledGrayH_icon)
        self.header.hwLed.setToolTip(self.hwStatusMess)

    def updateHWstatus(self, ctrl):
        if self.hwdevice is not None:
            if hasattr(self.hwdevice, 'dongle'):
                self.hwdevice.dongle.close()

        self.hwdevice = HWdevice()

        statusCode, statusMess = self.hwdevice.getStatus()
        printDbg("mess: %s" % statusMess)
        if statusCode != 2:
            # If is not connected try again
            try:
                if hasattr(self.hwdevice, 'dongle'):
                    self.hwdevice.dongle.close()
                self.hwdevice = HWdevice()
                self.hwdevice.initDevice()
                statusCode, statusMess = self.hwdevice.getStatus()

            except Exception as e:
                err_msg = "error in checkHw"
                printException(getCallerName(), getFunctionName(), err_msg, e.args)

        self.hwStatus = statusCode
        self.hwStatusMess = statusMess

        # if all is good connect the signals
        if statusCode == 2:
            self.hwdevice.sigTxdone.connect(self.t_rewards.FinishSend)
            self.hwdevice.sigTxabort.connect(self.t_rewards.onCancel)
            self.hwdevice.tx_progress.connect(self.t_rewards.updateProgressPercent)

    def updateLastBlockLabel(self):
        text = '--'
        if self.rpcLastBlock == 1:
            text = "Loading block index..."
        elif self.rpcLastBlock > 0 and self.rpcConnected:
            text = str(self.rpcLastBlock)
            text += " ("
            if not self.isBlockchainSynced:
                text += "Synchronizing"
            else:
                text += "Synced"
            text += ")"

        self.header.lastBlockLabel.setText(text)

    def updateRPCled(self):
        if self.rpcConnected:
            self.header.rpcLed.setPixmap(self.ledPurpleH_icon)
        else:
            if self.rpcLastBlock == 1:
                self.header.rpcLed.setPixmap(self.ledHalfPurpleH_icon)
            else:
                self.header.rpcLed.setPixmap(self.ledGrayH_icon)

        self.header.rpcLed.setToolTip(self.rpcStatusMess)
        self.updateLastBlockLabel()

    def updateRPCstatus(self, ctrl):
        if self.rpcClient is None:
            self.rpcClient = RpcClient()

        status, statusMess, lastBlock = self.rpcClient.getStatus()

        self.rpcConnected = status
        self.rpcLastBlock = lastBlock
        self.rpcStatusMess = statusMess
        self.isBlockchainSynced = self.rpcClient.isBlockchainSynced()

        # If is not connected try again
        if not status:
            self.rpcClient = RpcClient()
Ejemplo n.º 13
0
    def __init__(self, parent, masternode_list, imgDir):
        super(QWidget, self).__init__(parent)
        self.parent = parent
        self.imgDir = imgDir
        self.runInThread = ThreadFuns.runInThread
        self.lock = threading.Lock()

        ###-- Masternode list
        self.masternode_list = masternode_list

        ###-- Create clients and statuses
        self.hwStatus = 0
        self.hwModel = 0
        self.hwStatusMess = "Not Connected"
        self.rpcClient = None
        self.rpcConnected = False
        self.updatingRPCbox = False
        self.rpcStatusMess = "Not Connected"
        self.isBlockchainSynced = False
        # Changes when an RPC client is connected (affecting API client)
        self.isTestnetRPC = self.parent.cache['isTestnetRPC']

        ###-- Load icons & images
        self.loadIcons()
        ###-- Create main layout
        self.layout = QVBoxLayout()
        self.header = GuiHeader(self)
        self.initConsole()
        self.layout.addWidget(self.header)

        ##-- Load RPC Servers list (init selection and self.isTestnet)
        self.updateRPClist()

        ##-- Init HW selection
        self.header.hwDevices.setCurrentIndex(
            self.parent.cache['selectedHW_index'])

        ##-- init HW Client
        self.hwdevice = HWdevice(self)

        ##-- init Api Client
        self.apiClient = ApiClient(self.isTestnetRPC)

        ###-- Create Queues and redirect stdout
        self.queue = Queue()
        sys.stdout = WriteStream(self.queue)

        ###-- Init last logs
        logging.debug("STARTING SPMT")

        ###-- Create the thread to update console log for stdout
        self.consoleLogThread = QThread()
        self.myWSReceiver = WriteStreamReceiver(self.queue)
        self.myWSReceiver.mysignal.connect(self.append_to_console)
        self.myWSReceiver.moveToThread(self.consoleLogThread)
        self.consoleLogThread.started.connect(self.myWSReceiver.run)
        self.consoleLogThread.start()
        printDbg("Console Log thread started")

        ###-- Initialize tabs
        self.tabs = QTabWidget()
        self.t_main = TabMain(self)
        self.t_mnconf = TabMNConf(self)
        self.t_rewards = TabRewards(self)
        self.t_governance = TabGovernance(self)

        ###-- Add tabs
        self.tabs.setTabPosition(QTabWidget.West)
        self.tabs.addTab(self.tabMain, "Masternode List")
        #self.tabs.addTab(self.tabMNConf, "MN Configuration")
        self.tabs.addTab(self.tabRewards, "Rewards")
        self.tabs.addTab(self.tabGovernance, "Governance")

        ###-- Connect change action
        self.tabs.currentChanged.connect(lambda: self.onTabChange())

        ###-- Add tabs and console to Layout
        self.splitter = QSplitter(Qt.Vertical)
        self.splitter.addWidget(self.tabs)
        self.splitter.addWidget(self.console)
        self.splitter.setStretchFactor(0, 0)
        self.splitter.setStretchFactor(1, 1)
        self.layout.addWidget(self.splitter)

        ###-- Set Layout
        self.setLayout(self.layout)

        ###-- Init Settings
        self.initSettings()

        ###-- Connect buttons/signals
        self.connButtons()

        ##-- Check version
        self.onCheckVersion()

        ###-- Create RPC Whatchdog
        self.rpc_watchdogThread = QThread()
        self.myRpcWd = RpcWatchdog(self)
        self.myRpcWd.moveToThread(self.rpc_watchdogThread)
        self.rpc_watchdogThread.started.connect(self.myRpcWd.run)

        ###-- Let's go
        self.mnode_to_change = None
        printOK("Hello! Welcome to " + parent.title)