diff --git a/Static/Main.qss b/Static/Main.qss index e534ace..dba20b8 100644 --- a/Static/Main.qss +++ b/Static/Main.qss @@ -1,9 +1,109 @@ + QMdiSubWindow { font-size: 18px; font-weight: bold; + } +QPushButton#deviceAddButton, QPushButton#addareabutton { + + color: #328ffc; + font-size: 17px; } + + + + QTabBar::close-button { + + image: url(Static/close.png); + + subcontrol-origin: padding; + + margin-top: 2px; + + margin-left: 4px; + } + + QTabBar::close-button:hover { + + background-color: #cccccc; + } + + +QTabBar::tab:hover { + + background-color: #809ac2; + +} + + +QTabBar::tab{ + + background: #cbdeec; + + border: 2px; + + min-width: 200px; + + min-height: 30px; + + font: 17px; + + + + + + font-family: ".SFNSDisplay-Regular"; + + +} +QTabBar#areaTabBar::tab{ + + min-width: 100px; +} + + + +QTabBar::tab:selected { + + background-color: #f0f0f0; + + font: bold; + + border-radius: 3px; + + margin-bottom: -4px + + +} + +QTabWidget#deviceTabWidget::pane { + + border: 1px solid #a8a8a8; + + border-radius: 3px; + + margin: 2px; + + } + +QDockWidget{ + + font: 18px; + + font: bold; + + font-family: ".SFNSDisplay-Regular"; +} + +QDockWidget::title{ + + background-color: #cbdeec; + color: white; + + text-align: center; + +} \ No newline at end of file diff --git a/Static/add.png b/Static/add.png new file mode 100644 index 0000000..a9b3ca7 Binary files /dev/null and b/Static/add.png differ diff --git a/Static/close.png b/Static/close.png new file mode 100644 index 0000000..4374906 Binary files /dev/null and b/Static/close.png differ diff --git a/UI/AreaMansge.py b/UI/AreaMansge.py new file mode 100644 index 0000000..7c38695 --- /dev/null +++ b/UI/AreaMansge.py @@ -0,0 +1,29 @@ + + + +class AreaWidgetManage: + def __init__(self): + + # self.label = [] #主站AI, DI与从站AO,DO,没有确定按钮 + # self.lineEdit = [] #存放主站AO,DO与从站AI,DI,有确定按钮 + + self.areaAllWidgets = [] + + def addWidgets(self,areaWidgets): + + #主站AI, DI没有确定按钮 从站AI,DI有确定按钮 + #主站AO,DO有确定按钮 , 从站AO,DO没有确定按钮 + self.areaAllWidgets.append(areaWidgets) + + + + def getAllWidgets(self): + l = [] + for areaWidgets in self.areaAllWidgets: + for areawidget in areaWidgets: + l.append(areawidget) + return l + + def delareaWidget(self, index): + self.areaAllWidgets.pop(index) + \ No newline at end of file diff --git a/UI/AreaTabWidget.py b/UI/AreaTabWidget.py index 19fde02..6a2f5f0 100644 --- a/UI/AreaTabWidget.py +++ b/UI/AreaTabWidget.py @@ -1,226 +1,430 @@ +import re +from socket import AI_ADDRCONFIG import sys import json -from PyQt5.QtWidgets import QApplication, QMainWindow, QTabWidget, QWidget, QVBoxLayout, QLabel, QPushButton, \ - QHBoxLayout, QComboBox, QLineEdit, QSpacerItem, QSizePolicy, QGridLayout, QMessageBox -from PyQt5 import QtCore - -from model.ProjectModel.DeviceManage import DevicesManange, Device - +from tkinter import N +from functools import partial +from PyQt5.QtWidgets import QApplication, QMainWindow, QTabWidget, QWidget, QVBoxLayout, QLabel, QPushButton, QLayout, \ + QHBoxLayout, QComboBox, QLineEdit, QSpacerItem, QSizePolicy, QGridLayout, QMessageBox, QSplitter, QFrame +from PyQt5.QtCore import QLine +from PyQt5.QtGui import QIcon +from numpy import add, byte, delete +from model.ProjectModel.AreaManage import Area +from model.ProjectModel.DeviceWidgetManage import DeviceWidgetManage +from UI.AreaMansge import AreaWidgetManage +from model.ProjectModel.DeviceManage import Device, DevicesManange + +class forceButton(QPushButton): + def __init__(self, valueEdit): + super().__init__() + self.valueEdit = valueEdit + self.setText('强制') -class AreaTabWidget(QMainWindow): - def __init__(self, mainwindow): +class ButtonLayout(QWidget): + def __init__(self): super().__init__() + # self.index = index + self.addLayout() + l = [] + + def addLayout(self): + self.setLayout(self.areaLayout()) + + + def areaLayout(self): + areaLayout = QVBoxLayout() + for i in range(8): + hLayout = QHBoxLayout() + hLayout.addLayout(self.dateLayout()) + hLayout.addWidget(QSplitter()) + hLayout.addLayout(self.dateLayout()) + areaLayout.addLayout(hLayout) + return areaLayout + + def dateLayout(self, force = True): + forceLayout = QHBoxLayout() + areaMessLabel = QLabel('DO' + str(1) + ": " + '字节长度: ' + '22' + ' 当前值: ' ) + areaValueLabel = QLabel('0') + forceLayout.addWidget(areaMessLabel) + forceLayout.addWidget(areaValueLabel) + + + if force: + areaLineEdit = QLineEdit('0') + forceBtn = forceButton(areaLineEdit) + forceBtn.clicked.connect(self.forceValues) + forceLayout.addWidget(areaLineEdit) + forceLayout.addWidget(forceBtn) + + return forceLayout + + def forceValues(self): + sender = self.sender() + print(sender.valueEdit.text()) + + + + + +class AreaTabWidget(QTabWidget): + def __init__(self, deviceWidget): + super().__init__() + self.deviceWidget = deviceWidget + self.initUI() - self.mainwindow = mainwindow + + def initUI(self): + self.areaWidgetmanage = AreaWidgetManage() + self.deviceName = self.deviceWidget.deviceName # 创建一个 QTabWidget - self.widgetList = [] - self.areaTabWidget = QTabWidget(self) - self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) - self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) - # 设置主窗口的中心部分为 QTabWidget - self.setCentralWidget(self.areaTabWidget) - - def initAreaTab(self, dataType, order, channelBytes): - widgetList = self.addAreaTab() - widgetList[0].setCurrentIndex(dataType) - widgetList[1].setCurrentIndex(order) - widgetList[2].setText(channelBytes) - - self.addAreaWidget(widgetList, loacl = False, init = True) - - - def addAreaTab(self): - areaTabWidget = QWidget() - - tabIndex = self.areaTabWidget.count() - # 将标签页添加到 QTabWidget 中 - self.areaTabWidget.addTab(areaTabWidget, str(tabIndex)) - self.areaTabWidget.setCurrentIndex(int(tabIndex)) - self.setCentralWidget(self.areaTabWidget) - widgetList = [] - mainLayout = QVBoxLayout() - topLayout = QHBoxLayout() - areaLayout = QGridLayout() - - dataTypeCombox = QComboBox() - dataTypeCombox.addItems(['AI', 'AO', 'DI', 'DO']) - dataTypeCombox.setObjectName('dataTypeCombox') - - orderCombox = QComboBox() - orderCombox.addItems(['不转换', '字节转换', '字转换', '字内转换']) - byteLineEdit = QLineEdit() - byteLineEdit.setPlaceholderText('字节长度') - byteLineEdit.setObjectName('byteLineEdit') + self.setTabPosition(QTabWidget.South) + self.tabBar().setObjectName('areaTabBar') + self.addAreaButton = QPushButton("添加区域") + self.addAreaButton.setObjectName('addareabutton') + self.addAreaButton.setIcon(QIcon('Static/add.png')) + self.addAreaButton.setFlat(True) + self.setCornerWidget(self.addAreaButton) + self.addAreaButton.clicked.connect(self.addAreaTab) + + self.initWidget() #初始化界面 - okBtn = QPushButton('确定') - delAreaBtn = QPushButton('删除') - - topLayout.addWidget(dataTypeCombox, 1) - topLayout.addWidget(orderCombox, 1) - # topLayout.addWidget(byteLabel) - topLayout.addWidget(byteLineEdit, 2) - topLayout.addWidget(okBtn, 1) - topLayout.addItem(self.horizontalSpacer) - topLayout.addItem(self.horizontalSpacer) - topLayout.addItem(self.horizontalSpacer) - topLayout.addItem(self.horizontalSpacer) - topLayout.addWidget(delAreaBtn, 1) - - widget = QWidget() - areaLayout.addWidget(widget) - mainLayout.addLayout(topLayout, 1) - mainLayout.addLayout(areaLayout, 9) - - okBtn.clicked.connect(lambda checked, btn=okBtn: self.addAreaWidget(widgetList)) + # self.tabCloseRequested.connect(self.closeTab) + + # self.setTabPosition(QTabWidget.West) + + # self.setTabsClosable(True) + + # 设置主窗口的中心部分为 QTabWidget - delAreaBtn.clicked.connect(self.removeAreaTab) + + + def initWidget(self): + alldevices = DevicesManange.getAllDevice() + if alldevices: + for devices in alldevices: + if self.deviceName in devices: + areas = json.loads(devices[3]) + if areas: + self.removeTab(0) + for area in areas: + dataType, order = self.tran(area["type"], area["order"]) + channelBytes = area["bytes"] + settingValue = [dataType, order, channelBytes] + self.addAreaTab(settingValue=settingValue) + else: + widget = QWidget() + layout = QHBoxLayout() + addButton = QPushButton('添加区域') + addButton.clicked.connect(lambda: self.addAreaTab(True)) + layout.addWidget(QSplitter()) + layout.addWidget(addButton) + layout.addWidget(QSplitter()) + widget.setLayout(layout) + self.addTab(widget,'') + self.tabBar().setHidden(True) + + + + + def addAreaTab(self, init = False, settingValue = None): + if settingValue is None: + if init: + self.removeTab(0) + tabIndex = self.count() + areaWidget = AreaWidget(self, areaWidgetManage = self.areaWidgetmanage) + self.addTab(areaWidget, '通道' + str(tabIndex + 1)) + self.setCurrentIndex(tabIndex) + self.tabBar().setHidden(False) + else: + tabIndex = self.count() + areaWidget = AreaWidget(self, settingValue, areaWidgetManage = self.areaWidgetmanage) + self.addTab(areaWidget, '通道' + str(tabIndex + 1)) + self.tabBar().setHidden(False) + + + def tran(self, dataType, order): + if dataType == 'AI': + dataType = 0 + if dataType == 'AO': + dataType = 1 + if dataType == 'DI': + dataType = 2 + if dataType == 'DO': + dataType = 3 + + if order == 'ABCD': + order = 0 + if order == 'DCBA': + order = 1 + if order == 'CDAB': + order = 2 + if order == 'BADC': + order = 3 + + return dataType, order + +class AreaWidget(QWidget): + def __init__(self, areaTabWidget, settingValue = None, areaWidgetManage = None): + super().__init__() + self.areaTabWidget = areaTabWidget + self.settingValue = settingValue + self.areaWidgetManage = areaWidgetManage + self.initUI() - widgetList.extend([dataTypeCombox, orderCombox, byteLineEdit, areaLayout]) - areaTabWidget.setLayout(mainLayout) - return widgetList + def initUI(self): + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.mainLayout = QHBoxLayout() + self.leftLayout = QGridLayout() + self.rightLayout = QGridLayout() + + self.dataTypeLabel = QLabel('数据类型:') + # self.dataTypeLabel.setFixedSize(90, 27) + self.dataTypeCombox = QComboBox() + self.dataTypeCombox.addItems(['AI', 'AO', 'DI', 'DO']) + self.dataTypeCombox.setObjectName('dataTypeCombox') + # self.dataTypeCombox.setFixedSize(90, 27) + + self.dataOrderLabel = QLabel('数据格式:') + # self.dataOrderLabel.setFixedSize(90, 27) + self.orderCombox = QComboBox() + self.orderCombox.addItems(['不转换', '字节转换', '字转换', '字内转换']) + # self.orderCombox.setFixedSize(90, 27) + + self.byteLineLabel = QLabel('字节长度:') + # self.byteLineLabel.setFixedSize(90, 27) + self.byteLineEdit = QLineEdit() + self.byteLineEdit.setPlaceholderText('字节长度') + self.byteLineEdit.setObjectName('byteLineEdit') + # self.byteLineEdit.setFixedSize(90, 27) + + self.okBtn = QPushButton('确定') + # self.okBtn.setFixedSize(90, 27) + self.okBtn.clicked.connect(self.addAreaWidget) + self.obBtnValue = True + + self.delAreaBtn = QPushButton('删除') + # self.delAreaBtn.setFixedSize(90, 27) + self.delAreaBtn.clicked.connect(self.removeAreaTab) + + self.leftLayout.addWidget(self.dataTypeLabel, 0, 0, 1, 1) + self.leftLayout.addWidget(self.dataTypeCombox, 0, 1, 1, 1) + self.leftLayout.addWidget(self.dataOrderLabel,1, 0, 1, 1 ) + self.leftLayout.addWidget(self.orderCombox,1, 1, 1, 1 ) + self.leftLayout.addWidget(self.byteLineLabel,2, 0, 1, 1 ) + self.leftLayout.addWidget(self.byteLineEdit,2, 1, 1, 1 ) + self.leftLayout.addWidget(self.okBtn, 3, 0, 1, 1) + self.leftLayout.addWidget(self.delAreaBtn, 3, 1, 1, 1) + + + + + self.rightWidget = ButtonLayout() + # self.rightLayout.addWidget(self.rightWidget) + line = QFrame() + line.setFrameShape(QFrame.VLine) + line.setLineWidth(2) + + self.mainLayout.addLayout(self.leftLayout, 1) + self.mainLayout.addWidget(line) + self.mainLayout.addWidget(self.rightWidget, 9) + self.mainLayout.setSpacing(20) + + # self.deviceWidgetManage.addArea(mainLayout=mainLayout, leftLayoutWidget=leftLayoutWidgets) + + self.setLayout(self.mainLayout) + if self.settingValue is not None: + self.addAreaWidget() + + self.settingValue = None def removeAreaTab(self): # 获取 QTabWidget 并从中删除标签页 - deviceName = self.areaTabWidget.parent().parent().parent().parent().parent().windowTitle() - index = self.areaTabWidget.currentIndex() + deviceName = self.areaTabWidget.deviceName - alldevices = DevicesManange.getAllDevice() - for device in alldevices: - if deviceName in device: - areas = device[3] - if areas is not None: - areas = json.loads(areas) - area = areas[index] - type = area["type"] - # print(area, type,'ssss') + index = self.areaTabWidget.currentIndex() + tabCount = self.areaTabWidget.count() + + + + # alldevices = DevicesManange.getAllDevice() + # for device in alldevices: + # if deviceName in device: + # areas = device[3] + # if areas is not None: + # areas = json.loads(areas) + # if index >= len(areas): + # self.areaTabWidget.removeTab(index) + # return if index != -1: self.areaTabWidget.removeTab(index) - del self.widgetList[index] + Device.delAreas(deviceName, index) - self.mainwindow.devicesManange.getDevice(deviceName).delArea(index, type) - self.mainwindow.devicesManange.recalculateAddress() + + # self.mainwindow.devicesManange.getDevice(deviceName).delArea(index, type) + # self.mainwindow.devicesManange.recalculateAddress() + if tabCount == 1: + self.areaTabWidget.initWidget() - def addAreaWidget(self, widgetList, loacl = True, init = False): - self.mainwindow.readVarTimer.stop() - dataType = widgetList[0].currentText() - # print(widgetList) - order = self.dataTypeTranslate(widgetList[1].currentText()) - byteLineEdit = widgetList[2].text() - areaLayout = widgetList[3] - deviceName = self.areaTabWidget.parent().parent().parent().parent().parent().windowTitle() - widgetLists = [] - - while areaLayout.count(): - item = areaLayout.takeAt(0) - widget = item.widget() - if widget: - widget.setParent(None) - if len(byteLineEdit) == 0: - QMessageBox.warning(self, '警告', '请输入字节长度。') + def addAreaWidget(self): + curIndex = self.areaTabWidget.currentIndex() + #获取左侧配置布局的参数 + areaWidgets = [] + areaLayout = self.rightLayout + deviceName = self.areaTabWidget.deviceName + #开启软件时判断数据库是否有存在设备信息,并执行相应的操作 + if self.settingValue is None: + dataType = self.dataTypeCombox.currentText() + order = self.dataTypeTranslate(self.orderCombox.currentText()) + byteLineEdit = self.byteLineEdit.text() + + else: + dataTypeIndex = self.settingValue[0] + orderIndex = self.settingValue[1] + byteLineEditIndex = self.settingValue[2] + self.dataTypeCombox.setCurrentIndex(dataTypeIndex) + self.orderCombox.setCurrentIndex(orderIndex) + self.byteLineEdit.setText(byteLineEditIndex) + dataType = self.dataTypeCombox.currentText() + order = self.dataTypeTranslate(self.orderCombox.currentText()) + byteLineEdit = self.byteLineEdit.text() + + #判断字节长度的输入是否是数字 + pattern = re.compile(r'^\d+$') + match = pattern.match(byteLineEdit) + if not match: + QMessageBox.warning(self, '提示', '请输入数字。') return else: - widgetList[0].setEnabled(False) - if dataType in ['AI', 'AO']: - areaLabel = QLabel(dataType + str(1) + ": " + '字节长度: ' + byteLineEdit + ' 当前值: ' ) - areaLabel2 =QLabel('0') - - if '主站' in deviceName and dataType == 'AI' or ('从站' in deviceName and dataType == 'AO'): - areaLayout.addWidget(areaLabel, 0, 0) - areaLayout.addWidget(areaLabel2, 0, 1) - areaLayout.addItem(self.horizontalSpacer, 0, 4) - widgetLists.append([areaLabel2, areaLayout, areaLabel]) - - elif '主站' in deviceName and dataType == 'AO' or ('从站' in deviceName and dataType == 'AI'): - areaLineEdit = QLineEdit('0') - editbtn = QPushButton('强制') - areaLayout.addWidget(areaLabel, 0, 0) - areaLayout.addWidget(areaLabel2, 0, 1 ) - areaLayout.addWidget(areaLineEdit, 0, 2 ) - areaLayout.addWidget(editbtn, 0, 3) - areaLayout.addItem(self.horizontalSpacer, 0, 4) - editbtn.clicked.connect(lambda checked, btn=editbtn: self.wirteValue(btn)) - widgetLists.append([areaLabel2, areaLineEdit, editbtn, areaLayout, areaLabel]) - self.widgetList.append(widgetLists) - + #设置点击确定后无法编辑,点击编辑后才能编辑 + if self.obBtnValue: + self.okBtn.setText('编辑') + self.dataTypeCombox.setEnabled(False ) + self.orderCombox.setEnabled(False ) + self.byteLineEdit.setEnabled(False ) + self.obBtnValue = False + else: - channelNumber = int(byteLineEdit) * 8 - if '主站' in deviceName and dataType == 'DI' or ( - '从站' in deviceName and dataType == 'DO'): - for i in range(int(channelNumber)): - if i % 2 == 0: - areaLabel = QLabel(dataType + str(1) + ": " + '字节长度: ' + byteLineEdit + ' 当前值: ') - areaLabel2 = QLabel('0') - areaLayout.addWidget(areaLabel, i // 2, i % 2) - areaLayout.addWidget(areaLabel2, i // 2, i % 2 + 1) - widgetLists.append([areaLabel2, areaLayout, areaLabel]) - - else: - areaLabel = QLabel(dataType + str(1) + ": " + '字节长度: ' + byteLineEdit + ' 当前值: ') - areaLabel2 = QLabel('0') - areaLayout.addWidget(areaLabel, i // 2, i % 2 + 2) - areaLayout.addWidget(areaLabel2, i // 2, i % 2 + 3) - widgetLists.append([areaLabel2, areaLayout, areaLabel]) - self.widgetList.append(widgetLists) - if '主站' in deviceName and dataType == 'DO' or ( - '从站' in deviceName and dataType == 'DI'): - for i in range(int(channelNumber)): - if i % 2 == 0: - areaLabel = QLabel(dataType + str(1) + ": " + '字节长度: ' + byteLineEdit + ' 当前值: ') - areaLabel2 = QLabel('0') - areaLineEdit = QLineEdit('0') - editbtn = QPushButton('强制') - - areaLayout.addWidget(areaLabel, i // 2, i % 2) - areaLayout.addWidget(areaLabel2, i // 2, i % 2 + 1) - areaLayout.addWidget(areaLineEdit, i // 2, i % 2 + 2) - areaLayout.addWidget(editbtn, i // 2, i % 2 + 3) - editbtn.clicked.connect(lambda checked, btn=editbtn: self.wirteValue(btn)) - widgetLists.append([areaLabel2, areaLineEdit, editbtn, areaLabel]) - else: - areaLabel = QLabel(dataType + str(1) + ": " + '字节长度: ' + byteLineEdit + ' 当前值: ') - areaLabel2 = QLabel('0') - areaLineEdit = QLineEdit('0') - editbtn = QPushButton('强制') - - areaLayout.addWidget(areaLabel, i // 2, i % 2 + 4) - areaLayout.addWidget(areaLabel2, i // 2, i % 2 + 5) - areaLayout.addWidget(areaLineEdit, i // 2, i % 2 + 6) - areaLayout.addWidget(editbtn, i // 2, i % 2 + 7) - editbtn.clicked.connect(lambda checked, btn=editbtn: self.wirteValue(btn)) - - widgetLists.append([areaLabel2, areaLineEdit, editbtn, areaLabel]) - self.widgetList.append(widgetLists) - areaLayout.addItem(self.verticalSpacer, int(byteLineEdit) * 8 ,0) - - index = self.areaTabWidget.currentIndex() + 1 - areaId = DevicesManange.getAreaID(deviceName) - if areaId is not None and index in areaId: - if loacl: - - del self.widgetList[index - 1] - if init: - # print(222) - # self.mainwindow.devicesManange.getDevice(deviceName).addArea(type = dataType, bytes = int(byteLineEdit), nums = 1) - # self.mainwindow.devicesManange.recalculateAddress() + self.okBtn.setText('确定') + self.dataTypeCombox.setEnabled(True ) + self.orderCombox.setEnabled(True ) + self.byteLineEdit.setEnabled(True ) + self.obBtnValue = True return - DevicesManange.updataAreas(dataType, order, byteLineEdit, deviceName, index) - self.mainwindow.devicesManange.getDevice(deviceName).editArea(index = index - 1, type = dataType, order = order, bytes = int(byteLineEdit)) - self.mainwindow.devicesManange.recalculateAddress() - self.mainwindow.readVarTimer.start(500) - else: - DevicesManange.addAreas(dataType, order, byteLineEdit, deviceName) - self.mainwindow.devicesManange.getDevice(deviceName).addArea(type = dataType, bytes = int(byteLineEdit), order = order, nums = 1) - self.mainwindow.devicesManange.recalculateAddress() - self.mainwindow.readVarTimer.start(500) + + #删除布局内容 + if self.settingValue is None: + self.areaWidgetManage.delareaWidget(curIndex) + while areaLayout.count(): + + items = areaLayout.takeAt(0) + if isinstance(items, QSpacerItem): + areaLayout.removeItem(items) + if isinstance(items, QHBoxLayout): + while items.count(): + item = items.takeAt(0) + + widget = item.widget() + print(widget) + if widget: + widget.setParent(None) + widget.deleteLater() + items.deleteLater() + + + + # #添加布局 + # if dataType in ['AI', 'AO']: + + # if '主站' in deviceName and dataType == 'AI' or ('从站' in deviceName and dataType == 'AO'): + # buttonLayout = ButtonLayout(index = 1, dataType = dataType, byteLineEdit = byteLineEdit, devicetype = '主站AI') + # areaLayout.addLayout(buttonLayout, 0, 0) + # areaLayout.addItem(self.horizontalSpacer, 0, 1) + # areaLayout.addItem(self.verticalSpacer, 1, 0) + # areaWidgets.append([buttonLayout.areaLabe2]) + + + # elif '主站' in deviceName and dataType == 'AO' or ('从站' in deviceName and dataType == 'AI'): + # buttonLayout = ButtonLayout(index = 0, dataType = dataType, byteLineEdit = byteLineEdit, devicetype = '主站AO' ) + # areaLayout.addLayout(buttonLayout, 0, 0) + # areaLayout.addItem(self.horizontalSpacer, 0, 4) + # areaLayout.addItem(self.verticalSpacer, 1, 0) + # areaLineEdit = buttonLayout.areaLineEdit + # buttonLayout.editbtn.clicked.connect(lambda: self.wirteValue(areaLineEdit, dataType='主站AO')) + # areaWidgets.append([buttonLayout.areaLabe2, areaLineEdit,buttonLayout.editbtn]) + + # self.areaWidgetManage.addWidgets(areaWidgets) + # else: + # channelNumber = int(byteLineEdit) * 8 + # if '主站' in deviceName and dataType == 'DI' or ( + # '从站' in deviceName and dataType == 'DO'): + # for i in range(int(channelNumber)): + # buttonLayout = ButtonLayout(index = i + 1, dataType = dataType, byteLineEdit = byteLineEdit, devicetype = '主站DI' ) # type: ignore + # if i % 2 == 0: + # areaLayout.addLayout(buttonLayout, i // 2, i % 2) + # else: + # areaLayout.addLayout(buttonLayout, i // 2, i % 2 + 1 ) + # areaWidgets.append([buttonLayout.areaLabe2]) + # areaLayout.addItem(self.verticalSpacer, int(channelNumber) // 2 + 1, 0) + # self.areaWidgetManage.addWidgets(areaWidgets) + + # if '主站' in deviceName and dataType == 'DO' or ( + # '从站' in deviceName and dataType == 'DI'): + # for i in range(int(channelNumber)): + # buttonLayout = ButtonLayout(index = i + 1, dataType = dataType, byteLineEdit = byteLineEdit, devicetype = '主站DO' ) # type: ignore + # if i % 2 == 0: + # areaLayout.addLayout(buttonLayout, i // 2, i % 2) + # areaLineEdit = buttonLayout.areaLineEdit + # buttonLayout.editbtn.clicked.connect(partial(self.wirteValue, areaLineEdit, '主站DO')) + + # else: + # areaLayout.addLayout(buttonLayout, i // 2, i % 2 + 1 ) + # areaLineEdit = buttonLayout.areaLineEdit + # buttonLayout.editbtn.clicked.connect(partial(self.wirteValue, areaLineEdit, '主站DO')) + # areaWidgets.append([buttonLayout.areaLabe2, areaLineEdit,buttonLayout.editbtn]) + + # areaLayout.addItem(self.verticalSpacer, int(channelNumber) // 2 + 1, 0) + # self.areaWidgetManage.addWidgets(areaWidgets) + + # index = curIndex + 1 + + # areaId = DevicesManange.getAreaID(deviceName) + + # if self.settingValue is not None: + # return + # elif areaId is not None and index in areaId: + + # DevicesManange.updataAreas(dataType, order, byteLineEdit, deviceName, index) + # else: + + # DevicesManange.addAreas(dataType, order, byteLineEdit, deviceName) + + + + + # if areaId is not None and index in areaId: + # # if loacl: + # # del self.widgetList[index - 1] + # if init: + # return + # DevicesManange.updataAreas(dataType, order, byteLineEdit, deviceName, index) + # self.mainwindow.devicesManange.getDevice(deviceName).editArea(index = index - 1, type = dataType, order = order, bytes = int(byteLineEdit)) + # self.mainwindow.devicesManange.recalculateAddress() + # self.mainwindow.readVarTimer.start(500) + # else: + # DevicesManange.addAreas(dataType, order, byteLineEdit, deviceName) + # self.mainwindow.devicesManange.getDevice(deviceName).addArea(type = dataType, bytes = int(byteLineEdit), order = order, nums = 1) + # self.mainwindow.devicesManange.recalculateAddress() + # self.mainwindow.readVarTimer.start(500) @@ -230,31 +434,65 @@ class AreaTabWidget(QMainWindow): self.dataTypeDict = {'不转换': 'ABCD', '字节转换': 'DCBA', '字转换': 'CDAB', '字内转换': 'BADC'} return self.dataTypeDict[order] - def wirteValue(self, editBtn): - deviceName = self.areaTabWidget.parent().parent().parent().parent().parent().windowTitle() - # index = self.areaTabWidget.currentIndex() + def wirteValue(self, editbtn, dataType = None): + #判断输入值是否为数字 + if dataType == '主站AO': + editbtnText = editbtn.text() + print(editbtn, editbtnText) + pattern = re.compile(r'^\d+(\.\d+)?$') + match = pattern.match(editbtnText) + if not match: + QMessageBox.warning(self, '提示', '请输入数字。') + return + #判断输入值是否为0和1 + elif dataType == '主站DO': + editbtnText = editbtn.text() + print(editbtn, editbtnText, 'sssss') + pattern = re.compile(r'^[01]+$') + match = pattern.match(editbtnText) + if not match: + QMessageBox.warning(self, '提示', '请输入0或1。') + return + areaWidgets = self.areaWidgetManage.getAllWidgets() valueList = [] didoValueList = [] - if len(self.widgetList) > 0: - for widgetLists in self.widgetList: - for widgetList in widgetLists: - if editBtn in widgetList: - widgetList[0].setText(widgetList[1].text()) - - if isinstance(widgetList[1], QLineEdit): - dataType = widgetList[-1].text()[0:2] - # if dataType in ['DI', "DO"]: - didoValueList.append(float(widgetList[1].text())) - if didoValueList: - valueList.append(didoValueList) + if areaWidgets: + for areaWidget in areaWidgets: + if editbtn in areaWidget: + areaWidget[0].setText(areaWidget[1].text()) + if isinstance(areaWidget[1], QLineEdit): + didoValueList.append(float(areaWidget[1].text())) + print(didoValueList) + + if didoValueList: + valueList.append(didoValueList) didoValueList = [] - # print(valueList) - self.mainwindow.devicesManange.writeAreas(deviceName = deviceName, values = valueList) + + # self.mainwindow.devicesManange.writeAreas(deviceName = deviceName, values = valueList) + + + # valueList = [] + # didoValueList = [] + # if len(self.widgetList) > 0: + # for widgetLists in self.widgetList: + # for widgetList in widgetLists: + # if editBtn in widgetList: + # widgetList[0].setText(widgetList[1].text()) + + # if isinstance(widgetList[1], QLineEdit): + # dataType = widgetList[-1].text()[0:2] + # # if dataType in ['DI', "DO"]: + # didoValueList.append(float(widgetList[1].text())) + # if didoValueList: + # valueList.append(didoValueList) + # didoValueList = [] + + # self.mainwindow.devicesManange.writeAreas(deviceName = deviceName, values = valueList) def readValue(self): - deviceName = self.areaTabWidget.parent().parent().parent().parent().parent().windowTitle() + deviceName = self.mainwindow.devicesManange.getDeviceName(self) curIndex = -1 areaIndex = self.areaTabWidget.currentIndex() if len(self.widgetList) > 0: @@ -280,7 +518,7 @@ class AreaTabWidget(QMainWindow): for value, widgets in zip(values, areaWidgets): widgets[0].setText(str(value)) - + if __name__ == '__main__': app = QApplication(sys.argv) diff --git a/UI/AreaTableWidget.py b/UI/AreaTableWidget.py deleted file mode 100644 index e69de29..0000000 diff --git a/UI/DeviceDialogWidget.py b/UI/DeviceDialogWidget.py new file mode 100644 index 0000000..7533ce6 --- /dev/null +++ b/UI/DeviceDialogWidget.py @@ -0,0 +1,45 @@ +from PyQt5.QtWidgets import QDialog, QFormLayout, QLineEdit, QDialogButtonBox, QMessageBox +from PyQt5.QtGui import QIcon +from PyQt5.QtCore import Qt + +class DeviceDialog(QDialog): + def __init__(self, parent=None): + super().__init__(parent) + + self.initUI() + + def initUI(self): + layout = QFormLayout() + + deviceName = QLineEdit() + deviceName.setObjectName('deviceName') + + layout.addRow("设备名:", deviceName) + + button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + ok_button = button_box.button(QDialogButtonBox.Ok) + ok_button.setText("确定") # 设置Ok按钮的文本 + + cancel_button = button_box.button(QDialogButtonBox.Cancel) + cancel_button.setText("取消") # 设置Cancel按钮的文本 + + button_box.accepted.connect(self.check_input) + button_box.rejected.connect(self.reject) + + layout.addRow(button_box) + + self.setWindowIcon(QIcon('Static/zhjt.ico')) + self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) # 去掉标题栏的问号 + self.setLayout(layout) + self.setWindowTitle("设备信息") + + def getParameters(self): + deviceName = self.findChild(QLineEdit, "deviceName").text() + return deviceName + + def check_input(self): + deviceName = self.getParameters() + if not deviceName: + QMessageBox.warning(self, '警告', '请输入设备名') + else: + self.accept() # 所有输入都是数字且不为空时接受对话框 \ No newline at end of file diff --git a/UI/DeviceWidget.py b/UI/DeviceWidget.py index 0632af9..684a8bc 100644 --- a/UI/DeviceWidget.py +++ b/UI/DeviceWidget.py @@ -1,74 +1,158 @@ -from PyQt5.QtWidgets import QDialog, QFormLayout, QLineEdit, QComboBox, QDialogButtonBox, QMessageBox -from PyQt5.QtGui import QPixmap, QIcon -from PyQt5.QtCore import Qt -import sys -import re -class DeviceDialog(QDialog): - def __init__(self, parent=None): - super().__init__(parent) - self.initUI() +import json + +from PyQt5.QtWidgets import QMainWindow, QDialog, QTabWidget, QPushButton, QSpacerItem, QSizePolicy,QMessageBox, QHBoxLayout, QWidget +from PyQt5.QtGui import QIcon +from UI.DeviceDialogWidget import DeviceDialog + +from model.ProjectModel.DeviceManage import DevicesManange +from utils.DBModels.BaseModel import * +from UI.AreaTabWidget import AreaTabWidget +from utils.DBModels.DeviceModels import DeviceDB +from model.ProjectModel.DeviceManage import DevicesManange +from UI.DeviceDialogWidget import DeviceDialog +from model.ProjectModel.DeviceWidgetManage import DeviceWidgetManage +class DeviceWidget(QMainWindow): + def __init__(self, dockWidget): + super().__init__() + self.dockWidget = dockWidget + self.forceValues = [] + self.initUI() + + def initUI(self): - layout = QFormLayout() - proType = QComboBox() - proType.addItems(['DP', 'PA']) - proType.setObjectName('ProtocolType') - masterSlaveModel = QComboBox() - masterSlaveModel.addItems(['主站', '从站']) - masterSlaveModel.setObjectName('masterSlaveModel') - - deviceName = QLineEdit() - deviceName.setObjectName('deviceName') - - pvUpperLimit = QLineEdit() - pvUpperLimit.setObjectName('pvUpperLimit') - - pvLowerLimit = QLineEdit() - pvLowerLimit.setObjectName('pvLowerLimit') - - pvUnit = QLineEdit() - pvUnit.setObjectName('pvUnit') - - layout.addRow('协议类型', proType) - layout.addRow('主从模式', masterSlaveModel) - layout.addRow("设备名:", deviceName) - layout.addRow("量程上限:", pvUpperLimit) - layout.addRow("量程下限:", pvLowerLimit) - layout.addRow("单位:", pvUnit) - - - button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) - ok_button = button_box.button(QDialogButtonBox.Ok) - ok_button.setText("确定") # 设置Ok按钮的文本 - cancel_button = button_box.button(QDialogButtonBox.Cancel) - cancel_button.setText("取消") # 设置Cancel按钮的文本 - - button_box.accepted.connect(self.check_input) - button_box.rejected.connect(self.reject) - - layout.addRow(button_box) - self.setWindowIcon(QIcon('Static/zhjt.ico')) - self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) # 去掉标题栏的问号 - self.setLayout(layout) - self.setWindowTitle("设备信息") - - def getParameters(self): - proType = self.findChild(QComboBox, "ProtocolType").currentText() - masterSlaveModel = self.findChild(QComboBox, "masterSlaveModel").currentText() - deviceName = self.findChild(QLineEdit, "deviceName").text() - pvUpperLimit = self.findChild(QLineEdit, "pvUpperLimit").text() - pvLowerLimit = self.findChild(QLineEdit, "pvLowerLimit").text() - pvUnit = self.findChild(QLineEdit, "pvUnit").text() - return deviceName, proType, masterSlaveModel, pvUpperLimit, pvLowerLimit, pvUnit - - def check_input(self): - deviceName, proType, masterSlaveModel, pvUpperLimit, pvLowerLimit, pvUnit = self.getParameters() - - if not pvUpperLimit or not pvLowerLimit or not pvUnit or not deviceName: - QMessageBox.warning(self, '警告', '有值未输入。') - elif not re.match(r'^[-+]?\d*\.?\d*$', pvUpperLimit) or not re.match(r'^[-+]?\d*\.?\d*$', pvLowerLimit): - QMessageBox.warning(self, '警告', '请输入数字。') - elif pvUpperLimit < pvLowerLimit: - QMessageBox.warning(self, '警告', '量程输入有误。') + #获取DP、PA协议和主从模式 + + self.proType = self.dockWidget.windowTitle()[0:2] + self.masterSlaveModel = self.dockWidget.windowTitle()[2:4] + + # self.deviceWidgetManage = DeviceWidgetManage() + self.deviceTabWidget = QTabWidget(self) + self.deviceTabWidget.setObjectName('deviceTabWidget') + + + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + + self.addDeviceButton = QPushButton('添加设备 ') + self.addDeviceButton.setObjectName('deviceAddButton') + self.addDeviceButton.setIcon(QIcon('Static/add.png')) + self.addDeviceButton.setFlat(True) + self.addDeviceButton.clicked.connect(self.addDeviceWidget) + + self.deviceTabWidget.setCornerWidget(self.addDeviceButton) + self.deviceTabWidget.setTabsClosable(True) + self.deviceTabWidget.tabCloseRequested.connect(self.closeTab) + + self.initWidget() + + # 设置主窗口的中心部分为 QTabWidget + self.setCentralWidget(self.deviceTabWidget) + + def closeTab(self, index): + reply = QMessageBox.question(self, 'Confirmation', '确定删掉此设备吗?', + QMessageBox.Yes | QMessageBox.No, QMessageBox.No) + if reply == QMessageBox.Yes: + if index != -1: + self.deviceTabWidget.removeTab(index) + DeviceDB.deleteDevice(deviceName = self.deviceName) + else: + return + if self.deviceTabWidget.count() == 0: + self.initWidget() + + + + def addDeviceWidget(self,init = False,deviceName = None): + if deviceName is None: + dialog = DeviceDialog() + if dialog.exec_() == QDialog.Accepted: + self.titleName = dialog.getParameters() + self.deviceName = self.titleName + self.dockWidget.windowTitle() + DeviceDB().addDevice(deviceName = self.deviceName, proType = self.proType , masterSlaveModel = self.masterSlaveModel) + areaTabWidget = AreaTabWidget(self) + if init: + self.deviceTabWidget.removeTab(0) + tabIndex = self.deviceTabWidget.count() + self.deviceTabWidget.tabBar().setHidden(False) + self.deviceTabWidget.addTab(areaTabWidget,str(self.titleName)) + self.deviceTabWidget.setCurrentIndex(tabIndex) + # self.deviceWidgetManage.addDevice(deviceName = self.deviceName, areaTabWidget=areaTabWidget, dockWidget=self.dockWidget) + else: + return + else: + self.deviceTabWidget.removeTab(0) + self.deviceName = deviceName + self.titleName = self.deviceName[:-4] + areaTabWidget = AreaTabWidget(self) + self.deviceTabWidget.tabBar().setHidden(False) + self.deviceTabWidget.addTab(areaTabWidget,str(self.titleName)) + + + def initWidget(self): + widget = QWidget() + layout = QHBoxLayout() + addButton = QPushButton('添加设备') + addButton.clicked.connect(lambda: self.addDeviceWidget(True)) + layout.addItem(self.horizontalSpacer) + layout.addWidget(addButton) + layout.addItem(self.horizontalSpacer) + widget.setLayout(layout) + self.deviceTabWidget.addTab(widget,'') + self.deviceTabWidget.tabBar().setHidden(True) + + alldevices = DevicesManange.getAllDevice() + titleName = self.dockWidget.windowTitle() + if alldevices: + for devices in alldevices: + # self.devicesManange.addDevice(proType = devices[1], masterSlaveModel = devices[2], deviceName = devices[0]) + deviceName = devices[0] + if titleName in deviceName: + self.addDeviceWidget(deviceName=deviceName) + + + + + + + def initAreaWidget(self, mdiarea): + alldevices = DevicesManange.getAllDevice() + for devices in alldevices: + areas = devices[3] + + deviceWidget = self.deviceWidget(devices[0], mdiarea) #新建deviceWidget + areaTabWidget = deviceWidget.widget().widget().centralWidget() # type: ignore + self.devicesManange.addDevice(proType = devices[1], masterSlaveModel = devices[2], deviceName = devices[0], deviceWidget = deviceWidget, areaTabWidget = areaTabWidget) # type: ignore + + + if areas is not None: + areas = json.loads(areas) + for area in areas: + dataType, order = self.tran(area["type"], area["order"]) + channelBytes = area["bytes"] + dev = self.devicesManange.getDevice(deviceName = devices[0]) + dev.addArea(type = area["type"], order = area["order"], bytes = int(channelBytes), nums = 1) #添加area + areaTabWidget.initAreaTab(dataType, order, channelBytes) + self.devicesManange.recalculateAddress() + + def createDeciveWidget(self, mdiarea): + dialog = DeviceDialog() + + if dialog.exec_() == QDialog.Accepted: + deviceName, proType, masterSlaveModel, pvUpperLimit, pvLowerLimit, pvUnit = dialog.getParameters() + windowTitle = deviceName + ' ' + proType + masterSlaveModel + ' ' + pvLowerLimit + '-' + pvUpperLimit + pvUnit + DeviceDB().addDevice(deviceName = windowTitle, proType = proType, masterSlaveModel = masterSlaveModel, pvUpperLimit=pvUpperLimit, pvLowerLimit=pvLowerLimit, pvUnit=pvUnit) + deviceWidget = self.deviceWidget(windowTitle, mdiarea) + areaTabWidget = deviceWidget.widget().widget().centralWidget() + self.devicesManange.addDevice(proType = proType, masterSlaveModel = masterSlaveModel, deviceName = windowTitle, deviceWidget = deviceName, areaTabWidget = areaTabWidget) + self.devicesManange.recalculateAddress() else: - self.accept() # 所有输入都是数字且不为空时接受对话框 \ No newline at end of file + return + + + + + + + + diff --git a/UI/Find Results b/UI/Find Results new file mode 100644 index 0000000..c026acb --- /dev/null +++ b/UI/Find Results @@ -0,0 +1,6 @@ + +111111111111111111111111 + +111111111111111111111111 + + diff --git a/UI/MainWindow.py b/UI/MainWindow.py index 0767ee4..df51be0 100644 --- a/UI/MainWindow.py +++ b/UI/MainWindow.py @@ -1,23 +1,11 @@ import sys -import json -import collections -import time - -from PyQt5.QtWidgets import QApplication, QMainWindow, QToolBar, QMdiArea, QAction, QInputDialog, QDialog, QFormLayout, QLineEdit, \ - QMdiSubWindow, QDialogButtonBox, QWidget, QComboBox, QTabBar, QTabWidget, QGridLayout, QLabel, QPushButton, QSpacerItem, QSizePolicy, QHBoxLayout, QTableWidget, QScrollArea -from PyQt5 import QtCore -from PyQt5.QtGui import QPixmap, QIcon -from UI.DeviceWidget import DeviceDialog -from UI.AreaSettingWidget import AreaSettingWidget -from UI.DelAreaWidget import DelAreaWidget -from model.ProjectModel.DeviceManage import DevicesManange, Device -from protocol.ModBus.ModBusThread import MyThread + +from PyQt5.QtWidgets import QApplication, QMainWindow, QDockWidget, QToolBar, QAction +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QIcon from utils.DBModels.BaseModel import * -from UI.AreaTabWidget import AreaTabWidget -from utils.DBModels.DeviceModels import DeviceDB from model.ClientModel.Client import Client -from model.ProjectModel.DeviceManage import DevicesManange - +from UI.DeviceWidget import DeviceWidget class CommonHelper: def __init__(self): @@ -32,23 +20,14 @@ class CommonHelper: class MainWindow(QMainWindow): def __init__(self): super().__init__() - self.devicesManange = DevicesManange() - self.subWindows = [] #存储设备widget self.initUI() - self.initAreaWidget() - - self.states = True def initUI(self): - self.toolbar = QToolBar() + self.toolbar = QToolBar() self.addToolBar(self.toolbar) - # self.setWindowState(self.windowState() | QtCore.Qt.WindowMaximized) - self.addDiviceBtn = QAction("添加设备", self) - self.addDiviceBtn.setObjectName("addDiviceBtn") - self.addDiviceBtn.triggered.connect(self.createDeciveWidget) - - self.startProtocolBtn = QAction("开始读取", self) + + self.startProtocolBtn = QAction("开始通讯", self) self.startProtocolBtn.setObjectName("startProtocolBtn") self.startProtocolBtn.triggered.connect(self.startProtocol) @@ -56,146 +35,39 @@ class MainWindow(QMainWindow): self.loadProjectBtn.setObjectName("loadProjectBtn") self.loadProjectBtn.triggered.connect(self.loadProject) - self.toolbar.addAction(self.addDiviceBtn) self.toolbar.addAction(self.loadProjectBtn) self.toolbar.addAction(self.startProtocolBtn) - self.mdi_area = QMdiArea() - - self.setCentralWidget(self.mdi_area) - self.setWindowIcon(QIcon('Static/zhjt.ico')) - - self.setWindowTitle("PROFIBUS") - self.setGeometry(1000, 500, 800, 600) - - self.readVarTimer = QtCore.QTimer() - self.readVarTimer.timeout.connect(self.readValues) - - - - def deviceWidget(self, windowTitle): - subWindow = AreaQMdiSubWindow(self)# 创建一个子窗口 - subWindow.setObjectName('subWindow') - areaTabWidget = AreaTabWidget(self) - - #新建mainWindows放入subwindows - areaMainWindow = QMainWindow() - areaMainWindow.setCentralWidget(areaTabWidget) + dpMasterDockWidget = QDockWidget('DP主站') + dpMasterDockWidget.setWidget(DeviceWidget(dpMasterDockWidget)) + dpMasterDockWidget.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) # type: ignore - #mainwindows添加工具栏 - toolbar = QToolBar() - areaMainWindow.addToolBar(toolbar) - addAreaBtn = QAction("添加通道", areaMainWindow) - addAreaBtn.setObjectName("addDiviceBtn") - addAreaBtn.triggered.connect(areaTabWidget.addAreaTab) - toolbar.addAction(addAreaBtn) + dpSlaveDockWidget = QDockWidget('DP从站') + dpSlaveDockWidget.setWidget(DeviceWidget(dpSlaveDockWidget)) + dpSlaveDockWidget.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) # type: ignore - #为mainwindow添加右滑动条 - scroll_widget = QScrollArea() - scroll_widget.setWidgetResizable(True) - scroll_widget.setWidget(areaMainWindow) + paMasterDockWidget = QDockWidget('PA主站') + paMasterDockWidget.setWidget(DeviceWidget(paMasterDockWidget)) + paMasterDockWidget.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) # type: ignore - #设置subwindow - subWindow.setWindowTitle(windowTitle) - subWindow.setGeometry(0, 0, 600, 500) - subWindow.setWidget(scroll_widget) - subWindow.setWindowIcon(QIcon('Static/zhjt.ico')) - self.mdi_area.addSubWindow(subWindow) # 将子窗口添加到MDI区域 - subWindow.show() + paSlaveDockWidget = QDockWidget('PA从站') + paSlaveDockWidget.setWidget(DeviceWidget(paSlaveDockWidget)) + paSlaveDockWidget.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) # type: ignore - self.subWindows.append(subWindow) - return subWindow - - def loadProject(self): - pass - - def initAreaWidget(self): - alldevices = DevicesManange.getAllDevice() - for devices in alldevices: - areas = devices[3] - self.devicesManange.addDevice(proType = devices[1], masterSlaveModel = devices[2], deviceName = devices[0]) - areaTabWidget = self.deviceWidget(devices[0]).widget().widget().centralWidget() - if areas is not None: - areas = json.loads(areas) - for area in areas: - dataType, order = self.tran(area["type"], area["order"]) - channelBytes = area["bytes"] - dev = self.devicesManange.getDevice(deviceName = devices[0]) - - dev.addArea(type = area["type"], order = area["order"], bytes = int(channelBytes), nums = 1) - areaTabWidget.initAreaTab(dataType, order, channelBytes) - self.devicesManange.recalculateAddress() - - def createDeciveWidget(self): - dialog = DeviceDialog() - if dialog.exec_() == QDialog.Accepted: - deviceName, proType, masterSlaveModel, pvUpperLimit, pvLowerLimit, pvUnit = dialog.getParameters() - windowTitle = deviceName + ' ' + proType + masterSlaveModel + ' ' + pvLowerLimit + '-' + pvUpperLimit + pvUnit - DeviceDB().addDevice(deviceName = windowTitle, proType = proType, masterSlaveModel = masterSlaveModel, pvUpperLimit=pvUpperLimit, pvLowerLimit=pvLowerLimit, pvUnit=pvUnit) - self.devicesManange.addDevice(proType = proType, masterSlaveModel = masterSlaveModel, deviceName = windowTitle) - self.devicesManange.recalculateAddress() - else: - return - - self.deviceWidget(windowTitle) + self.addDockWidget(Qt.TopDockWidgetArea, dpMasterDockWidget) # type: ignore + self.addDockWidget(Qt.TopDockWidgetArea, dpSlaveDockWidget) # type: ignore + self.addDockWidget(Qt.BottomDockWidgetArea, paMasterDockWidget) # type: ignore + self.addDockWidget(Qt.BottomDockWidgetArea, paSlaveDockWidget) # type: ignore + self.setWindowIcon(QIcon('Static/zhjt.ico')) + self.setWindowTitle("PROFIBUS") + self.showMaximized() def startProtocol(self): - if self.states == True: - self.readVarTimer.start(500) - self.states = False - self.startProtocolBtn.setText('停止读取') - else: - self.readVarTimer.stop() - self.states = True - self.startProtocolBtn.setText('开始读取') - def readValues(self): - # try: - self.devicesManange.readAreas() - # except Exception as e: - # print(e) - for subWindow in self.subWindows: - areaTabWidget = subWindow.widget().widget().centralWidget() - areaTabWidget.readValue() - - def tran(self, dataType, order): - if dataType == 'AI': - dataType = 0 - if dataType == 'AO': - dataType = 1 - if dataType == 'DI': - dataType = 2 - if dataType == 'DO': - dataType = 3 - - if order == 'ABCD': - order = 0 - if order == 'DCBA': - order = 1 - if order == 'CDAB': - order = 2 - if order == 'BADC': - order = 3 - - return dataType, order - - - -class AreaQMdiSubWindow(QMdiSubWindow): - def __init__(self, parentWindow): - super().__init__() - self.parentWindow = parentWindow - def closeEvent(self, event): - self.parentWindow.subWindows.remove(self) - self.parentWindow.devicesManange.delDevice(deviceName = self.windowTitle()) - DeviceDB.deleteDevice(deviceName = self.windowTitle()) - - - - - - + pass + def loadProject(self): + pass if __name__ == '__main__': app = QApplication(sys.argv) diff --git a/bin.py b/bin.py index cf96e85..2e78048 100644 --- a/bin.py +++ b/bin.py @@ -8,7 +8,7 @@ import sys if __name__ == '__main__': app = QApplication(sys.argv) - app.setStyle(QStyleFactory.create('Fusion')) + app.setStyle(QStyleFactory.create('windowsvista')) app.setStyleSheet(CommonHelper.readQss('static/main.qss')) Client.initDB() window = MainWindow() diff --git a/model/ProjectModel/DeviceManage.py b/model/ProjectModel/DeviceManage.py index ec346d3..fa2b701 100644 --- a/model/ProjectModel/DeviceManage.py +++ b/model/ProjectModel/DeviceManage.py @@ -1,5 +1,7 @@ import collections import json + + from utils.DBModels.DeviceModels import DeviceDB from model.ProjectModel.AreaManage import Area import numpy as np @@ -17,6 +19,9 @@ class Device(): protocolType = None masterOrSlave = None deviceName = None + deviceWidget = None + areaTabWidget = [] + def __init__(self): self.inputAreas = [] self.outputAreas = [] @@ -28,21 +33,20 @@ class Device(): bytes = int(bytes) area.type = type area.order = order - area.bytes = bytes - area.length = self.getLength(nums, bytes) + area.bytes = bytes # type: ignore + area.length = self.getLength(nums, bytes) # type: ignore area.nums = nums area.currentValue = [0] * nums if type in ["AI", "DI"]: - area.startAddress = 0 if not self.inputEndAddress else self.inputEndAddress - area.endAddress = area.startAddress + area.length - # print(area.startAddress, area.endAddress) + area.startAddress = 0 if not self.inputEndAddress else self.inputEndAddress + 1 # type: ignore + area.endAddress = area.startAddress + area.length # type: ignore self.inputEndAddress = area.endAddress area.addressList = np.arange(area.startAddress, area.endAddress + 1, area.bytes).tolist() self.indexDict[len(self.indexDict.values())] = len(self.inputAreas) self.inputAreas.append(area) elif type in ["DO" , "AO"]: - area.startAddress = 0 if not self.outputEndAddress else self.outputEndAddress - area.endAddress = area.startAddress + area.length + area.startAddress = 0 if not self.outputEndAddress else self.outputEndAddress + 1 # type: ignore + area.endAddress = area.startAddress + area.length # type: ignore self.outputEndAddress = area.endAddress area.addressList = np.arange(area.startAddress, area.endAddress + 1, area.bytes).tolist() self.indexDict[len(self.indexDict.values())] = len(self.outputAreas) @@ -66,7 +70,7 @@ class Device(): elif index == 0 and inputOrOutput == 1: area.startAddress = self.outputStartAddress else: - area.startAddress = areas[index - 1].endAddress + area.startAddress = areas[index - 1].endAddress + 1 area.endAddress = area.startAddress + area.length area.addressList = np.arange(area.startAddress, area.endAddress + 1, area.bytes).tolist() # print(area.addressList, area.startAddress, area.endAddress, self.deviceName) @@ -109,6 +113,8 @@ class Device(): @classmethod def delAreas(self, deviceName, id): jsonCon = json.loads(DeviceDB.getByName(deviceName=deviceName).areaJson) + if not jsonCon or len(jsonCon) < id: + return jsonCon.pop(id) if jsonCon == []: @@ -147,11 +153,14 @@ class DevicesManange(): - def addDevice(self, proType, masterSlaveModel, deviceName): + def addDevice(self, proType, masterSlaveModel, deviceName, deviceWidget, areaTabWidget): device = Device() device.type = proType device.masterOrSlave = masterSlaveModel device.deviceName = deviceName + device.deviceWidget = deviceWidget + device.areaTabWidget.append(areaTabWidget) + if proType == "DP" and masterSlaveModel == "主站": curProDict = self.dpMasterDevices @@ -166,13 +175,18 @@ class DevicesManange(): device.inputStartAddress = 0 device.outputStartAddress = 0 else: - device.inputStartAddress = list(curProDict.values())[-1].inputEndAddress - device.outputStartAddress = list(curProDict.values())[-1].outputEndAddress + device.inputStartAddress = list(curProDict.values())[-1].inputEndAddress + 1 + device.outputStartAddress = list(curProDict.values())[-1].outputEndAddress + 1 curProDict[deviceName] = device + + + + + def initDevices(self): pass - + def delDevice(self, deviceName): for devicesDict in [self.paMasterDevices, self.paSlaveDevices, self.dpMasterDevices, self.dpSlaveDevices]: if deviceName in devicesDict: @@ -189,8 +203,8 @@ class DevicesManange(): else: inputAddress = list(devicesDict.values())[index - 1].inputEndAddress outputAddress = list(devicesDict.values())[index - 1].outputEndAddress - device.inputStartAddress = 0 if inputAddress == 0 else inputAddress - device.outputStartAddress = 0 if outputAddress == 0 else outputAddress + device.inputStartAddress = 0 if inputAddress == 0 else inputAddress + 1 + device.outputStartAddress = 0 if outputAddress == 0 else outputAddress + 1 # print(device.inputStartAddress, device.inputEndAddress, deviceName, '输入') # print(device.outputStartAddress, device.outputEndAddress, deviceName, 'shuchu') device.recalculateAddress() @@ -201,7 +215,16 @@ class DevicesManange(): for devicesDict in [self.paMasterDevices, self.paSlaveDevices, self.dpMasterDevices, self.dpSlaveDevices]: if deviceName in devicesDict: return devicesDict[deviceName] + + + def getAllDeviceObj(self): + deviceObjLst = [] + for devicesDict in [self.paMasterDevices, self.paSlaveDevices, self.dpMasterDevices, self.dpSlaveDevices]: + for deviceName in devicesDict: + deviceObjLst.append(devicesDict[deviceName]) + return deviceObjLst + def writeAreas(self, deviceName, values): # print(values) bytes = b"" @@ -234,7 +257,6 @@ class DevicesManange(): for area in forceAreas: # print(area.forceValue) if area.type in ["AI", "AO"]: - # print(area.forceValue) byte = floatToBytes(area.forceValue, area.bytes, order = area.order) elif area.type in ["DI", "DO"]: # if device.type == "PA" and device.masterOrSlave == "从站" and len(area.forceValue) == 16: @@ -244,7 +266,6 @@ class DevicesManange(): if len(bytes) % 2 != 0: bytes += struct.pack('B', 0) # print(bytes) - # print(bytes) values = struct.unpack('!' + 'H' * int(len(bytes) / 2), bytes) modbusM.writeMultipleRegister(slaveId = 1, address = 0, outputValue = values) # print(struct.unpack('>f', struct.pack('!HH', *values[:2]))) @@ -268,33 +289,26 @@ class DevicesManange(): continue inputEndAddress = max([x.inputEndAddress for x in list(curProDict.values())]) outputEndAddress = max([x.outputEndAddress for x in list(curProDict.values())]) - inputAreaNums = sum([len(x.inputAreas) for x in list(curProDict.values())]) - 1 - outputAreaNums = sum([len(x.outputAreas) for x in list(curProDict.values())]) - 1 bytesNums = inputEndAddress if areaType == 'input' else outputEndAddress intNums = int(bytesNums / 2) if bytesNums % 2 == 0 else int(bytesNums / 2) + 1 if bytesNums == 0: continue intValues = modbusM.readHoldingRegisters(slaveId = 1, startAddress = 0, varNums = intNums) bytesValues = struct.pack(f"!{'H' * len(intValues)}", *intValues) - # print(bytesValues, intNums, bytesNums) - # print(bytes) for device in curProDict.values(): readAreas = device.inputAreas if areaType == 'input' else device.outputAreas for area in readAreas: - # print(area.startAddress, area.endAddress) if area.startAddress == 0: bytes = bytesValues[area.startAddress:area.endAddress] else: - bytes = bytesValues[area.startAddress:area.endAddress] - # print(area.startAddress, area.endAddress) + bytes = bytesValues[area.startAddress - 1:area.endAddress] + if area.type in ['AI', 'AO']: for i in range(0, len(bytes), 4): byte = bytes[i:i+4] if len(byte) != 4: continue - # print(round(struct.unpack('!f', reorderBytes(byte, area.order))[0], 4)) area.currentValue[i] = round(struct.unpack('!f', reorderBytes(byte, area.order))[0], 4) - # print(round(struct.unpack('!f', reorderBytes(byte, area.order))[0], 4)) elif area.type in ['DI', 'DO']: bytes = bytes[::-1] area.currentValue = bytesToCoils(bytes) @@ -307,7 +321,6 @@ class DevicesManange(): "type": type, "order": order, "bytes": bytes, - }]) else: jsonCon = json.loads(DeviceDB.getByName(deviceName=deviceName).areaJson) @@ -364,6 +377,12 @@ class DevicesManange(): pass @classmethod + def getMasterSlaveModel(self, deviceName): + deviceName = deviceName + masterSlaveModel = DeviceDB.getByName(deviceName=deviceName).masterSlaveModel + if masterSlaveModel: + return masterSlaveModel + @classmethod def getAllDevice(self): # 查询所有设备 devices = DeviceDB.get_all() @@ -373,4 +392,3 @@ class DevicesManange(): for x in devices: l.append([x.deviceName, x.proType, x.masterSlaveModel, x.areaJson]) return l - diff --git a/model/ProjectModel/DeviceWidgetManage.py b/model/ProjectModel/DeviceWidgetManage.py new file mode 100644 index 0000000..7c5c81d --- /dev/null +++ b/model/ProjectModel/DeviceWidgetManage.py @@ -0,0 +1,37 @@ + +class Area(): + mainLayout = None + leftLayoutWidget = [] + rightLayoutWidget = [] + + + + +class Device(): + deviceName = None + areaTabWidget = None + dockWidget = None + +class DeviceWidgetManage(): + + def addDevice(self,deviceName, areaTabWidget, dockWidget): + Device.deviceName = deviceName + Device.areaTabWidget = areaTabWidget + Device.dockWidget = dockWidget + + def getDeviceName(self): + return Device.deviceName + + def addArea(self, mainLayout=None, leftLayoutWidget=None, rightLayoutWidget=None): + + if mainLayout is not None: + Area.mainLayout = mainLayout + if leftLayoutWidget is not None: + Area.leftLayoutWidget = leftLayoutWidget + if rightLayoutWidget is not None: + Area.rightLayoutWidget = rightLayoutWidget + + def getAreaTabWidget(self): + return Device.areaTabWidget + + diff --git a/model/ProjectModel/Untitled-1.py b/model/ProjectModel/Untitled-1.py new file mode 100644 index 0000000..8079066 --- /dev/null +++ b/model/ProjectModel/Untitled-1.py @@ -0,0 +1,15 @@ +class Solution(object): + def twoSum(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: List[int] + """ + + for i in range(0, len(nums)): + for j in range(1, len(nums)): + if nums[i] + nums[j] == target: + print([i,j]) + +solution = Solution() +solution.twoSum([2,7,11,15], 9) \ No newline at end of file diff --git a/utils/DBModels/DeviceModels.py b/utils/DBModels/DeviceModels.py index 995640c..accb2fd 100644 --- a/utils/DBModels/DeviceModels.py +++ b/utils/DBModels/DeviceModels.py @@ -24,9 +24,7 @@ class DeviceDB(BaseModel): proType = CharField() masterSlaveModel = CharField() areaJson = JSONField() - pvUpperLimit = CharField() - pvLowerLimit = CharField() - pvUnit = CharField() + createTime = CharField() # 查询设备是否存在 @@ -50,29 +48,17 @@ class DeviceDB(BaseModel): # 添加设备 - def addDevice(self, deviceName, proType, masterSlaveModel=masterSlaveModel, areaJson=None, pvLowerLimit=pvLowerLimit, pvUpperLimit=pvUpperLimit, pvUnit=pvUnit): + def addDevice(self, deviceName, proType, masterSlaveModel=masterSlaveModel, areaJson=json.dumps([])): self.deviceName = deviceName self.proType = proType self.masterSlaveModel = masterSlaveModel self.areaJson = areaJson - self.pvUpperLimit = pvUpperLimit - self.pvLowerLimit = pvLowerLimit - self.pvUnit = pvUnit self.createTime = datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S') # print(self.createTime) self.save() - def initDevice(self, deviceName, proType, masterSlaveModel, areaJson, pvLowerLimit, pvUpperLimit, pvUnit): - self.deviceName = deviceName - self.proType = proType - self.masterSlaveModel = masterSlaveModel - self.areaJson = areaJson - self.pvUpperLimit = pvUpperLimit - self.pvLowerLimit = pvLowerLimit - self.pvUnit = pvUnit - self.createTime = datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S') - self.save() +