Ejemplo n.º 1
0
    def handle_login(self):
        if not self.main_controller.bitshares_instance:
            if not self.connect_to_bitshares():
                return

        wallet_controller = WalletController(self.main_controller.bitshares_instance)

        if wallet_controller.wallet_created():
            unlock_view = UnlockWalletView(wallet_controller)
        else:
            unlock_view = CreateWalletView(wallet_controller)

        if unlock_view.exec_():
            # Hide button once successful wallet creation / login
            self.unlock_wallet_button.hide()
            self.add_worker_button.show()

            # Load worker widgets from config file
            workers = self.config.workers_data
            for worker_name in workers:
                self.add_worker_widget(worker_name)

                # Limit the max amount of workers so that the performance isn't greatly affected
                if self.num_of_workers >= self.max_workers:
                    self.add_worker_button.setEnabled(False)
                    break

            # Dispatcher polls for events from the workers that are used to change the ui
            self.dispatcher = ThreadDispatcher(self)
            self.dispatcher.start()

            self.status_bar.showMessage("ver {} - Node delay: - ms".format(__version__))
            self.status_bar_updater = Thread(target=self._update_statusbar_message)
            self.status_bar_updater.start()
Ejemplo n.º 2
0
    def __init__(self, main_ctrl):
        super().__init__()
        self.setupUi(self)
        self.main_ctrl = main_ctrl

        self.config = main_ctrl.config
        self.max_workers = 10
        self.num_of_workers = 0
        self.worker_widgets = {}
        self.closing = False
        self.statusbar_updater = None
        self.statusbar_updater_first_run = True
        self.main_ctrl.set_info_handler(self.set_worker_status)
        self.layout = FlowLayout(self.scrollAreaContent)

        self.add_worker_button_2.clicked.connect(
            lambda: self.handle_visualisation())
        self.add_worker_button.clicked.connect(
            lambda: self.handle_add_worker())
        self.settings_button.clicked.connect(
            lambda: self.handle_open_settings())
        self.help_button.clicked.connect(
            lambda: self.handle_open_documentation())

        # Load worker widgets from config file
        workers = self.config.workers_data
        for worker_name in workers:
            self.add_worker_widget(worker_name)

            # Limit the max amount of workers so that the performance isn't greatly affected
            if self.num_of_workers >= self.max_workers:
                self.add_worker_button.setEnabled(False)
                break

        # Dispatcher polls for events from the workers that are used to change the ui
        self.dispatcher = ThreadDispatcher(self)
        self.dispatcher.start()

        self.status_bar.showMessage(
            "ver {} - Node delay: - ms".format(__version__))
        self.statusbar_updater = Thread(target=self._update_statusbar_message)
        self.statusbar_updater.start()

        QtGui.QFontDatabase.addApplicationFont(
            ":/bot_widget/font/SourceSansPro-Bold.ttf")
Ejemplo n.º 3
0
class MainView(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, main_ctrl):
        super().__init__()
        self.setupUi(self)
        self.main_ctrl = main_ctrl

        self.config = main_ctrl.config
        self.max_workers = 10
        self.num_of_workers = 0
        self.worker_widgets = {}
        self.closing = False
        self.statusbar_updater = None
        self.statusbar_updater_first_run = True
        self.main_ctrl.set_info_handler(self.set_worker_status)
        self.layout = FlowLayout(self.scrollAreaContent)

        self.add_worker_button.clicked.connect(
            lambda: self.handle_add_worker())
        self.settings_button.clicked.connect(
            lambda: self.handle_open_settings())
        self.help_button.clicked.connect(
            lambda: self.handle_open_documentation())

        # Load worker widgets from config file
        workers = self.config.workers_data
        for worker_name in workers:
            self.add_worker_widget(worker_name)

            # Limit the max amount of workers so that the performance isn't greatly affected
            if self.num_of_workers >= self.max_workers:
                self.add_worker_button.setEnabled(False)
                break

        # Dispatcher polls for events from the workers that are used to change the ui
        self.dispatcher = ThreadDispatcher(self)
        self.dispatcher.start()

        self.status_bar.showMessage(
            "ver {} - Node delay: - ms".format(__version__))
        self.statusbar_updater = Thread(target=self._update_statusbar_message)
        self.statusbar_updater.start()

        QtGui.QFontDatabase.addApplicationFont(
            ":/bot_widget/font/SourceSansPro-Bold.ttf")

    def add_worker_widget(self, worker_name):
        config = self.config.get_worker_config(worker_name)
        widget = WorkerItemWidget(worker_name, config, self.main_ctrl, self)
        widget.setFixedSize(widget.frameSize())
        self.layout.addWidget(widget)
        self.worker_widgets[worker_name] = widget

        # Limit the max amount of workers so that the performance isn't greatly affected
        self.num_of_workers += 1
        if self.num_of_workers >= self.max_workers:
            self.add_worker_button.setEnabled(False)

    def remove_worker_widget(self, worker_name):
        self.worker_widgets.pop(worker_name, None)

        self.num_of_workers -= 1
        if self.num_of_workers < self.max_workers:
            self.add_worker_button.setEnabled(True)

    def change_worker_widget_name(self, old_worker_name, new_worker_name):
        worker_data = self.worker_widgets.pop(old_worker_name)
        self.worker_widgets[new_worker_name] = worker_data

    @gui_error
    def handle_add_worker(self):
        create_worker_dialog = CreateWorkerView(
            self.main_ctrl.bitshares_instance)
        return_value = create_worker_dialog.exec_()

        # User clicked save
        if return_value == 1:
            worker_name = create_worker_dialog.worker_name
            self.main_ctrl.create_worker(worker_name)

            self.config.add_worker_config(worker_name,
                                          create_worker_dialog.worker_data)
            self.add_worker_widget(worker_name)

    @gui_error
    def handle_open_settings(self):
        settings_dialog = SettingsView()
        return_value = settings_dialog.exec_()

    @staticmethod
    def handle_open_documentation():
        webbrowser.open('https://github.com/Codaone/DEXBot/wiki')

    def set_worker_name(self, worker_name, value):
        self.worker_widgets[worker_name].set_worker_name(value)

    def set_worker_account(self, worker_name, value):
        self.worker_widgets[worker_name].set_worker_account(value)

    def set_worker_profit(self, worker_name, value):
        self.worker_widgets[worker_name].set_worker_profit(value)

    def set_worker_market(self, worker_name, value):
        self.worker_widgets[worker_name].set_worker_market(value)

    def set_worker_slider(self, worker_name, value):
        self.worker_widgets[worker_name].set_worker_slider(value)

    def customEvent(self, event):
        # Process idle_queue_dispatcher events
        event.callback()

    def closeEvent(self, event):
        self.closing = True
        self.status_bar.showMessage("Closing app...")
        if self.statusbar_updater and self.statusbar_updater.is_alive():
            self.statusbar_updater.join()

    def _update_statusbar_message(self):
        while not self.closing:
            # When running first time the workers are also interrupting with the connection
            # so we delay the first time to get correct information
            if self.statusbar_updater_first_run:
                self.statusbar_updater_first_run = False
                time.sleep(1)

            msg = self.get_statusbar_message()
            idle_add(self.set_statusbar_message, msg)
            runner_count = 0
            # Wait for 30s but do it in 0.5s pieces to not prevent closing the app
            while not self.closing and runner_count < 60:
                runner_count += 1
                time.sleep(0.5)

    def get_statusbar_message(self):
        node = self.config['node']
        try:
            start = time.time()
            BitSharesNodeRPC(node, num_retries=1)
            latency = (time.time() - start) * 1000
        except BaseException:
            latency = -1

        if latency != -1:
            return "ver {} - Node delay: {:.2f}ms".format(__version__, latency)
        else:
            return "ver {} - Node disconnected".format(__version__)

    def set_statusbar_message(self, msg):
        self.status_bar.showMessage(msg)

    def set_worker_status(self, worker_name, level, status):
        if worker_name != 'NONE':
            worker = self.worker_widgets.get(worker_name, None)
            if worker:
                worker.set_status(status)
Ejemplo n.º 4
0
class MainView(QMainWindow, Ui_MainWindow):
    def __init__(self, main_controller):
        super().__init__()
        self.setupUi(self)
        self.main_controller = main_controller

        self.config = main_controller.config
        self.max_workers = 10
        self.num_of_workers = 0
        self.worker_widgets = {}
        self.closing = False
        self.status_bar_updater = None
        self.statusbar_updater_first_run = True
        self.main_controller.set_info_handler(self.set_worker_status)
        self.layout = FlowLayout(self.scrollAreaContent)
        self.dispatcher = None

        # GUI buttons
        self.add_worker_button.clicked.connect(self.handle_add_worker)
        self.settings_button.clicked.connect(self.handle_open_settings)
        self.help_button.clicked.connect(self.handle_open_documentation)
        self.unlock_wallet_button.clicked.connect(self.handle_login)

        # Hide certain buttons by default until login success
        self.add_worker_button.hide()

        self.status_bar.showMessage(
            "ver {} - Node disconnected".format(__version__))

        QFontDatabase.addApplicationFont(
            ":/bot_widget/font/SourceSansPro-Bold.ttf")

    def connect_to_bitshares(self):
        # Check if there is already a connection
        if self.config['node']:
            # Test nodes first. This only checks if we're able to connect
            self.status_bar.showMessage('Connecting to Bitshares...')
            try:
                self.main_controller.measure_latency(self.config['node'])
            except NumRetriesReached:
                self.status_bar.showMessage(
                    'ver {} - Coudn\'t connect to Bitshares. '
                    'Please use different node(s) and retry.'.format(
                        __version__))
                self.main_controller.set_bitshares_instance(None)
                return False

            self.main_controller.new_bitshares_instance(self.config['node'])
            self.status_bar.showMessage(self.get_statusbar_message())
            return True
        else:
            # Config has no nodes in it
            self.status_bar.showMessage(
                'ver {} - Node(s) not found. '
                'Please add node(s) from settings.'.format(__version__))
            return False

    @pyqtSlot(name='handle_login')
    def handle_login(self):
        if not self.main_controller.bitshares_instance:
            if not self.connect_to_bitshares():
                return

        wallet_controller = WalletController(
            self.main_controller.bitshares_instance)

        if wallet_controller.wallet_created():
            unlock_view = UnlockWalletView(wallet_controller)
        else:
            unlock_view = CreateWalletView(wallet_controller)

        if unlock_view.exec_():
            # Hide button once successful wallet creation / login
            self.unlock_wallet_button.hide()
            self.add_worker_button.show()

            # Load worker widgets from config file
            workers = self.config.workers_data
            for worker_name in workers:
                self.add_worker_widget(worker_name)

                # Limit the max amount of workers so that the performance isn't greatly affected
                if self.num_of_workers >= self.max_workers:
                    self.add_worker_button.setEnabled(False)
                    break

            # Dispatcher polls for events from the workers that are used to change the ui
            self.dispatcher = ThreadDispatcher(self)
            self.dispatcher.start()

            self.status_bar.showMessage(
                "ver {} - Node delay: - ms".format(__version__))
            self.status_bar_updater = Thread(
                target=self._update_statusbar_message)
            self.status_bar_updater.start()

    def add_worker_widget(self, worker_name):
        config = self.config.get_worker_config(worker_name)
        widget = WorkerItemWidget(worker_name, config, self.main_controller,
                                  self)
        widget.setFixedSize(widget.frameSize())
        self.layout.addWidget(widget)
        self.worker_widgets[worker_name] = widget

        # Limit the max amount of workers so that the performance isn't greatly affected
        self.num_of_workers += 1
        if self.num_of_workers >= self.max_workers:
            self.add_worker_button.setEnabled(False)

    def remove_worker_widget(self, worker_name):
        self.worker_widgets.pop(worker_name, None)

        self.num_of_workers -= 1
        if self.num_of_workers < self.max_workers:
            self.add_worker_button.setEnabled(True)

    def change_worker_widget_name(self, old_worker_name, new_worker_name):
        worker_data = self.worker_widgets.pop(old_worker_name)
        self.worker_widgets[new_worker_name] = worker_data

    @pyqtSlot(name='handle_add_worker')
    @gui_error
    def handle_add_worker(self):
        create_worker_dialog = CreateWorkerView(
            self.main_controller.bitshares_instance)
        return_value = create_worker_dialog.exec_()

        # User clicked save
        if return_value == 1:
            worker_name = create_worker_dialog.worker_name
            self.main_controller.create_worker(worker_name)

            self.config.add_worker_config(worker_name,
                                          create_worker_dialog.worker_data)
            self.add_worker_widget(worker_name)

    @pyqtSlot(name='handle_open_settings')
    @gui_error
    def handle_open_settings(self):
        settings_dialog = SettingsView()
        reconnect = settings_dialog.exec_()

        if reconnect:
            # Reinitialize config after closing the settings window
            self.config = Config()
            self.main_controller.config = self.config

            self.connect_to_bitshares()

    @staticmethod
    @pyqtSlot(name='handle_open_documentation')
    def handle_open_documentation():
        webbrowser.open('https://github.com/Codaone/DEXBot/wiki')

    def set_worker_name(self, worker_name, value):
        self.worker_widgets[worker_name].set_worker_name(value)

    def set_worker_account(self, worker_name, value):
        self.worker_widgets[worker_name].set_worker_account(value)

    def set_worker_profit(self, worker_name, value):
        self.worker_widgets[worker_name].set_worker_profit(value)

    def set_worker_market(self, worker_name, value):
        self.worker_widgets[worker_name].set_worker_market(value)

    def set_worker_slider(self, worker_name, value):
        self.worker_widgets[worker_name].set_worker_slider(value)

    def customEvent(self, event):
        # Process idle_queue_dispatcher events
        event.callback()

    def closeEvent(self, event):
        self.closing = True
        self.status_bar.showMessage("Closing app...")
        if self.status_bar_updater and self.status_bar_updater.is_alive():
            self.status_bar_updater.join()

    def _update_statusbar_message(self):
        while not self.closing:
            # When running first time the workers are also interrupting with the connection
            # so we delay the first time to get correct information
            if self.statusbar_updater_first_run:
                self.statusbar_updater_first_run = False
                time.sleep(1)

            msg = self.get_statusbar_message()
            idle_add(self.set_statusbar_message, msg)
            runner_count = 0
            # Wait for 30s but do it in 0.5s pieces to not prevent closing the app
            while not self.closing and runner_count < 60:
                runner_count += 1
                time.sleep(0.5)

    def get_statusbar_message(self):
        node = self.main_controller.bitshares_instance.rpc.url
        try:
            latency = self.main_controller.measure_latency(node)
        except BaseException:
            latency = -1

        if latency != -1:
            return "ver {} - Node delay: {:.2f}ms - node: {}".format(
                __version__, latency, node)
        else:
            return "ver {} - Node disconnected".format(__version__)

    def set_statusbar_message(self, msg):
        self.status_bar.showMessage(msg)

    def set_worker_status(self, worker_name, level, status):
        if worker_name != 'NONE':
            worker = self.worker_widgets.get(worker_name, None)
            if worker:
                worker.set_status(status)