2018-07-26 06:13:42 +00:00
|
|
|
|
# encoding: UTF-8
|
|
|
|
|
|
|
|
|
|
import json
|
|
|
|
|
import csv
|
|
|
|
|
import os
|
|
|
|
|
import platform
|
|
|
|
|
from collections import OrderedDict
|
|
|
|
|
|
|
|
|
|
from six import text_type
|
|
|
|
|
|
|
|
|
|
from vnpy.event import *
|
|
|
|
|
from vnpy.trader import vtText
|
|
|
|
|
from vnpy.trader.vtEvent import *
|
|
|
|
|
from vnpy.trader.vtConstant import *
|
|
|
|
|
from vnpy.trader.vtFunction import *
|
|
|
|
|
from vnpy.trader.vtGateway import *
|
|
|
|
|
from vnpy.trader.uiQt import QtGui, QtWidgets, QtCore, BASIC_FONT
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
COLOR_RED = QtGui.QColor('red')
|
|
|
|
|
COLOR_GREEN = QtGui.QColor('green')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class BasicCell(QtWidgets.QTableWidgetItem):
|
|
|
|
|
"""基础的单元格"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, text=None, mainEngine=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(BasicCell, self).__init__()
|
|
|
|
|
self.data = None
|
2018-07-26 09:40:29 +00:00
|
|
|
|
|
|
|
|
|
self.setTextAlignment(QtCore.Qt.AlignCenter)
|
|
|
|
|
|
2018-07-26 06:13:42 +00:00
|
|
|
|
if text:
|
|
|
|
|
self.setContent(text)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setContent(self, text):
|
|
|
|
|
"""设置内容"""
|
|
|
|
|
if text == '0' or text == '0.0':
|
|
|
|
|
self.setText('')
|
|
|
|
|
else:
|
|
|
|
|
self.setText(text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
2018-07-26 09:40:29 +00:00
|
|
|
|
class NumCell(BasicCell):
|
2018-07-26 06:13:42 +00:00
|
|
|
|
"""用来显示数字的单元格"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, text=None, mainEngine=None):
|
|
|
|
|
"""Constructor"""
|
2018-07-26 09:40:29 +00:00
|
|
|
|
super(NumCell, self).__init__(text)
|
|
|
|
|
|
2018-07-26 06:13:42 +00:00
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setContent(self, text):
|
|
|
|
|
"""设置内容"""
|
|
|
|
|
# 考虑到NumCell主要用来显示OrderID和TradeID之类的整数字段,
|
|
|
|
|
# 这里的数据转化方式使用int类型。但是由于部分交易接口的委托
|
|
|
|
|
# 号和成交号可能不是纯数字的形式,因此补充了一个try...except
|
|
|
|
|
try:
|
|
|
|
|
num = int(text)
|
|
|
|
|
self.setData(QtCore.Qt.DisplayRole, num)
|
|
|
|
|
except ValueError:
|
|
|
|
|
self.setText(text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
2018-07-26 09:40:29 +00:00
|
|
|
|
class DirectionCell(BasicCell):
|
2018-07-26 06:13:42 +00:00
|
|
|
|
"""用来显示买卖方向的单元格"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, text=None, mainEngine=None):
|
|
|
|
|
"""Constructor"""
|
2018-07-26 09:40:29 +00:00
|
|
|
|
super(DirectionCell, self).__init__(text)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setContent(self, text):
|
|
|
|
|
"""设置内容"""
|
|
|
|
|
if text == DIRECTION_LONG or text == DIRECTION_NET:
|
|
|
|
|
self.setForeground(QtGui.QColor('red'))
|
|
|
|
|
elif text == DIRECTION_SHORT:
|
|
|
|
|
self.setForeground(QtGui.QColor('green'))
|
|
|
|
|
self.setText(text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
2018-07-26 09:40:29 +00:00
|
|
|
|
class NameCell(BasicCell):
|
2018-07-26 06:13:42 +00:00
|
|
|
|
"""用来显示合约中文的单元格"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, text=None, mainEngine=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(NameCell, self).__init__()
|
|
|
|
|
|
|
|
|
|
self.mainEngine = mainEngine
|
|
|
|
|
self.data = None
|
|
|
|
|
|
|
|
|
|
if text:
|
|
|
|
|
self.setContent(text)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setContent(self, text):
|
|
|
|
|
"""设置内容"""
|
|
|
|
|
if self.mainEngine:
|
|
|
|
|
# 首先尝试正常获取合约对象
|
|
|
|
|
contract = self.mainEngine.getContract(text)
|
|
|
|
|
|
|
|
|
|
# 如果能读取合约信息
|
|
|
|
|
if contract:
|
|
|
|
|
self.setText(contract.name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
2018-07-26 09:40:29 +00:00
|
|
|
|
class BidCell(BasicCell):
|
2018-07-26 06:13:42 +00:00
|
|
|
|
"""买价单元格"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, text=None, mainEngine=None):
|
|
|
|
|
"""Constructor"""
|
2018-07-26 09:40:29 +00:00
|
|
|
|
super(BidCell, self).__init__(text)
|
|
|
|
|
|
2018-07-26 06:13:42 +00:00
|
|
|
|
self.setForeground(QtGui.QColor('black'))
|
|
|
|
|
self.setBackground(QtGui.QColor(255,174,201))
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setContent(self, text):
|
|
|
|
|
"""设置内容"""
|
|
|
|
|
self.setText(text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
2018-07-26 09:40:29 +00:00
|
|
|
|
class AskCell(BasicCell):
|
2018-07-26 06:13:42 +00:00
|
|
|
|
"""卖价单元格"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, text=None, mainEngine=None):
|
|
|
|
|
"""Constructor"""
|
2018-07-26 09:40:29 +00:00
|
|
|
|
super(AskCell, self).__init__(text)
|
|
|
|
|
|
2018-07-26 06:13:42 +00:00
|
|
|
|
self.setForeground(QtGui.QColor('black'))
|
|
|
|
|
self.setBackground(QtGui.QColor(160,255,160))
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setContent(self, text):
|
|
|
|
|
"""设置内容"""
|
|
|
|
|
self.setText(text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
2018-07-26 09:40:29 +00:00
|
|
|
|
class PnlCell(BasicCell):
|
2018-07-26 06:13:42 +00:00
|
|
|
|
"""显示盈亏的单元格"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, text=None, mainEngine=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(PnlCell, self).__init__()
|
|
|
|
|
self.data = None
|
|
|
|
|
self.color = ''
|
|
|
|
|
if text:
|
|
|
|
|
self.setContent(text)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setContent(self, text):
|
|
|
|
|
"""设置内容"""
|
|
|
|
|
self.setText(text)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
value = float(text)
|
|
|
|
|
if value >= 0 and self.color != 'red':
|
|
|
|
|
self.color = 'red'
|
|
|
|
|
self.setForeground(COLOR_RED)
|
|
|
|
|
elif value < 0 and self.color != 'green':
|
|
|
|
|
self.color = 'green'
|
|
|
|
|
self.setForeground(COLOR_GREEN)
|
|
|
|
|
except ValueError:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class BasicMonitor(QtWidgets.QTableWidget):
|
|
|
|
|
"""
|
|
|
|
|
基础监控
|
|
|
|
|
|
|
|
|
|
headerDict中的值对应的字典格式如下
|
|
|
|
|
{'chinese': u'中文名', 'cellType': BasicCell}
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
signal = QtCore.Signal(type(Event()))
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine=None, eventEngine=None, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(BasicMonitor, self).__init__(parent)
|
|
|
|
|
|
|
|
|
|
self.mainEngine = mainEngine
|
|
|
|
|
self.eventEngine = eventEngine
|
|
|
|
|
|
|
|
|
|
# 保存表头标签用
|
|
|
|
|
self.headerDict = OrderedDict() # 有序字典,key是英文名,value是对应的配置字典
|
|
|
|
|
self.headerList = [] # 对应self.headerDict.keys()
|
|
|
|
|
|
|
|
|
|
# 保存相关数据用
|
|
|
|
|
self.dataDict = {} # 字典,key是字段对应的数据,value是保存相关单元格的字典
|
|
|
|
|
self.dataKey = '' # 字典键对应的数据字段
|
|
|
|
|
|
|
|
|
|
# 监控的事件类型
|
|
|
|
|
self.eventType = ''
|
|
|
|
|
|
|
|
|
|
# 列宽调整状态(只在第一次更新数据时调整一次列宽)
|
|
|
|
|
self.columnResized = False
|
|
|
|
|
|
|
|
|
|
# 字体
|
|
|
|
|
self.font = None
|
|
|
|
|
|
|
|
|
|
# 保存数据对象到单元格
|
|
|
|
|
self.saveData = False
|
|
|
|
|
|
|
|
|
|
# 默认不允许根据表头进行排序,需要的组件可以开启
|
|
|
|
|
self.sorting = False
|
|
|
|
|
|
2018-07-26 09:40:29 +00:00
|
|
|
|
# 默认表头可调整
|
|
|
|
|
self.resizeMode = QtWidgets.QHeaderView.Interactive
|
|
|
|
|
|
2018-07-26 06:13:42 +00:00
|
|
|
|
# 初始化右键菜单
|
|
|
|
|
self.initMenu()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setHeaderDict(self, headerDict):
|
|
|
|
|
"""设置表头有序字典"""
|
|
|
|
|
self.headerDict = headerDict
|
|
|
|
|
self.headerList = headerDict.keys()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setDataKey(self, dataKey):
|
|
|
|
|
"""设置数据字典的键"""
|
|
|
|
|
self.dataKey = dataKey
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setEventType(self, eventType):
|
|
|
|
|
"""设置监控的事件类型"""
|
|
|
|
|
self.eventType = eventType
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setFont(self, font):
|
|
|
|
|
"""设置字体"""
|
|
|
|
|
self.font = font
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setSaveData(self, saveData):
|
|
|
|
|
"""设置是否要保存数据到单元格"""
|
|
|
|
|
self.saveData = saveData
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def initTable(self):
|
|
|
|
|
"""初始化表格"""
|
|
|
|
|
# 设置表格的列数
|
|
|
|
|
col = len(self.headerDict)
|
|
|
|
|
self.setColumnCount(col)
|
|
|
|
|
|
|
|
|
|
# 设置列表头
|
|
|
|
|
labels = [d['chinese'] for d in self.headerDict.values()]
|
|
|
|
|
self.setHorizontalHeaderLabels(labels)
|
|
|
|
|
|
|
|
|
|
# 关闭左边的垂直表头
|
|
|
|
|
self.verticalHeader().setVisible(False)
|
|
|
|
|
|
|
|
|
|
# 设为不可编辑
|
|
|
|
|
self.setEditTriggers(self.NoEditTriggers)
|
|
|
|
|
|
|
|
|
|
# 设为行交替颜色
|
|
|
|
|
self.setAlternatingRowColors(True)
|
|
|
|
|
|
|
|
|
|
# 设置允许排序
|
|
|
|
|
self.setSortingEnabled(self.sorting)
|
2018-07-26 09:40:29 +00:00
|
|
|
|
|
|
|
|
|
# 设为表头拉伸
|
|
|
|
|
self.horizontalHeader().setSectionResizeMode(self.resizeMode)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def registerEvent(self):
|
|
|
|
|
"""注册GUI更新相关的事件监听"""
|
|
|
|
|
self.signal.connect(self.updateEvent)
|
|
|
|
|
self.eventEngine.register(self.eventType, self.signal.emit)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def updateEvent(self, event):
|
|
|
|
|
"""收到事件更新"""
|
|
|
|
|
data = event.dict_['data']
|
|
|
|
|
self.updateData(data)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def updateData(self, data):
|
|
|
|
|
"""将数据更新到表格中"""
|
|
|
|
|
# 如果允许了排序功能,则插入数据前必须关闭,否则插入新的数据会变乱
|
|
|
|
|
if self.sorting:
|
|
|
|
|
self.setSortingEnabled(False)
|
|
|
|
|
|
|
|
|
|
# 如果设置了dataKey,则采用存量更新模式
|
|
|
|
|
if self.dataKey:
|
|
|
|
|
key = data.__getattribute__(self.dataKey)
|
|
|
|
|
# 如果键在数据字典中不存在,则先插入新的一行,并创建对应单元格
|
|
|
|
|
if key not in self.dataDict:
|
|
|
|
|
self.insertRow(0)
|
|
|
|
|
d = {}
|
|
|
|
|
for n, header in enumerate(self.headerList):
|
|
|
|
|
content = safeUnicode(data.__getattribute__(header))
|
|
|
|
|
cellType = self.headerDict[header]['cellType']
|
|
|
|
|
cell = cellType(content, self.mainEngine)
|
|
|
|
|
|
|
|
|
|
if self.font:
|
|
|
|
|
cell.setFont(self.font) # 如果设置了特殊字体,则进行单元格设置
|
|
|
|
|
|
|
|
|
|
if self.saveData: # 如果设置了保存数据对象,则进行对象保存
|
|
|
|
|
cell.data = data
|
|
|
|
|
|
|
|
|
|
self.setItem(0, n, cell)
|
|
|
|
|
d[header] = cell
|
|
|
|
|
self.dataDict[key] = d
|
|
|
|
|
# 否则如果已经存在,则直接更新相关单元格
|
|
|
|
|
else:
|
|
|
|
|
d = self.dataDict[key]
|
|
|
|
|
for header in self.headerList:
|
|
|
|
|
content = safeUnicode(data.__getattribute__(header))
|
|
|
|
|
cell = d[header]
|
|
|
|
|
cell.setContent(content)
|
|
|
|
|
|
|
|
|
|
if self.saveData: # 如果设置了保存数据对象,则进行对象保存
|
|
|
|
|
cell.data = data
|
|
|
|
|
# 否则采用增量更新模式
|
|
|
|
|
else:
|
|
|
|
|
self.insertRow(0)
|
|
|
|
|
for n, header in enumerate(self.headerList):
|
|
|
|
|
content = safeUnicode(data.__getattribute__(header))
|
|
|
|
|
cellType = self.headerDict[header]['cellType']
|
|
|
|
|
cell = cellType(content, self.mainEngine)
|
|
|
|
|
|
|
|
|
|
if self.font:
|
|
|
|
|
cell.setFont(self.font)
|
|
|
|
|
|
|
|
|
|
if self.saveData:
|
|
|
|
|
cell.data = data
|
|
|
|
|
|
|
|
|
|
self.setItem(0, n, cell)
|
|
|
|
|
|
2018-07-26 09:40:29 +00:00
|
|
|
|
## 调整列宽
|
|
|
|
|
#if not self.columnResized:
|
|
|
|
|
#self.resizeColumns()
|
|
|
|
|
#self.columnResized = True
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
# 重新打开排序
|
|
|
|
|
if self.sorting:
|
|
|
|
|
self.setSortingEnabled(True)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def resizeColumns(self):
|
|
|
|
|
"""调整各列的大小"""
|
|
|
|
|
self.horizontalHeader().resizeSections(QtWidgets.QHeaderView.ResizeToContents)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setSorting(self, sorting):
|
|
|
|
|
"""设置是否允许根据表头排序"""
|
|
|
|
|
self.sorting = sorting
|
2018-07-26 09:40:29 +00:00
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setResizeMode(self, mode):
|
|
|
|
|
""""""
|
|
|
|
|
self.resizeMode = mode
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def saveToCsv(self):
|
|
|
|
|
"""保存表格内容到CSV文件"""
|
|
|
|
|
# 先隐藏右键菜单
|
|
|
|
|
self.menu.close()
|
|
|
|
|
|
|
|
|
|
# 获取想要保存的文件名
|
|
|
|
|
path, fileType = QtWidgets.QFileDialog.getSaveFileName(self, vtText.SAVE_DATA, '', 'CSV(*.csv)')
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
#if not path.isEmpty():
|
|
|
|
|
if path:
|
|
|
|
|
with open(unicode(path), 'wb') as f:
|
|
|
|
|
writer = csv.writer(f)
|
|
|
|
|
|
|
|
|
|
# 保存标签
|
|
|
|
|
headers = [header.encode('gbk') for header in self.headerList]
|
|
|
|
|
writer.writerow(headers)
|
|
|
|
|
|
|
|
|
|
# 保存每行内容
|
|
|
|
|
for row in range(self.rowCount()):
|
|
|
|
|
rowdata = []
|
|
|
|
|
for column in range(self.columnCount()):
|
|
|
|
|
item = self.item(row, column)
|
|
|
|
|
if item is not None:
|
|
|
|
|
rowdata.append(
|
|
|
|
|
text_type(item.text()).encode('gbk'))
|
|
|
|
|
else:
|
|
|
|
|
rowdata.append('')
|
|
|
|
|
writer.writerow(rowdata)
|
|
|
|
|
except IOError:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def initMenu(self):
|
|
|
|
|
"""初始化右键菜单"""
|
|
|
|
|
self.menu = QtWidgets.QMenu(self)
|
|
|
|
|
|
|
|
|
|
resizeAction = QtWidgets.QAction(vtText.RESIZE_COLUMNS, self)
|
|
|
|
|
resizeAction.triggered.connect(self.resizeColumns)
|
|
|
|
|
|
|
|
|
|
saveAction = QtWidgets.QAction(vtText.SAVE_DATA, self)
|
|
|
|
|
saveAction.triggered.connect(self.saveToCsv)
|
|
|
|
|
|
|
|
|
|
self.menu.addAction(resizeAction)
|
|
|
|
|
self.menu.addAction(saveAction)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def contextMenuEvent(self, event):
|
|
|
|
|
"""右键点击事件"""
|
|
|
|
|
self.menu.popup(QtGui.QCursor.pos())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class MarketMonitor(BasicMonitor):
|
|
|
|
|
"""市场监控组件"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, eventEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(MarketMonitor, self).__init__(mainEngine, eventEngine, parent)
|
|
|
|
|
|
|
|
|
|
# 设置表头有序字典
|
|
|
|
|
d = OrderedDict()
|
2018-07-26 09:40:29 +00:00
|
|
|
|
d['gatewayName'] = {'chinese':vtText.GATEWAY, 'cellType':BasicCell}
|
2018-07-26 06:13:42 +00:00
|
|
|
|
d['symbol'] = {'chinese':vtText.CONTRACT_SYMBOL, 'cellType':BasicCell}
|
|
|
|
|
d['lastPrice'] = {'chinese':vtText.LAST_PRICE, 'cellType':BasicCell}
|
|
|
|
|
d['volume'] = {'chinese':vtText.VOLUME, 'cellType':BasicCell}
|
|
|
|
|
d['openPrice'] = {'chinese':vtText.OPEN_PRICE, 'cellType':BasicCell}
|
|
|
|
|
d['highPrice'] = {'chinese':vtText.HIGH_PRICE, 'cellType':BasicCell}
|
|
|
|
|
d['lowPrice'] = {'chinese':vtText.LOW_PRICE, 'cellType':BasicCell}
|
|
|
|
|
d['bidPrice1'] = {'chinese':vtText.BID_PRICE_1, 'cellType':BidCell}
|
|
|
|
|
d['bidVolume1'] = {'chinese':vtText.BID_VOLUME_1, 'cellType':BidCell}
|
|
|
|
|
d['askPrice1'] = {'chinese':vtText.ASK_PRICE_1, 'cellType':AskCell}
|
|
|
|
|
d['askVolume1'] = {'chinese':vtText.ASK_VOLUME_1, 'cellType':AskCell}
|
|
|
|
|
d['time'] = {'chinese':vtText.TIME, 'cellType':BasicCell}
|
|
|
|
|
self.setHeaderDict(d)
|
|
|
|
|
|
|
|
|
|
self.setDataKey('vtSymbol')
|
|
|
|
|
self.setEventType(EVENT_TICK)
|
|
|
|
|
self.setFont(BASIC_FONT)
|
|
|
|
|
self.setSorting(False)
|
2018-07-26 09:40:29 +00:00
|
|
|
|
self.setResizeMode(QtWidgets.QHeaderView.Stretch)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
self.initTable()
|
|
|
|
|
self.registerEvent()
|
2018-07-26 09:40:29 +00:00
|
|
|
|
|
|
|
|
|
self.setFixedHeight(400)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class LogMonitor(BasicMonitor):
|
|
|
|
|
"""日志监控"""
|
|
|
|
|
signalError = QtCore.Signal(type(Event()))
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, eventEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(LogMonitor, self).__init__(mainEngine, eventEngine, parent)
|
|
|
|
|
|
|
|
|
|
d = OrderedDict()
|
2018-07-26 09:40:29 +00:00
|
|
|
|
d['gatewayName'] = {'chinese':vtText.GATEWAY, 'cellType':BasicCell}
|
2018-07-26 06:13:42 +00:00
|
|
|
|
d['logTime'] = {'chinese':vtText.TIME, 'cellType':BasicCell}
|
|
|
|
|
d['logContent'] = {'chinese':vtText.CONTENT, 'cellType':BasicCell}
|
|
|
|
|
self.setHeaderDict(d)
|
|
|
|
|
|
|
|
|
|
self.setEventType(EVENT_LOG)
|
|
|
|
|
self.setFont(BASIC_FONT)
|
|
|
|
|
self.initTable()
|
|
|
|
|
self.registerEvent()
|
|
|
|
|
|
|
|
|
|
self.signalError.connect(self.processErrorEvent)
|
|
|
|
|
self.eventEngine.register(EVENT_ERROR, self.signalError.emit)
|
2018-07-26 09:40:29 +00:00
|
|
|
|
|
|
|
|
|
self.horizontalHeader().setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)
|
|
|
|
|
self.setFixedHeight(200)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def processErrorEvent(self, event):
|
|
|
|
|
""""""
|
|
|
|
|
error = event.dict_['data']
|
|
|
|
|
logContent = u'发生错误,错误代码:%s,错误信息:%s' %(error.errorID, error.errorMsg)
|
|
|
|
|
|
|
|
|
|
self.insertRow(0)
|
|
|
|
|
cellLogTime = BasicCell(error.errorTime)
|
|
|
|
|
cellLogContent = BasicCell(logContent)
|
|
|
|
|
cellGatewayName = BasicCell(error.gatewayName)
|
|
|
|
|
|
2018-08-05 14:03:43 +00:00
|
|
|
|
self.setItem(0, 0, cellGatewayName)
|
|
|
|
|
self.setItem(0, 1, cellLogTime)
|
|
|
|
|
self.setItem(0, 2, cellLogContent)
|
|
|
|
|
|
|
|
|
|
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class TradeMonitor(BasicMonitor):
|
|
|
|
|
"""成交监控"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, eventEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(TradeMonitor, self).__init__(mainEngine, eventEngine, parent)
|
|
|
|
|
|
|
|
|
|
d = OrderedDict()
|
2018-07-26 09:40:29 +00:00
|
|
|
|
d['gatewayName'] = {'chinese':vtText.GATEWAY, 'cellType':BasicCell}
|
2018-07-26 06:13:42 +00:00
|
|
|
|
d['tradeID'] = {'chinese':vtText.TRADE_ID, 'cellType':NumCell}
|
|
|
|
|
d['orderID'] = {'chinese':vtText.ORDER_ID, 'cellType':NumCell}
|
|
|
|
|
d['symbol'] = {'chinese':vtText.CONTRACT_SYMBOL, 'cellType':BasicCell}
|
|
|
|
|
d['direction'] = {'chinese':vtText.DIRECTION, 'cellType':DirectionCell}
|
|
|
|
|
d['price'] = {'chinese':vtText.PRICE, 'cellType':BasicCell}
|
|
|
|
|
d['volume'] = {'chinese':vtText.VOLUME, 'cellType':BasicCell}
|
|
|
|
|
d['tradeTime'] = {'chinese':vtText.TRADE_TIME, 'cellType':BasicCell}
|
|
|
|
|
self.setHeaderDict(d)
|
|
|
|
|
|
|
|
|
|
self.setEventType(EVENT_TRADE)
|
|
|
|
|
self.setFont(BASIC_FONT)
|
|
|
|
|
self.setSorting(True)
|
2018-07-26 09:40:29 +00:00
|
|
|
|
self.setResizeMode(QtWidgets.QHeaderView.Stretch)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
self.initTable()
|
|
|
|
|
self.registerEvent()
|
|
|
|
|
|
2018-07-26 09:40:29 +00:00
|
|
|
|
self.setFixedHeight(200)
|
|
|
|
|
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class OrderMonitor(BasicMonitor):
|
|
|
|
|
"""委托监控"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, eventEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(OrderMonitor, self).__init__(mainEngine, eventEngine, parent)
|
|
|
|
|
|
|
|
|
|
self.mainEngine = mainEngine
|
|
|
|
|
|
|
|
|
|
d = OrderedDict()
|
2018-07-26 09:40:29 +00:00
|
|
|
|
d['gatewayName'] = {'chinese':vtText.GATEWAY, 'cellType':BasicCell}
|
2018-07-26 06:13:42 +00:00
|
|
|
|
d['orderID'] = {'chinese':vtText.ORDER_ID, 'cellType':NumCell}
|
|
|
|
|
d['symbol'] = {'chinese':vtText.CONTRACT_SYMBOL, 'cellType':BasicCell}
|
|
|
|
|
d['direction'] = {'chinese':vtText.DIRECTION, 'cellType':DirectionCell}
|
|
|
|
|
d['price'] = {'chinese':vtText.PRICE, 'cellType':BasicCell}
|
|
|
|
|
d['totalVolume'] = {'chinese':vtText.ORDER_VOLUME, 'cellType':BasicCell}
|
|
|
|
|
d['tradedVolume'] = {'chinese':vtText.TRADED_VOLUME, 'cellType':BasicCell}
|
|
|
|
|
d['status'] = {'chinese':vtText.ORDER_STATUS, 'cellType':BasicCell}
|
|
|
|
|
d['orderTime'] = {'chinese':vtText.ORDER_TIME, 'cellType':BasicCell}
|
|
|
|
|
self.setHeaderDict(d)
|
|
|
|
|
|
|
|
|
|
self.setDataKey('vtOrderID')
|
|
|
|
|
self.setEventType(EVENT_ORDER)
|
|
|
|
|
self.setFont(BASIC_FONT)
|
|
|
|
|
self.setSaveData(True)
|
|
|
|
|
self.setSorting(True)
|
2018-07-26 09:40:29 +00:00
|
|
|
|
self.setResizeMode(QtWidgets.QHeaderView.Stretch)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
self.initTable()
|
|
|
|
|
self.registerEvent()
|
|
|
|
|
self.connectSignal()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def connectSignal(self):
|
|
|
|
|
"""连接信号"""
|
|
|
|
|
# 双击单元格撤单
|
|
|
|
|
self.itemDoubleClicked.connect(self.cancelOrder)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def cancelOrder(self, cell):
|
|
|
|
|
"""根据单元格的数据撤单"""
|
|
|
|
|
order = cell.data
|
|
|
|
|
|
|
|
|
|
req = VtCancelOrderReq()
|
|
|
|
|
req.symbol = order.symbol
|
|
|
|
|
req.exchange = order.exchange
|
|
|
|
|
req.frontID = order.frontID
|
|
|
|
|
req.sessionID = order.sessionID
|
|
|
|
|
req.orderID = order.orderID
|
|
|
|
|
self.mainEngine.cancelOrder(req, order.gatewayName)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class PositionMonitor(BasicMonitor):
|
|
|
|
|
"""持仓监控"""
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, eventEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(PositionMonitor, self).__init__(mainEngine, eventEngine, parent)
|
|
|
|
|
|
|
|
|
|
d = OrderedDict()
|
2018-07-26 09:40:29 +00:00
|
|
|
|
d['gatewayName'] = {'chinese':vtText.GATEWAY, 'cellType':BasicCell}
|
2018-07-26 06:13:42 +00:00
|
|
|
|
d['symbol'] = {'chinese':vtText.CONTRACT_SYMBOL, 'cellType':BasicCell}
|
|
|
|
|
d['direction'] = {'chinese':vtText.DIRECTION, 'cellType':DirectionCell}
|
|
|
|
|
d['position'] = {'chinese':vtText.POSITION, 'cellType':BasicCell}
|
|
|
|
|
d['frozen'] = {'chinese':vtText.FROZEN, 'cellType':BasicCell}
|
|
|
|
|
d['price'] = {'chinese':vtText.PRICE, 'cellType':BasicCell}
|
|
|
|
|
self.setHeaderDict(d)
|
|
|
|
|
|
|
|
|
|
self.setDataKey('vtPositionName')
|
|
|
|
|
self.setEventType(EVENT_POSITION)
|
|
|
|
|
self.setFont(BASIC_FONT)
|
|
|
|
|
self.setSaveData(True)
|
2018-07-26 09:40:29 +00:00
|
|
|
|
self.setResizeMode(QtWidgets.QHeaderView.Stretch)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
self.initTable()
|
|
|
|
|
self.registerEvent()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class AccountMonitor(BasicMonitor):
|
|
|
|
|
"""账户监控"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, eventEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(AccountMonitor, self).__init__(mainEngine, eventEngine, parent)
|
|
|
|
|
|
|
|
|
|
d = OrderedDict()
|
2018-07-26 09:40:29 +00:00
|
|
|
|
d['gatewayName'] = {'chinese':vtText.GATEWAY, 'cellType':BasicCell}
|
2018-07-26 06:13:42 +00:00
|
|
|
|
d['accountID'] = {'chinese':vtText.ACCOUNT_ID, 'cellType':BasicCell}
|
|
|
|
|
d['balance'] = {'chinese':vtText.BALANCE, 'cellType':BasicCell}
|
|
|
|
|
d['available'] = {'chinese':vtText.AVAILABLE, 'cellType':BasicCell}
|
|
|
|
|
self.setHeaderDict(d)
|
|
|
|
|
|
|
|
|
|
self.setDataKey('vtAccountID')
|
|
|
|
|
self.setEventType(EVENT_ACCOUNT)
|
|
|
|
|
self.setFont(BASIC_FONT)
|
2018-07-26 09:40:29 +00:00
|
|
|
|
self.setSaveData(True)
|
|
|
|
|
self.setResizeMode(QtWidgets.QHeaderView.Stretch)
|
|
|
|
|
|
2018-07-26 06:13:42 +00:00
|
|
|
|
self.initTable()
|
|
|
|
|
self.registerEvent()
|
2018-07-26 09:40:29 +00:00
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def updateData(self, data):
|
|
|
|
|
"""更新数据"""
|
|
|
|
|
super(AccountMonitor, self).updateData(data)
|
|
|
|
|
|
|
|
|
|
# 如果该委托已完成,则隐藏该行
|
|
|
|
|
vtAccountID = data.vtAccountID
|
|
|
|
|
cellDict = self.dataDict[vtAccountID]
|
|
|
|
|
cell = cellDict['balance']
|
|
|
|
|
row = self.row(cell)
|
|
|
|
|
|
|
|
|
|
if data.balance == 0:
|
|
|
|
|
self.hideRow(row)
|
|
|
|
|
else:
|
|
|
|
|
self.showRow(row)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class DepthMonitor(QtWidgets.QTableWidget):
|
|
|
|
|
"""报价深度监控"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, eventEngine):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(DepthMonitor, self).__init__()
|
|
|
|
|
|
|
|
|
|
self.mainEngine = mainEngine
|
|
|
|
|
|
|
|
|
|
self.contractSize = 1 # 合约乘数
|
|
|
|
|
self.cellDict = {}
|
|
|
|
|
|
|
|
|
|
self.initUi()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def initUi(self):
|
|
|
|
|
""""""
|
|
|
|
|
labels = [u'价格',
|
|
|
|
|
u'数量',
|
|
|
|
|
u'总额']
|
|
|
|
|
|
|
|
|
|
self.setColumnCount(len(labels))
|
|
|
|
|
self.setHorizontalHeaderLabels(labels)
|
|
|
|
|
self.setRowCount(11)
|
|
|
|
|
self.verticalHeader().setVisible(False)
|
|
|
|
|
self.setEditTriggers(self.NoEditTriggers)
|
|
|
|
|
self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
|
|
|
|
|
self.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
|
|
|
|
|
|
|
|
|
|
left = QtCore.Qt.AlignLeft
|
|
|
|
|
right = QtCore.Qt.AlignRight
|
|
|
|
|
|
|
|
|
|
# 单元格
|
|
|
|
|
askColor = 'green'
|
|
|
|
|
bidColor = 'red'
|
|
|
|
|
lastColor = 'orange'
|
|
|
|
|
|
|
|
|
|
self.addCell('askPrice5', 0, 0, askColor)
|
|
|
|
|
self.addCell('askPrice4', 1, 0, askColor)
|
|
|
|
|
self.addCell('askPrice3', 2, 0, askColor)
|
|
|
|
|
self.addCell('askPrice2', 3, 0, askColor)
|
|
|
|
|
self.addCell('askPrice1', 4, 0, askColor)
|
|
|
|
|
self.addCell('lastPrice', 5, 0, lastColor)
|
|
|
|
|
self.addCell('bidPrice1', 6, 0, bidColor)
|
|
|
|
|
self.addCell('bidPrice2', 7, 0, bidColor)
|
|
|
|
|
self.addCell('bidPrice3', 8, 0, bidColor)
|
|
|
|
|
self.addCell('bidPrice4', 9, 0, bidColor)
|
|
|
|
|
self.addCell('bidPrice5', 10, 0, bidColor)
|
|
|
|
|
|
|
|
|
|
self.addCell('askVolume5', 0, 1, askColor)
|
|
|
|
|
self.addCell('askVolume4', 1, 1, askColor)
|
|
|
|
|
self.addCell('askVolume3', 2, 1, askColor)
|
|
|
|
|
self.addCell('askVolume2', 3, 1, askColor)
|
|
|
|
|
self.addCell('askVolume1', 4, 1, askColor)
|
|
|
|
|
self.addCell('todayChange', 5, 1, lastColor)
|
|
|
|
|
self.addCell('bidVolume1', 6, 1, bidColor)
|
|
|
|
|
self.addCell('bidVolume2', 7, 1, bidColor)
|
|
|
|
|
self.addCell('bidVolume3', 8, 1, bidColor)
|
|
|
|
|
self.addCell('bidVolume4', 9, 1, bidColor)
|
|
|
|
|
self.addCell('bidVolume5', 10, 1, bidColor)
|
|
|
|
|
|
|
|
|
|
self.addCell('askValue5', 0, 2, askColor)
|
|
|
|
|
self.addCell('askValue4', 1, 2, askColor)
|
|
|
|
|
self.addCell('askValue3', 2, 2, askColor)
|
|
|
|
|
self.addCell('askValue2', 3, 2, askColor)
|
|
|
|
|
self.addCell('askValue1', 4, 2, askColor)
|
|
|
|
|
self.addCell('bidValue1', 6, 2, bidColor)
|
|
|
|
|
self.addCell('bidValue2', 7, 2, bidColor)
|
|
|
|
|
self.addCell('bidValue3', 8, 2, bidColor)
|
|
|
|
|
self.addCell('bidValue4', 9, 2, bidColor)
|
|
|
|
|
self.addCell('bidValue5', 10, 2, bidColor)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def addCell(self, name, row, col, color, alignment=None):
|
|
|
|
|
"""新增单元格"""
|
|
|
|
|
cell = QtWidgets.QTableWidgetItem()
|
|
|
|
|
self.setItem(row, col, cell)
|
|
|
|
|
self.cellDict[name] = cell
|
|
|
|
|
|
|
|
|
|
if color:
|
|
|
|
|
cell.setForeground(QtGui.QColor(color))
|
|
|
|
|
|
|
|
|
|
if alignment:
|
|
|
|
|
cell.setTextAlignment(alignment)
|
|
|
|
|
else:
|
|
|
|
|
cell.setTextAlignment(QtCore.Qt.AlignCenter)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def updateCell(self, name, value, decimals=None, data=None):
|
|
|
|
|
"""更新单元格"""
|
|
|
|
|
if decimals is not None:
|
|
|
|
|
text = '%.*f' %(decimals, value)
|
|
|
|
|
else:
|
|
|
|
|
text = '%s' %value
|
|
|
|
|
|
|
|
|
|
cell = self.cellDict[name]
|
|
|
|
|
cell.setText(text)
|
|
|
|
|
|
|
|
|
|
if data:
|
|
|
|
|
cell.price = data
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def updateTick(self, tick):
|
|
|
|
|
"""更新Tick"""
|
|
|
|
|
valueDecimals = 2
|
|
|
|
|
|
|
|
|
|
# bid
|
|
|
|
|
self.updateCell('bidPrice1', tick.bidPrice1, data=tick.bidPrice1)
|
|
|
|
|
self.updateCell('bidPrice2', tick.bidPrice2, data=tick.bidPrice2)
|
|
|
|
|
self.updateCell('bidPrice3', tick.bidPrice3, data=tick.bidPrice3)
|
|
|
|
|
self.updateCell('bidPrice4', tick.bidPrice4, data=tick.bidPrice4)
|
|
|
|
|
self.updateCell('bidPrice5', tick.bidPrice5, data=tick.bidPrice5)
|
|
|
|
|
|
|
|
|
|
self.updateCell('bidVolume1', tick.bidVolume1, data=tick.bidPrice1)
|
|
|
|
|
self.updateCell('bidVolume2', tick.bidVolume2, data=tick.bidPrice2)
|
|
|
|
|
self.updateCell('bidVolume3', tick.bidVolume3, data=tick.bidPrice3)
|
|
|
|
|
self.updateCell('bidVolume4', tick.bidVolume4, data=tick.bidPrice4)
|
|
|
|
|
self.updateCell('bidVolume5', tick.bidVolume5, data=tick.bidPrice5)
|
|
|
|
|
|
|
|
|
|
self.updateCell('bidValue1', tick.bidPrice1*tick.bidVolume1*self.contractSize, valueDecimals, data=tick.bidPrice1)
|
|
|
|
|
self.updateCell('bidValue2', tick.bidPrice2*tick.bidVolume2*self.contractSize, valueDecimals, data=tick.bidPrice2)
|
|
|
|
|
self.updateCell('bidValue3', tick.bidPrice3*tick.bidVolume3*self.contractSize, valueDecimals, data=tick.bidPrice3)
|
|
|
|
|
self.updateCell('bidValue4', tick.bidPrice4*tick.bidVolume4*self.contractSize, valueDecimals, data=tick.bidPrice4)
|
|
|
|
|
self.updateCell('bidValue5', tick.bidPrice5*tick.bidVolume5*self.contractSize, valueDecimals, data=tick.bidPrice5)
|
|
|
|
|
|
|
|
|
|
# ask
|
|
|
|
|
self.updateCell('askPrice1', tick.askPrice1, data=tick.askPrice1)
|
|
|
|
|
self.updateCell('askPrice2', tick.askPrice2, data=tick.askPrice2)
|
|
|
|
|
self.updateCell('askPrice3', tick.askPrice3, data=tick.askPrice3)
|
|
|
|
|
self.updateCell('askPrice4', tick.askPrice4, data=tick.askPrice4)
|
|
|
|
|
self.updateCell('askPrice5', tick.askPrice5, data=tick.askPrice5)
|
|
|
|
|
|
|
|
|
|
self.updateCell('askVolume1', tick.askVolume1, data=tick.askPrice1)
|
|
|
|
|
self.updateCell('askVolume2', tick.askVolume2, data=tick.askPrice2)
|
|
|
|
|
self.updateCell('askVolume3', tick.askVolume3, data=tick.askPrice3)
|
|
|
|
|
self.updateCell('askVolume4', tick.askVolume4, data=tick.askPrice4)
|
|
|
|
|
self.updateCell('askVolume5', tick.askVolume5, data=tick.askPrice5)
|
|
|
|
|
|
|
|
|
|
self.updateCell('askValue1', tick.askPrice1*tick.askVolume1*self.contractSize, valueDecimals, data=tick.askPrice1)
|
|
|
|
|
self.updateCell('askValue2', tick.askPrice2*tick.askVolume2*self.contractSize, valueDecimals, data=tick.askPrice2)
|
|
|
|
|
self.updateCell('askValue3', tick.askPrice3*tick.askVolume3*self.contractSize, valueDecimals, data=tick.askPrice3)
|
|
|
|
|
self.updateCell('askValue4', tick.askPrice4*tick.askVolume4*self.contractSize, valueDecimals, data=tick.askPrice4)
|
|
|
|
|
self.updateCell('askValue5', tick.askPrice5*tick.askVolume5*self.contractSize, valueDecimals, data=tick.askPrice5)
|
|
|
|
|
|
|
|
|
|
# today
|
|
|
|
|
self.updateCell('lastPrice', tick.lastPrice)
|
|
|
|
|
|
|
|
|
|
if tick.openPrice:
|
|
|
|
|
todayChange = tick.lastPrice/tick.openPrice - 1
|
|
|
|
|
else:
|
|
|
|
|
todayChange = 0
|
|
|
|
|
|
|
|
|
|
self.updateCell('todayChange', ('%.2f%%' %(todayChange*100)))
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def updateVtSymbol(self, vtSymbol):
|
|
|
|
|
"""更换显示行情标的"""
|
|
|
|
|
for cell in self.cellDict.values():
|
|
|
|
|
cell.setText('')
|
|
|
|
|
|
|
|
|
|
contract = self.mainEngine.getContract(vtSymbol)
|
|
|
|
|
if contract:
|
|
|
|
|
self.contractSize = contract.size
|
|
|
|
|
else:
|
|
|
|
|
self.contractSize = 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class TradingWidget(QtWidgets.QFrame):
|
|
|
|
|
"""简单交易组件"""
|
|
|
|
|
signal = QtCore.Signal(type(Event()))
|
|
|
|
|
|
|
|
|
|
directionList = [DIRECTION_LONG,
|
|
|
|
|
DIRECTION_SHORT]
|
|
|
|
|
|
|
|
|
|
priceTypeList = [PRICETYPE_LIMITPRICE,
|
|
|
|
|
PRICETYPE_MARKETPRICE]
|
|
|
|
|
|
2018-11-06 15:07:43 +00:00
|
|
|
|
offsetList = [OFFSET_OPEN,
|
|
|
|
|
OFFSET_CLOSE]
|
|
|
|
|
|
2018-07-26 06:13:42 +00:00
|
|
|
|
gatewayList = ['']
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, eventEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(TradingWidget, self).__init__(parent)
|
|
|
|
|
self.mainEngine = mainEngine
|
|
|
|
|
self.eventEngine = eventEngine
|
|
|
|
|
|
|
|
|
|
self.vtSymbol = ''
|
|
|
|
|
|
|
|
|
|
# 添加交易接口
|
|
|
|
|
l = mainEngine.getAllGatewayDetails()
|
|
|
|
|
gatewayNameList = [d['gatewayName'] for d in l]
|
|
|
|
|
self.gatewayList.extend(gatewayNameList)
|
|
|
|
|
|
|
|
|
|
self.initUi()
|
|
|
|
|
self.registerEvent()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def initUi(self):
|
|
|
|
|
"""初始化界面"""
|
|
|
|
|
self.setWindowTitle(vtText.TRADING)
|
|
|
|
|
self.setFixedHeight(400)
|
|
|
|
|
self.setFixedWidth(600)
|
|
|
|
|
self.setFrameShape(self.Box) # 设置边框
|
|
|
|
|
self.setLineWidth(1)
|
|
|
|
|
|
|
|
|
|
# 左边部分
|
|
|
|
|
labelPriceType = QtWidgets.QLabel(vtText.PRICE_TYPE)
|
|
|
|
|
labelSymbol = QtWidgets.QLabel(u'VT代码')
|
|
|
|
|
labelPrice = QtWidgets.QLabel(vtText.PRICE)
|
|
|
|
|
labelVolume = QtWidgets.QLabel(u'数量')
|
2018-11-06 15:07:43 +00:00
|
|
|
|
labelOffset = QtWidgets.QLabel(u'开平')
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
self.comboPriceType = QtWidgets.QComboBox()
|
|
|
|
|
self.comboPriceType.addItems(self.priceTypeList)
|
|
|
|
|
|
2018-11-06 15:07:43 +00:00
|
|
|
|
self.comboOffset = QtWidgets.QComboBox()
|
|
|
|
|
self.comboOffset.addItems(self.offsetList)
|
|
|
|
|
|
2018-07-26 06:13:42 +00:00
|
|
|
|
self.lineSymbol = QtWidgets.QLineEdit()
|
|
|
|
|
|
|
|
|
|
validator = QtGui.QDoubleValidator()
|
|
|
|
|
validator.setBottom(0)
|
|
|
|
|
|
|
|
|
|
self.linePrice = QtWidgets.QLineEdit()
|
|
|
|
|
self.linePrice.setValidator(validator)
|
|
|
|
|
|
|
|
|
|
self.lineVolume = QtWidgets.QLineEdit()
|
|
|
|
|
self.lineVolume.setValidator(validator)
|
|
|
|
|
|
|
|
|
|
gridLeft = QtWidgets.QGridLayout()
|
|
|
|
|
gridLeft.addWidget(labelPriceType, 0, 0)
|
2018-11-06 15:07:43 +00:00
|
|
|
|
gridLeft.addWidget(labelOffset, 1, 0)
|
|
|
|
|
gridLeft.addWidget(labelSymbol, 2, 0)
|
|
|
|
|
gridLeft.addWidget(labelPrice, 3, 0)
|
|
|
|
|
gridLeft.addWidget(labelVolume, 4, 0)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
gridLeft.addWidget(self.comboPriceType, 0, 1)
|
2018-11-06 15:07:43 +00:00
|
|
|
|
gridLeft.addWidget(self.comboOffset, 1, 1)
|
|
|
|
|
gridLeft.addWidget(self.lineSymbol, 2, 1)
|
|
|
|
|
gridLeft.addWidget(self.linePrice, 3, 1)
|
|
|
|
|
gridLeft.addWidget(self.lineVolume, 4, 1)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
# 右边部分
|
|
|
|
|
self.depthMonitor = DepthMonitor(self.mainEngine, self.eventEngine)
|
|
|
|
|
|
|
|
|
|
# 发单按钮
|
|
|
|
|
buttonBuy = QtWidgets.QPushButton(u'买入')
|
|
|
|
|
buttonSell = QtWidgets.QPushButton(u'卖出')
|
|
|
|
|
buttonCancelAll = QtWidgets.QPushButton(vtText.CANCEL_ALL)
|
|
|
|
|
|
|
|
|
|
size = buttonBuy.sizeHint()
|
|
|
|
|
buttonBuy.setMinimumHeight(size.height()*2)
|
|
|
|
|
buttonSell.setMinimumHeight(size.height()*2)
|
|
|
|
|
buttonCancelAll.setMinimumHeight(size.height()*2)
|
|
|
|
|
|
|
|
|
|
buttonBuy.clicked.connect(self.sendBuyOrder)
|
|
|
|
|
buttonSell.clicked.connect(self.sendSellOrder)
|
|
|
|
|
buttonCancelAll.clicked.connect(self.cancelAll)
|
|
|
|
|
|
|
|
|
|
buttonBuy.setStyleSheet('color:white;background-color:red')
|
|
|
|
|
buttonSell.setStyleSheet('color:white;background-color:green')
|
|
|
|
|
buttonCancelAll.setStyleSheet('color:black;background-color:yellow')
|
|
|
|
|
|
|
|
|
|
gridButton = QtWidgets.QGridLayout()
|
|
|
|
|
gridButton.addWidget(buttonBuy, 0, 0)
|
|
|
|
|
gridButton.addWidget(buttonSell, 0, 1)
|
|
|
|
|
gridButton.addWidget(buttonCancelAll, 1, 0, 1, 2)
|
|
|
|
|
|
|
|
|
|
# 整合布局
|
|
|
|
|
vbox = QtWidgets.QVBoxLayout()
|
|
|
|
|
vbox.addLayout(gridLeft)
|
|
|
|
|
vbox.addLayout(gridButton)
|
|
|
|
|
|
|
|
|
|
hbox = QtWidgets.QHBoxLayout()
|
|
|
|
|
hbox.addLayout(vbox)
|
|
|
|
|
hbox.addWidget(self.depthMonitor)
|
|
|
|
|
|
|
|
|
|
self.setLayout(hbox)
|
|
|
|
|
|
|
|
|
|
# 关联更新
|
|
|
|
|
self.lineSymbol.returnPressed.connect(self.updateSymbol)
|
|
|
|
|
self.depthMonitor.itemDoubleClicked.connect(self.updatePrice)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def updateSymbol(self):
|
|
|
|
|
"""合约变化"""
|
|
|
|
|
self.vtSymbol = str(self.lineSymbol.text())
|
|
|
|
|
contract = self.mainEngine.getContract(self.vtSymbol)
|
|
|
|
|
|
|
|
|
|
if not contract:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 清空价格数量
|
|
|
|
|
self.linePrice.clear()
|
|
|
|
|
self.lineVolume.clear()
|
|
|
|
|
|
|
|
|
|
self.depthMonitor.updateVtSymbol(self.vtSymbol)
|
|
|
|
|
|
|
|
|
|
# 订阅合约
|
|
|
|
|
req = VtSubscribeReq()
|
|
|
|
|
req.symbol = contract.symbol
|
|
|
|
|
self.mainEngine.subscribe(req, contract.gatewayName)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def updateTick(self, event):
|
|
|
|
|
"""更新行情"""
|
|
|
|
|
tick = event.dict_['data']
|
|
|
|
|
if tick.vtSymbol != self.vtSymbol:
|
|
|
|
|
return
|
|
|
|
|
self.depthMonitor.updateTick(tick)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def registerEvent(self):
|
|
|
|
|
"""注册事件监听"""
|
|
|
|
|
self.signal.connect(self.updateTick)
|
|
|
|
|
self.eventEngine.register(EVENT_TICK, self.signal.emit)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def updatePrice(self, cell):
|
|
|
|
|
""""""
|
|
|
|
|
try:
|
|
|
|
|
price = cell.price
|
|
|
|
|
except AttributeError:
|
|
|
|
|
return
|
|
|
|
|
self.linePrice.setText(str(price))
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def sendOrder(self, direction):
|
|
|
|
|
"""发单"""
|
|
|
|
|
vtSymbol = str(self.lineSymbol.text())
|
|
|
|
|
contract = self.mainEngine.getContract(vtSymbol)
|
|
|
|
|
if not contract:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 获取价格
|
|
|
|
|
priceText = self.linePrice.text()
|
|
|
|
|
if not priceText:
|
|
|
|
|
return
|
|
|
|
|
price = float(priceText)
|
|
|
|
|
|
|
|
|
|
# 获取数量
|
|
|
|
|
volumeText = self.lineVolume.text()
|
|
|
|
|
if not volumeText:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if '.' in volumeText:
|
|
|
|
|
volume = float(volumeText)
|
|
|
|
|
else:
|
|
|
|
|
volume = int(volumeText)
|
|
|
|
|
|
|
|
|
|
# 委托
|
|
|
|
|
req = VtOrderReq()
|
|
|
|
|
req.symbol = contract.symbol
|
|
|
|
|
req.price = price
|
|
|
|
|
req.volume = volume
|
|
|
|
|
req.direction = direction
|
|
|
|
|
req.priceType = text_type(self.comboPriceType.currentText())
|
2018-11-06 15:07:43 +00:00
|
|
|
|
req.offset = text_type(self.comboOffset.currentText())
|
2018-07-26 06:13:42 +00:00
|
|
|
|
|
|
|
|
|
self.mainEngine.sendOrder(req, contract.gatewayName)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def sendBuyOrder(self):
|
|
|
|
|
""""""
|
|
|
|
|
self.sendOrder(DIRECTION_LONG)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def sendSellOrder(self):
|
|
|
|
|
""""""
|
|
|
|
|
self.sendOrder(DIRECTION_SHORT)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def cancelAll(self):
|
|
|
|
|
"""一键撤销所有委托"""
|
|
|
|
|
l = self.mainEngine.getAllWorkingOrders()
|
|
|
|
|
for order in l:
|
|
|
|
|
req = VtCancelOrderReq()
|
|
|
|
|
req.symbol = order.symbol
|
|
|
|
|
req.exchange = order.exchange
|
|
|
|
|
req.frontID = order.frontID
|
|
|
|
|
req.sessionID = order.sessionID
|
|
|
|
|
req.orderID = order.orderID
|
|
|
|
|
self.mainEngine.cancelOrder(req, order.gatewayName)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class ContractMonitor(BasicMonitor):
|
|
|
|
|
"""合约查询"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(ContractMonitor, self).__init__(parent=parent)
|
|
|
|
|
|
|
|
|
|
self.mainEngine = mainEngine
|
|
|
|
|
|
|
|
|
|
d = OrderedDict()
|
|
|
|
|
d['symbol'] = {'chinese':vtText.CONTRACT_SYMBOL, 'cellType':BasicCell}
|
|
|
|
|
d['exchange'] = {'chinese':vtText.EXCHANGE, 'cellType':BasicCell}
|
|
|
|
|
d['vtSymbol'] = {'chinese':vtText.VT_SYMBOL, 'cellType':BasicCell}
|
|
|
|
|
d['productClass'] = {'chinese':vtText.PRODUCT_CLASS, 'cellType':BasicCell}
|
|
|
|
|
d['size'] = {'chinese':vtText.CONTRACT_SIZE, 'cellType':BasicCell}
|
|
|
|
|
d['priceTick'] = {'chinese':vtText.PRICE_TICK, 'cellType':BasicCell}
|
|
|
|
|
self.setHeaderDict(d)
|
|
|
|
|
|
|
|
|
|
# 过滤显示用的字符串
|
|
|
|
|
self.filterContent = EMPTY_STRING
|
|
|
|
|
|
|
|
|
|
self.initUi()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def initUi(self):
|
|
|
|
|
"""初始化界面"""
|
|
|
|
|
self.setMinimumSize(800, 800)
|
|
|
|
|
self.setFont(BASIC_FONT)
|
2018-07-26 09:40:29 +00:00
|
|
|
|
self.setResizeMode(QtWidgets.QHeaderView.Stretch)
|
2018-07-26 06:13:42 +00:00
|
|
|
|
self.initTable()
|
|
|
|
|
self.addMenuAction()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def showAllContracts(self):
|
|
|
|
|
"""显示所有合约数据"""
|
|
|
|
|
l = self.mainEngine.getAllContracts()
|
|
|
|
|
d = {'.'.join([contract.exchange, contract.symbol]):contract for contract in l}
|
|
|
|
|
l2 = list(d.keys())
|
|
|
|
|
l2.sort(reverse=True)
|
|
|
|
|
|
|
|
|
|
self.setRowCount(len(l2))
|
|
|
|
|
row = 0
|
|
|
|
|
|
|
|
|
|
for key in l2:
|
|
|
|
|
# 如果设置了过滤信息且合约代码中不含过滤信息,则不显示
|
|
|
|
|
if self.filterContent and self.filterContent not in key:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
contract = d[key]
|
|
|
|
|
|
|
|
|
|
for n, header in enumerate(self.headerList):
|
|
|
|
|
content = safeUnicode(contract.__getattribute__(header))
|
|
|
|
|
cellType = self.headerDict[header]['cellType']
|
|
|
|
|
cell = cellType(content)
|
|
|
|
|
|
|
|
|
|
if self.font:
|
|
|
|
|
cell.setFont(self.font) # 如果设置了特殊字体,则进行单元格设置
|
|
|
|
|
|
|
|
|
|
self.setItem(row, n, cell)
|
|
|
|
|
|
|
|
|
|
row = row + 1
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def refresh(self):
|
|
|
|
|
"""刷新"""
|
|
|
|
|
self.menu.close() # 关闭菜单
|
|
|
|
|
self.clearContents()
|
|
|
|
|
self.setRowCount(0)
|
|
|
|
|
self.showAllContracts()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def addMenuAction(self):
|
|
|
|
|
"""增加右键菜单内容"""
|
|
|
|
|
refreshAction = QtWidgets.QAction(vtText.REFRESH, self)
|
|
|
|
|
refreshAction.triggered.connect(self.refresh)
|
|
|
|
|
|
|
|
|
|
self.menu.addAction(refreshAction)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def show(self):
|
|
|
|
|
"""显示"""
|
|
|
|
|
super(ContractMonitor, self).show()
|
|
|
|
|
self.refresh()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def setFilterContent(self, content):
|
|
|
|
|
"""设置过滤字符串"""
|
|
|
|
|
self.filterContent = content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class ContractManager(QtWidgets.QWidget):
|
|
|
|
|
"""合约管理组件"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(ContractManager, self).__init__(parent=parent)
|
|
|
|
|
|
|
|
|
|
self.mainEngine = mainEngine
|
|
|
|
|
|
|
|
|
|
self.initUi()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def initUi(self):
|
|
|
|
|
"""初始化界面"""
|
|
|
|
|
self.setWindowTitle(vtText.CONTRACT_SEARCH)
|
|
|
|
|
|
|
|
|
|
self.lineFilter = QtWidgets.QLineEdit()
|
|
|
|
|
self.buttonFilter = QtWidgets.QPushButton(vtText.SEARCH)
|
|
|
|
|
self.buttonFilter.clicked.connect(self.filterContract)
|
|
|
|
|
self.monitor = ContractMonitor(self.mainEngine)
|
|
|
|
|
self.monitor.refresh()
|
|
|
|
|
|
|
|
|
|
hbox = QtWidgets.QHBoxLayout()
|
|
|
|
|
hbox.addWidget(self.lineFilter)
|
|
|
|
|
hbox.addWidget(self.buttonFilter)
|
|
|
|
|
hbox.addStretch()
|
|
|
|
|
|
|
|
|
|
vbox = QtWidgets.QVBoxLayout()
|
|
|
|
|
vbox.addLayout(hbox)
|
|
|
|
|
vbox.addWidget(self.monitor)
|
|
|
|
|
|
|
|
|
|
self.setLayout(vbox)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def filterContract(self):
|
|
|
|
|
"""显示过滤后的合约"""
|
|
|
|
|
content = str(self.lineFilter.text())
|
|
|
|
|
self.monitor.setFilterContent(content)
|
|
|
|
|
self.monitor.refresh()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class WorkingOrderMonitor(OrderMonitor):
|
|
|
|
|
"""活动委托监控"""
|
|
|
|
|
STATUS_COMPLETED = [STATUS_ALLTRADED, STATUS_CANCELLED, STATUS_REJECTED]
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, eventEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(WorkingOrderMonitor, self).__init__(mainEngine, eventEngine, parent)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def updateData(self, data):
|
|
|
|
|
"""更新数据"""
|
|
|
|
|
super(WorkingOrderMonitor, self).updateData(data)
|
|
|
|
|
|
|
|
|
|
# 如果该委托已完成,则隐藏该行
|
|
|
|
|
if data.status in self.STATUS_COMPLETED:
|
|
|
|
|
vtOrderID = data.vtOrderID
|
|
|
|
|
cellDict = self.dataDict[vtOrderID]
|
|
|
|
|
cell = cellDict['status']
|
|
|
|
|
row = self.row(cell)
|
|
|
|
|
self.hideRow(row)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########################################################################
|
|
|
|
|
class SettingEditor(QtWidgets.QWidget):
|
|
|
|
|
"""配置编辑器"""
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def __init__(self, mainEngine, parent=None):
|
|
|
|
|
"""Constructor"""
|
|
|
|
|
super(SettingEditor, self).__init__(parent)
|
|
|
|
|
|
|
|
|
|
self.mainEngine = mainEngine
|
|
|
|
|
self.currentFileName = ''
|
|
|
|
|
|
|
|
|
|
self.initUi()
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def initUi(self):
|
|
|
|
|
"""初始化界面"""
|
|
|
|
|
self.setWindowTitle(vtText.EDIT_SETTING)
|
|
|
|
|
|
|
|
|
|
self.comboFileName = QtWidgets.QComboBox()
|
|
|
|
|
self.comboFileName.addItems(jsonPathDict.keys())
|
|
|
|
|
|
|
|
|
|
buttonLoad = QtWidgets.QPushButton(vtText.LOAD)
|
|
|
|
|
buttonSave = QtWidgets.QPushButton(vtText.SAVE)
|
|
|
|
|
buttonLoad.clicked.connect(self.loadSetting)
|
|
|
|
|
buttonSave.clicked.connect(self.saveSetting)
|
|
|
|
|
|
|
|
|
|
self.editSetting = QtWidgets.QTextEdit()
|
|
|
|
|
self.labelPath = QtWidgets.QLabel()
|
|
|
|
|
|
|
|
|
|
hbox = QtWidgets.QHBoxLayout()
|
|
|
|
|
hbox.addWidget(self.comboFileName)
|
|
|
|
|
hbox.addWidget(buttonLoad)
|
|
|
|
|
hbox.addWidget(buttonSave)
|
|
|
|
|
hbox.addStretch()
|
|
|
|
|
|
|
|
|
|
vbox = QtWidgets.QVBoxLayout()
|
|
|
|
|
vbox.addLayout(hbox)
|
|
|
|
|
vbox.addWidget(self.editSetting)
|
|
|
|
|
vbox.addWidget(self.labelPath)
|
|
|
|
|
|
|
|
|
|
self.setLayout(vbox)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def loadSetting(self):
|
|
|
|
|
"""加载配置"""
|
|
|
|
|
self.currentFileName = str(self.comboFileName.currentText())
|
|
|
|
|
filePath = jsonPathDict[self.currentFileName]
|
|
|
|
|
self.labelPath.setText(filePath)
|
|
|
|
|
|
|
|
|
|
with open(filePath) as f:
|
|
|
|
|
self.editSetting.clear()
|
|
|
|
|
|
|
|
|
|
for line in f:
|
|
|
|
|
line = line.replace('\n', '') # 移除换行符号
|
|
|
|
|
line = line.decode('UTF-8')
|
|
|
|
|
self.editSetting.append(line)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def saveSetting(self):
|
|
|
|
|
"""保存配置"""
|
|
|
|
|
if not self.currentFileName:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
filePath = jsonPathDict[self.currentFileName]
|
|
|
|
|
|
|
|
|
|
with open(filePath, 'w') as f:
|
|
|
|
|
content = self.editSetting.toPlainText()
|
|
|
|
|
content = content.encode('UTF-8')
|
|
|
|
|
f.write(content)
|
|
|
|
|
|
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
|
def show(self):
|
|
|
|
|
"""显示"""
|
|
|
|
|
# 更新配置文件下拉框
|
|
|
|
|
self.comboFileName.clear()
|
|
|
|
|
self.comboFileName.addItems(jsonPathDict.keys())
|
|
|
|
|
|
|
|
|
|
# 显示界面
|
|
|
|
|
super(SettingEditor, self).show()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|