Ejemplo n.º 1
0
class NexEventPoller(QRunnable):
    def __init__(self, device: NexDevice, poll_interval_ms: int):
        super().__init__()
        self._device = device
        self._logger = logging.getLogger("pynextion.NexEventPoller")
        self._run_poll_loop = True
        self._run_poll_loop_lock = QReadWriteLock()
        self._thread_local = threading.local()
        self._poll_interval_ms = poll_interval_ms

    def stop(self):
        self._logger.info("Stopping Nextion event poller loop")
        try:
            self._run_poll_loop_lock.lockForWrite()
            self._run_poll_loop = False
        finally:
            self._run_poll_loop_lock.unlock()

    def run(self):
        self._logger.info(
            "Starting Nextion event poller with a %d [ms] interval",
            self._poll_interval_ms)
        while True:
            try:
                self._run_poll_loop_lock.lockForRead()
                self._thread_local.run = self._run_poll_loop
            finally:
                self._run_poll_loop_lock.unlock()

            if not self._thread_local.run:
                self._logger.info("Exiting Nextion event poller loop")
                break

            self._device.poll()
            QThread.msleep(self._poll_interval_ms)
Ejemplo n.º 2
0
class CSerWind(QMainWindow):
    """
    主窗口
    """
    def __init__(self, inp_host, inp_port):
        super().__init__()

        self.lock = QReadWriteLock()

        self.recordSignal = RecordSignal()
        self.recordSignal.sendSignal.connect(self.my_record)

        self.tcpServer = TcpServer(self.recordSignal, self.lock)
        if not self.tcpServer.listen(QHostAddress(inp_host), inp_port):
            QMessageBox.critical(
                self, '交易服务器',
                '服务器启动失败:{0}'.format(self.tcpServer.errorString()))
            rec_text = my_cur_time() + ' 服务器启动失败!'
            try:
                self.lock.lockForWrite()
                self.recordSignal.sendSignal.emit(rec_text)
            finally:
                self.lock.unlock()
            self.close()
            return
        else:
            self._initUI()
            rec_text = my_cur_time() + ' 开启交易服务器!'
            try:
                self.lock.lockForWrite()
                self.recordSignal.sendSignal.emit(rec_text)
            finally:
                self.lock.unlock()

    def _initUI(self):
        self.setFixedSize(600, 400)
        self.move(0, 60)
        self.setWindowTitle('服务器:交易跟单——复制信号')
        self.setWindowIcon(QIcon('myIcon.ico'))

        # TableView设置MT4账号及Files文件夹路径
        self.model = QStandardItemModel(2, 2)
        self.model.setHorizontalHeaderLabels(['MT4账号', 'Files文件夹路径'])
        row = 0
        for key, value in account_dir.items():
            self.model.setItem(row, 0, QStandardItem(key))
            self.model.setItem(row, 1, QStandardItem(value))
            row += 1
        self.table = QTableView(self)
        self.table.setModel(self.model)
        self.table.resize(500, 180)
        self.table.move(10, 15)
        self.table.horizontalHeader().setStretchLastSection(True)

        tbn_append = QPushButton('添 加', self)
        tbn_append.resize(70, 25)
        tbn_append.move(520, 30)
        tbn_append.clicked.connect(self.my_btn_append_clicked)
        btn_delete = QPushButton('删 除', self)
        btn_delete.resize(70, 25)
        btn_delete.move(520, 90)
        btn_delete.clicked.connect(self.my_btn_delete_clicked)
        btn_save = QPushButton('保 存', self)
        btn_save.resize(70, 25)
        btn_save.move(520, 150)
        btn_save.clicked.connect(self.my_btn_save_clicked)

        # 逐条显示交易服务器操作的每个记录
        self.text_browser = QTextBrowser(self)
        self.text_browser.resize(580, 180)
        self.text_browser.move(10, 210)

        self.show()

    def closeEvent(self, event):
        reply = QMessageBox.question(self, '操作提示!', '您确定要关闭“交易服务器”?',
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            rec_text = my_cur_time() + ' 关闭交易服务器!'
            try:
                self.lock.lockForWrite()
                self.recordSignal.sendSignal.emit(rec_text)
            finally:
                self.lock.unlock()
            event.accept()
        else:
            event.ignore()

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape:
            self.showMinimized()

    def my_btn_append_clicked(self):
        """
        增加一个MT4账户
        """
        self.model.appendRow([QStandardItem(''), QStandardItem('')])

    def my_btn_delete_clicked(self):
        """
        删除当前行的MT4账号信息
        """
        reply = QMessageBox.question(self, '操作提示!', '确定要删除这条数据?',
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            index = self.table.currentIndex()
            self.model.removeRow(index.row())

    def my_btn_save_clicked(self):
        """
        保存MT4账户信息到account_dir.txt文件中
        """
        reply = QMessageBox.question(self, '操作提示!', '确定要覆盖原有数据?',
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            account_dir_new = {}
            rows = self.model.rowCount()
            for row in range(rows):
                key = self.model.item(row, 0).text()
                # 对MT4账号进行正则表达式匹配检查
                if not re.match(r'^[1-9]\d+$', key):
                    QMessageBox.critical(
                        self, '错误提示!',
                        self.tr('第 %s 行MT4账号格式不对!' % str(row + 1)))
                    return
                value = self.model.item(row, 1).text()
                if not os.path.exists(value) or value.find('\MQL4\Files') < 0:
                    QMessageBox.critical(
                        self, '错误提示!',
                        self.tr('第 %s 行Files文件路径不对!' % str(row + 1)))
                    return
                account_dir_new[key] = value
            # 保存文件
            try:
                account_dir = account_dir_new
                with open('account_dir.txt', 'w') as file_object:
                    file_object.write(str(account_dir))
            except Exception as e:
                QMessageBox.critical(
                    self, '错误提示!',
                    self.tr('保存MT4账户信息出现错误!{0}'.format(str(Exception))))
            # 记录这一操作
            rec_text = my_cur_time() + ' 已经保存了当前列表中MT4账户信息!'
            try:
                self.lock.lockForWrite()
                self.recordSignal.sendSignal.emit(rec_text)
            finally:
                self.lock.unlock()

    def my_record(self, inp_text):
        """
        记录服务器操作日志保存到日志文件,并在主窗口TextBrowser组件中显示出来
        """
        now = time.localtime()
        file_name = 'ser_' + time.strftime('%Y-%m-%d', now) + '.txt'
        rec_text = inp_text + '\n'

        with open(file_name, 'a+', encoding='UTF-8') as file_object:
            file_object.write(rec_text)

        # text_browser只显示当天的操作记录
        pre_text = self.text_browser.toPlainText()
        if len(pre_text) > 0 and pre_text[0:10] != inp_text[0:10]:
            self.text_browser.setText('')
        self.text_browser.append(inp_text)
Ejemplo n.º 3
0
class __Config(object):
    def __init__(self, debug=False):
        self.debug = debug
        self._dict = dict()
        self._prepare_dir()
        self._remove_tmps()
        self._lock = QReadWriteLock()

    def __getitem__(self, key):
        self._lock.lockForRead()
        r = self._dict[key]
        self._lock.unlock()
        return r

    def __setitem__(self, key, value):
        self._lock.lockForWrite()
        self._dict[key] = value
        self._lock.unlock()

    def get(self, key, default=None):
        self._lock.lockForRead()
        r = self._dict.get(key, default)
        self._lock.unlock()
        return r

    def pop(self, key, default=None):
        self._lock.lockForWrite()
        r = self._dict.pop(key, default)
        self._lock.unlock()
        return r

    def __contains__(self, key):
        self._lock.lockForRead()
        r = self._dict.__contains__(key)
        self._lock.unlock()
        return r

    def __str__(self):
        self._lock.lockForRead()
        s = "".join(
            [
                "Config(",
                ", ".join("{0}: {1}".format(k, v) for (k, v) in self._dict),
                ")",
            ]
        )
        self._lock.unlock()
        return s

    @property
    def _config_dir(self):
        # Windows
        if sys.platform.startswith("win"):
            if "LOCALAPPDATA" in os.environ:
                return os.path.join(os.environ["LOCALAPPDATA"], "LDOCE5Viewer")
            else:
                return os.path.join(os.environ["APPDATA"], "LDOCE5Viewer")
        # Mac OS X
        elif sys.platform.startswith("darwin"):
            return os.path.expanduser("~/Library/Application Support/LDOCE5Viewer")
        # Linux
        else:
            base = os.path.join(os.path.expanduser("~"), ".config")
            # XDG
            try:
                import xdg.BaseDirectory

                base = xdg.BaseDirectory.xdg_config_home
            except ImportError:
                if "XDG_CONFIG_HOME" in os.environ:
                    base = os.environ["XDG_CONFIG_HOME"]
            return os.path.join(base, "ldoce5viewer")

    @property
    def _data_dir(self):
        # Windows
        if sys.platform.startswith("win"):
            return self._config_dir
        # Mac OS X
        elif sys.platform.startswith("darwin"):
            return self._config_dir
        # Linux
        else:
            base = os.path.join(os.path.expanduser("~"), ".local/share/")
            # XDG
            try:
                import xdg.BaseDirectory

                base = xdg.BaseDirectory.xdg_data_home
            except ImportError:
                if "XDG_DATA_HOME" in os.environ:
                    base = os.environ["XDG_DATA_HOME"]
            return os.path.join(base, "ldoce5viewer")

    @property
    def app_name(self):
        return "LDOCE5 Viewer"

    @property
    def _config_path(self):
        return os.path.join(self._config_dir, "config.pickle")

    @property
    def filemap_path(self):
        return os.path.join(self._data_dir, "filemap.cdb")

    @property
    def variations_path(self):
        return os.path.join(self._data_dir, "variations.cdb")

    @property
    def incremental_path(self):
        return os.path.join(self._data_dir, "incremental.db")

    @property
    def fulltext_hwdphr_path(self):
        return os.path.join(self._data_dir, "fulltext_hp")

    @property
    def fulltext_defexa_path(self):
        return os.path.join(self._data_dir, "fulltext_de")

    @property
    def scan_tmp_path(self):
        return os.path.join(self._data_dir, "scan" + self.tmp_suffix)

    @property
    def tmp_suffix(self):
        return ".tmp"

    def _remove_tmps(self):
        for name in os.listdir(self._config_dir) + os.listdir(self._data_dir):
            if name.endswith(self.tmp_suffix):
                path = os.path.join(self._config_dir, name)
                try:
                    if os.path.isfile(path):
                        os.remove(path)
                    elif os.path.isdir(path):
                        shutil.rmtree(path)
                except OSError:
                    pass

    def _prepare_dir(self):
        if not os.path.exists(self._config_dir):
            os.makedirs(self._config_dir)
        if not os.path.exists(self._data_dir):
            os.makedirs(self._data_dir)

    def load(self):
        self._lock.lockForWrite()
        try:
            with open(self._config_path, "rb") as f:
                self._dict.clear()
                try:
                    data = pickle.load(f)
                except:
                    pass
                else:
                    self._dict.update(data)
        except IOError:
            self._dict.clear()
        self._lock.unlock()

    def save(self):
        self._lock.lockForRead()

        if sys.platform == "win32":
            with open(self._config_path, "wb") as f:
                pickle.dump(self._dict, f)
        else:
            f = tempfile.NamedTemporaryFile(
                dir=self._config_dir, delete=False, suffix=self.tmp_suffix
            )
            pickle.dump(self._dict, f, protocol=0)
            f.close()
            os.rename(f.name, self._config_path)

        self._lock.unlock()
Ejemplo n.º 4
0
class __Config(object):
    def __init__(self, debug=False):
        self.debug = debug
        self._dict = dict()
        self._prepare_dir()
        self._remove_tmps()
        self._lock = QReadWriteLock()

    def __getitem__(self, key):
        self._lock.lockForRead()
        r = self._dict[key]
        self._lock.unlock()
        return r

    def __setitem__(self, key, value):
        self._lock.lockForWrite()
        self._dict[key] = value
        self._lock.unlock()

    def get(self, key, default=None):
        self._lock.lockForRead()
        r = self._dict.get(key, default)
        self._lock.unlock()
        return r

    def pop(self, key, default=None):
        self._lock.lockForWrite()
        r = self._dict.pop(key, default)
        self._lock.unlock()
        return r

    def __contains__(self, key):
        self._lock.lockForRead()
        r = self._dict.__contains__(key)
        self._lock.unlock()
        return r

    def __str__(self):
        self._lock.lockForRead()
        s = ''.join([
            'Config(',
            ', '.join("{0}: {1}".format(k, v) for (k, v) in self._dict), ')'
        ])
        self._lock.unlock()
        return s

    @property
    def _config_dir(self):
        # Windows
        if sys.platform.startswith('win'):
            if 'LOCALAPPDATA' in os.environ:
                return os.path.join(os.environ['LOCALAPPDATA'], 'LDOCE5Viewer')
            else:
                return os.path.join(os.environ['APPDATA'], 'LDOCE5Viewer')
        # Mac OS X
        elif sys.platform.startswith('darwin'):
            return os.path.expanduser(
                '~/Library/Application Support/LDOCE5Viewer')
        # Linux
        else:
            base = os.path.join(os.path.expanduser('~'), '.config')
            # XDG
            try:
                import xdg.BaseDirectory
                base = xdg.BaseDirectory.xdg_config_home
            except ImportError:
                if 'XDG_CONFIG_HOME' in os.environ:
                    base = os.environ['XDG_CONFIG_HOME']
            return os.path.join(base, 'ldoce5viewer')

    @property
    def _data_dir(self):
        # Windows
        if sys.platform.startswith('win'):
            return self._config_dir
        # Mac OS X
        elif sys.platform.startswith('darwin'):
            return self._config_dir
        # Linux
        else:
            base = os.path.join(os.path.expanduser('~'), '.local/share/')
            # XDG
            try:
                import xdg.BaseDirectory
                base = xdg.BaseDirectory.xdg_data_home
            except ImportError:
                if 'XDG_DATA_HOME' in os.environ:
                    base = os.environ['XDG_DATA_HOME']
            return os.path.join(base, 'ldoce5viewer')

    @property
    def app_name(self):
        return 'LDOCE5 Viewer'

    @property
    def _config_path(self):
        return os.path.join(self._config_dir, 'config.pickle')

    @property
    def filemap_path(self):
        return os.path.join(self._data_dir, 'filemap.cdb')

    @property
    def variations_path(self):
        return os.path.join(self._data_dir, 'variations.cdb')

    @property
    def incremental_path(self):
        return os.path.join(self._data_dir, 'incremental.db')

    @property
    def fulltext_hwdphr_path(self):
        return os.path.join(self._data_dir, 'fulltext_hp')

    @property
    def fulltext_defexa_path(self):
        return os.path.join(self._data_dir, 'fulltext_de')

    @property
    def scan_tmp_path(self):
        return os.path.join(self._data_dir, 'scan' + self.tmp_suffix)

    @property
    def tmp_suffix(self):
        return '.tmp'

    def _remove_tmps(self):
        for name in os.listdir(self._config_dir) + os.listdir(self._data_dir):
            if name.endswith(self.tmp_suffix):
                path = os.path.join(self._config_dir, name)
                try:
                    if os.path.isfile(path):
                        os.remove(path)
                    elif os.path.isdir(path):
                        shutil.rmtree(path)
                except OSError:
                    pass

    def _prepare_dir(self):
        if not os.path.exists(self._config_dir):
            os.makedirs(self._config_dir)
        if not os.path.exists(self._data_dir):
            os.makedirs(self._data_dir)

    def load(self):
        self._lock.lockForWrite()
        try:
            with open(self._config_path, 'rb') as f:
                self._dict.clear()
                try:
                    data = pickle.load(f)
                except:
                    pass
                else:
                    self._dict.update(data)
        except IOError:
            self._dict.clear()
        self._lock.unlock()

    def save(self):
        self._lock.lockForRead()

        if sys.platform == 'win32':
            with open(self._config_path, 'wb') as f:
                pickle.dump(self._dict, f)
        else:
            f = tempfile.NamedTemporaryFile(dir=self._config_dir,
                                            delete=False,
                                            suffix=self.tmp_suffix)
            pickle.dump(self._dict, f, protocol=0)
            f.close()
            os.rename(f.name, self._config_path)

        self._lock.unlock()