Ejemplo n.º 1
0
 def initDockWidgets(self):
     self.server_view_dock = HkuSessionViewWidget(self)
     self.server_view_dock.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable)  # 禁止关闭
     self.server_view_dock.setMinimumWidth(200)
     # 消除 docker window 的顶部按钮
     title_bar = self.server_view_dock.titleBarWidget()
     self.server_view_dock.setTitleBarWidget(QtWidgets.QWidget())
     del title_bar
     self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.server_view_dock)
     servers = self.db.session.query(SessionModel).order_by(SessionModel.name.asc()).all()
     for server in servers:
         self.server_view_dock.addSession(server)
Ejemplo n.º 2
0
 def initDockWidgets(self):
     self.server_view_dock = HkuSessionViewWidget(self)
     self.server_view_dock.setFeatures(
         QtWidgets.QDockWidget.DockWidgetMovable)  # 禁止关闭
     self.server_view_dock.setMinimumWidth(200)
     # 消除 docker window 的顶部按钮
     title_bar = self.server_view_dock.titleBarWidget()
     self.server_view_dock.setTitleBarWidget(QtWidgets.QWidget())
     del title_bar
     self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.server_view_dock)
     servers = self.db.session.query(SessionModel).order_by(
         SessionModel.name.asc()).all()
     for server in servers:
         server.running = False  # SQLalchemy query 出来的对象并没有添加非数据库外的属性,此处手工添加保护
         self.server_view_dock.addSession(server)
     self.server_view_dock.user_manage_trigger.connect(
         self.openUserManageTab)
Ejemplo n.º 3
0
class MyMainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        appid = 'HikyuuAdmin'
        QtWidgets.QApplication.setApplicationName(appid)
        QtWidgets.QApplication.setOrganizationName("org.hikyuu")

        # 国际化支持
        loc = QtCore.QLocale()
        if loc.language() == QtCore.QLocale.Chinese:
            self.trans = QtCore.QTranslator()
            self.trans.load("{}/language/zh_CN.qm".format(
                os.path.dirname(__file__)))  # 读取qm语言包
            _app = QtWidgets.QApplication.instance()  # 应用实例
            _app.installTranslator(self.trans)  # 将翻译者安装到实例中

        # 设置程序图标资源
        # 如未能正常显示图标,请检查 "import resource" 是否
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(":/logo/logo_16.png"))
        icon.addPixmap(QtGui.QPixmap(":/logo/logo_32.png"))
        icon.addPixmap(QtGui.QPixmap(":/logo/logo_48.png"))
        icon.addPixmap(QtGui.QPixmap(":/logo/logo_64.png"))
        icon.addPixmap(QtGui.QPixmap(":/logo/logo_128.png"))
        icon.addPixmap(QtGui.QPixmap(":/logo/logo_256.png"))
        self.setWindowIcon(icon)
        if sys.platform == 'win32':
            # window下设置任务栏图片
            import ctypes
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
                appid)

        self.ui_config = UiConfig()
        self.setObjectName("HikyuuAdminMainWindow")
        self.setWindowTitle(
            _translate("MainWindow", "Hikyuu Strategy Server Manager"))

        # 绑定本地数据库,辅助使用,尽量直接使用 Model 中的方法
        self.db = get_local_db()

        self.initAction()
        self.initMenuBar()
        self.initMenu()
        self.initToolBar()
        self.initActionConnect()
        self.initMainTabWidget()
        self.initDockWidgets()
        self.statusBar().showMessage(_translate('MainWindow', 'Running'))

        # 在窗口初始化完毕后,根据历史信息对窗口风格和大小进行重置
        style = self.ui_config.get('main_window',
                                   'style',
                                   fallback='normal_style')
        if style == 'dark_style':
            QtWidgets.qApp.setStyleSheet(
                qdarkstyle.load_stylesheet(qt_api='pyqt5'))

        if self.ui_config.getboolean('main_window',
                                     'maximized',
                                     fallback=False):
            self.showMaximized()
        else:
            self.resize(
                self.ui_config.getint('main_window', 'width', fallback=800),
                self.ui_config.getint('main_window', 'height', fallback=500))

        QtCore.QMetaObject.connectSlotsByName(self)

    @property
    def session(self):
        return self.db.session

    def closeEvent(self, event):
        self.ui_config.save(self)
        event.accept()

    def initAction(self):
        self.action_dict = dict(
            action_new_file_session=QtWidgets.QAction(
                QtGui.QIcon(":/icon/new_16.png"),
                _translate("MainWindow", "&New Session"), self),
            action_edit_file_session=QtWidgets.QAction(
                QtGui.QIcon(":/icon/edit_16.png"),
                _translate("MainWindow", "&Edit Session"), self),
            action_del_file_session=QtWidgets.QAction(
                QtGui.QIcon(":/icon/cancel_16.png"),
                _translate("MainWindow", "&Remove Session"), self),
            action_file_connect=QtWidgets.QAction(
                _translate('MainWindow', '&Connect Now')),
            action_file_quit=QtWidgets.QAction(
                QtGui.QIcon(":/icon/quit_16.png"),
                _translate('MainWindow', '&Quit'), self),
            action_view_normal_style=QtWidgets.QAction(
                _translate('MainWindow', 'Normal style'), self),
            action_view_dark_style=QtWidgets.QAction(
                _translate('MainWindow', 'Dark style'), self),
            action_about=QtWidgets.QAction(_translate('MainWindow', 'About'),
                                           self),
            action_about_qt=QtWidgets.QAction(
                _translate('MainWindow', 'About Qt'), self),
        )
        self.action_dict['action_new_file_session'].setStatusTip(
            _translate('MainWindow', 'New Session'))
        self.action_dict['action_file_connect'].setStatusTip(
            _translate('MainWindow', 'Connect Now'))
        self.action_dict['action_file_quit'].setStatusTip(
            _translate('MainWindow', 'Quit Application'))
        self.action_dict['action_about_qt'].setStatusTip(
            _translate('MainWindow', "Show the Qt library's About box"))
        self.action_dict['action_view_normal_style'].setObjectName(
            'normal_style')
        self.action_dict['action_view_normal_style'].setStatusTip(
            _translate('MainWindow', 'Switch to normal style'))
        self.action_dict['action_view_dark_style'].setObjectName('dark_style')
        self.action_dict['action_view_dark_style'].setStatusTip(
            _translate('MainWindow', 'Switch to dark style'))
        self.action_dict['action_edit_file_session'].setEnabled(False)
        self.action_dict['action_del_file_session'].setEnabled(False)

    def initMenuBar(self):
        self.menubar_dict = dict(menu_file=self.menuBar().addMenu(
            _translate('MainWindow', "&File(F)")),
                                 menu_view=self.menuBar().addMenu(
                                     _translate('MainWindow', "&View(V)")),
                                 menu_help=self.menuBar().addMenu(
                                     _translate('MainWindow', "&Help(H)")))

    def initMenu(self):
        file_session_menu = self.menubar_dict['menu_file'].addMenu(
            QtGui.QIcon(":/icon/server_16.png"),
            _translate('MainWindow', '&Session Manager'))
        style_menu = self.menubar_dict['menu_view'].addMenu(
            _translate('MainWindow', 'Skin style'))
        self.menu_dict = dict(
            menu_file_new_session=file_session_menu.addAction(
                self.action_dict['action_new_file_session']),
            menu_file_edit_session=file_session_menu.addAction(
                self.action_dict['action_edit_file_session']),
            menu_file_del_session=file_session_menu.addAction(
                self.action_dict['action_del_file_session']),
            menu_file_connect=self.menubar_dict['menu_file'].addAction(
                self.action_dict['action_file_connect']),
            menu_file_quit=self.menubar_dict['menu_file'].addAction(
                self.action_dict['action_file_quit']),
            menu_view_normal_style=style_menu.addAction(
                self.action_dict['action_view_normal_style']),
            menu_view_dark_style=style_menu.addAction(
                self.action_dict['action_view_dark_style']),
            menu_about=self.menubar_dict['menu_help'].addAction(
                self.action_dict['action_about']),
            menu_about_qt=self.menubar_dict['menu_help'].addAction(
                self.action_dict['action_about_qt']),
        )

    def initToolBar(self):
        self.setUnifiedTitleAndToolBarOnMac(True)
        file_toolbar = self.addToolBar('File')
        file_toolbar.addAction(self.action_dict['action_new_file_session'])
        file_toolbar.addAction(self.action_dict['action_edit_file_session'])
        file_toolbar.addAction(self.action_dict['action_del_file_session'])
        file_toolbar.addAction(self.action_dict['action_file_connect'])
        file_toolbar.addAction(self.action_dict['action_file_quit'])

    def initActionConnect(self):
        self.action_dict['action_new_file_session'].triggered.connect(
            self.actionNewSession)
        self.action_dict['action_edit_file_session'].triggered.connect(
            self.actionEditSession)
        self.action_dict['action_del_file_session'].triggered.connect(
            self.actionDeleteSession)
        self.action_dict['action_file_connect'].triggered.connect(
            self.actionConnect)
        self.action_dict['action_file_quit'].triggered.connect(self.close)
        self.action_dict['action_about'].triggered.connect(self.actionAbout)
        self.action_dict['action_about_qt'].triggered.connect(
            QtWidgets.QApplication.aboutQt)
        self.action_dict['action_view_normal_style'].triggered.connect(
            self.actionChangStyle)
        self.action_dict['action_view_dark_style'].triggered.connect(
            self.actionChangStyle)

    def initMainTabWidget(self):
        self.main_tab = QtWidgets.QTabWidget()
        self.setCentralWidget(self.main_tab)

        # 设置为可关闭,并连接信号
        self.main_tab.setTabsClosable(True)
        self.main_tab.tabCloseRequested.connect(self.closeTab)

        self.tab_title_user_manage = _translate("MainWindow", "User Manage")
        self.tabs = {}

    def initDockWidgets(self):
        self.server_view_dock = HkuSessionViewWidget(self)
        self.server_view_dock.setFeatures(
            QtWidgets.QDockWidget.DockWidgetMovable)  # 禁止关闭
        self.server_view_dock.setMinimumWidth(200)
        # 消除 docker window 的顶部按钮
        title_bar = self.server_view_dock.titleBarWidget()
        self.server_view_dock.setTitleBarWidget(QtWidgets.QWidget())
        del title_bar
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.server_view_dock)
        servers = self.db.session.query(SessionModel).order_by(
            SessionModel.name.asc()).all()
        for server in servers:
            self.server_view_dock.addSession(server)
        self.server_view_dock.user_manage_trigger.connect(
            self.openUserManageTab)

    def actionAbout(self):
        msg = _translate(
            'MainWindow', "<p><b>Hikyuu Strategy Server Manager</b><p>"
            "<p>Hikyuu strategy server management is used to "
            "manage quant trading strategies based on hikyuu "
            "quant framework</p>"
            "<p><b>Hikyuu Quant Framework</b></p>"
            "It is a high performance open source quantitative "
            "trading research framework based on C++/Python, "
            "which is used for stratgy analysis and back testing."
            "Now it only used in Chinese stock market)</p>"
            '<p>see more: <a href="https://hikyuu.org">https://hikyuu.org<a></p>'
        )
        QtWidgets.QMessageBox.about(
            self,
            _translate('MainWindow', 'About Hikyuu Strategy Server Manager'),
            msg)

    def actionChangStyle(self):
        QtWidgets.qApp.setStyleSheet('')
        style_name = self.sender().objectName()
        if style_name == 'dark_style':
            QtWidgets.qApp.setStyleSheet(
                qdarkstyle.load_stylesheet(qt_api='pyqt5'))
        self.ui_config.set('main_window', 'style', style_name)

    def actionNewSession(self):
        server_session = SessionModel()
        session_dialog = HkuEditSessionDialog(self)
        session_dialog.setWindowTitle(_translate("MainWindow", "New Session"))
        session_dialog.setData(server_session)
        if session_dialog.exec() >= 0:
            session_data = session_dialog.getData()
            session_data.save()
            self.server_view_dock.addSession(session_data)
        session_dialog.destroy()

    def actionEditSession(self):
        item = self.server_view_dock.tree.currentItem()
        server_session = self.db.session.query(SessionModel).filter_by(
            name=item.text(0)).first() if item else None
        if server_session is None:
            QtWidgets.QMessageBox.about(
                self, _translate("MainWindow", "info"),
                _translate("MainWindow", "Please select a session to execute"))
            return
        edit_session_dialog = HkuEditSessionDialog(self)
        edit_session_dialog.setWindowTitle(
            _translate("MainWindow", "Edit Session"))
        edit_session_dialog.setData(server_session)
        if edit_session_dialog.exec() >= 0:
            session_data = edit_session_dialog.getData()
            session_data.save()
            self.server_view_dock.modifySession(item, session_data)
        edit_session_dialog.destroy()

    def actionDeleteSession(self):
        item = self.server_view_dock.tree.currentItem()
        data = item.data(0, QtCore.Qt.UserRole) if item is not None else None
        if data is None:
            QtWidgets.QMessageBox.about(
                self, _translate("MainWindow", "info"),
                _translate("MainWindow", "Please select a session to execute"))
            return
        ret = QtWidgets.QMessageBox.question(
            self, _translate("MainWindow", "Confirm removal"),
            _translate("MainWindow", "Confirm to remove the session (%s)?") %
            item.text(0), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
        if ret == QtWidgets.QMessageBox.Yes:
            root_index = self.server_view_dock.tree.indexOfTopLevelItem(item)
            self.server_view_dock.tree.takeTopLevelItem(root_index)
            data.delete()

    def actionConnect(self):
        item = self.server_view_dock.tree.currentItem()
        session = item.data(0, QtCore.Qt.UserRole)
        status, msg = AssisService.getServerStatus(session)
        icons = {
            "running": QtGui.QIcon(":/icon/circular_green.png"),
            "stop": QtGui.QIcon(":/icon/circular_yellow.png")
        }
        item.setText(1, msg)
        item.setIcon(1, icons[status])
        self.server_view_dock.tree.viewport().update()
        if not session.running:
            QtWidgets.QMessageBox.warning(
                self, _translate("MainWindow", "info"),
                _translate("MainWindow", "connection failed"))

    def closeTab(self, index):
        title = self.main_tab.tabText(index)
        self.main_tab.removeTab(index)
        self.tabs[title] = None

    def openUserManageTab(self, session):
        """用户管理"""
        title = "{}({})".format(self.tab_title_user_manage, session.name)
        if title not in self.tabs or self.tabs[title] is None:
            if not session.running:
                QtWidgets.QMessageBox.warning(
                    self, _translate("MainWindow", "info"),
                    _translate(
                        "MainWindow",
                        "The server is disconnected. Please connect first!"))
            else:
                tab = HkuUserManagerWidget(session, self.main_tab)
                self.main_tab.addTab(tab, title)
                self.tabs[title] = tab