217 lines
9.0 KiB
Python
217 lines
9.0 KiB
Python
import sys
|
||
import csv
|
||
from PyQt5.QtWidgets import QApplication, QDialog, QVBoxLayout, QHBoxLayout, QTableWidget, QTableWidgetItem, \
|
||
QPushButton, QCheckBox, QFileDialog, QMessageBox
|
||
from PyQt5.QtCore import Qt
|
||
|
||
|
||
class BatchOperationDialog(QDialog):
|
||
def __init__(self):
|
||
super().__init__()
|
||
self.setWindowTitle("批量操作节点")
|
||
self.setGeometry(100, 100, 800, 400)
|
||
|
||
# 初始化分页
|
||
self.current_page = 0
|
||
self.rows_per_page = 20
|
||
|
||
# 初始化数据
|
||
self.data = []
|
||
|
||
# 初始化UI
|
||
self.init_ui()
|
||
|
||
def init_ui(self):
|
||
# 主布局
|
||
main_layout = QVBoxLayout()
|
||
|
||
# 创建表格(8列,初始行数可以设置为20)
|
||
self.table_widget = QTableWidget(self.rows_per_page, 8) # 默认显示20行
|
||
self.table_widget.setHorizontalHeaderLabels(
|
||
["选择", "IP地址", "MAC地址", "版本号", "通道1名称", "通道1绑定设备", "通道2名称", "通道2绑定设备"]
|
||
)
|
||
|
||
# 使通道列可编辑
|
||
for row in range(self.table_widget.rowCount()):
|
||
self.table_widget.setItem(row, 4, QTableWidgetItem()) # 通道1名称
|
||
self.table_widget.setItem(row, 5, QTableWidgetItem()) # 通道1绑定设备
|
||
self.table_widget.setItem(row, 6, QTableWidgetItem()) # 通道2名称
|
||
self.table_widget.setItem(row, 7, QTableWidgetItem()) # 通道2绑定设备
|
||
|
||
# 添加勾选框到第1列
|
||
for row in range(self.table_widget.rowCount()):
|
||
check_box_item = QTableWidgetItem()
|
||
check_box_item.setCheckState(0) # 初始状态为未选中
|
||
self.table_widget.setItem(row, 0, check_box_item)
|
||
|
||
# 按钮布局
|
||
button_layout = QHBoxLayout()
|
||
|
||
# 创建按钮
|
||
self.select_all_button = QPushButton("全选")
|
||
self.select_none_button = QPushButton("全不选")
|
||
self.get_version_button = QPushButton("获取版本")
|
||
self.get_mac_button = QPushButton("获取MAC")
|
||
self.upgrade_button = QPushButton("升级节点")
|
||
self.load_ips_button = QPushButton("加载IP列表")
|
||
self.load_all_button = QPushButton("加载完整信息列表")
|
||
self.save_button = QPushButton("保存表数据")
|
||
self.prev_page_button = QPushButton("上一页")
|
||
self.next_page_button = QPushButton("下一页")
|
||
|
||
# 按钮连接
|
||
self.select_all_button.clicked.connect(self.select_all)
|
||
self.select_none_button.clicked.connect(self.select_none)
|
||
self.get_version_button.clicked.connect(self.get_version)
|
||
self.get_mac_button.clicked.connect(self.get_mac)
|
||
self.upgrade_button.clicked.connect(self.upgrade_node)
|
||
self.save_button.clicked.connect(self.save_data)
|
||
self.load_ips_button.clicked.connect(self.load_ips)
|
||
self.load_all_button.clicked.connect(self.load_all_info)
|
||
self.prev_page_button.clicked.connect(self.prev_page)
|
||
self.next_page_button.clicked.connect(self.next_page)
|
||
|
||
# 将按钮加入布局
|
||
button_layout.addWidget(self.select_all_button)
|
||
button_layout.addWidget(self.select_none_button)
|
||
button_layout.addWidget(self.get_version_button)
|
||
button_layout.addWidget(self.get_mac_button)
|
||
button_layout.addWidget(self.upgrade_button)
|
||
button_layout.addWidget(self.load_ips_button)
|
||
button_layout.addWidget(self.load_all_button)
|
||
button_layout.addWidget(self.save_button)
|
||
button_layout.addWidget(self.prev_page_button)
|
||
button_layout.addWidget(self.next_page_button)
|
||
|
||
# 将表格和按钮布局添加到主布局
|
||
main_layout.addWidget(self.table_widget)
|
||
main_layout.addLayout(button_layout)
|
||
|
||
# 设置对话框的布局
|
||
self.setLayout(main_layout)
|
||
|
||
# 允许最大化
|
||
# self.setWindowState(Qt.WindowMaximized)
|
||
|
||
def select_all(self):
|
||
for row in range(self.table_widget.rowCount()):
|
||
item = self.table_widget.item(row, 0)
|
||
item.setCheckState(2) # 选中
|
||
|
||
def select_none(self):
|
||
for row in range(self.table_widget.rowCount()):
|
||
item = self.table_widget.item(row, 0)
|
||
item.setCheckState(0) # 未选中
|
||
|
||
def get_version(self):
|
||
print("获取版本按钮被点击")
|
||
|
||
def get_mac(self):
|
||
print("获取MAC按钮被点击")
|
||
|
||
def upgrade_node(self):
|
||
print("升级节点按钮被点击")
|
||
|
||
def save_data(self):
|
||
# 打开文件保存对话框
|
||
options = QFileDialog.Options()
|
||
file_path, _ = QFileDialog.getSaveFileName(self, "保存表数据", "", "CSV Files (*.csv);;All Files (*)", options=options)
|
||
if file_path:
|
||
# 保存表格数据到CSV文件
|
||
with open(file_path, mode='w', newline='', encoding='utf-8') as file:
|
||
writer = csv.writer(file)
|
||
# 写入表头
|
||
headers = [self.table_widget.horizontalHeaderItem(i).text() for i in range(self.table_widget.columnCount())]
|
||
writer.writerow(headers[1:])
|
||
# 写入表格内容
|
||
for row in range(self.table_widget.rowCount()):
|
||
row_data = [self.table_widget.item(row, col).text() if self.table_widget.item(row, col) else ""
|
||
for col in
|
||
range(1, self.table_widget.columnCount())] # Start from col=1 to skip the first column
|
||
writer.writerow(row_data)
|
||
|
||
print(f"数据已保存到 {file_path}")
|
||
|
||
def load_ips(self):
|
||
# 打开文件选择对话框
|
||
options = QFileDialog.Options()
|
||
file_path, _ = QFileDialog.getOpenFileName(self, "选择IP地址文件", "", "Text Files (*.txt);;All Files (*)", options=options)
|
||
if file_path:
|
||
# 读取IP地址
|
||
with open(file_path, 'r') as file:
|
||
lines = file.readlines()
|
||
|
||
invalid_ips = []
|
||
for i, line in enumerate(lines):
|
||
ip = line.strip()
|
||
# 验证IP地址格式
|
||
if not self.validate_ip(ip):
|
||
invalid_ips.append(i + 1)
|
||
|
||
if invalid_ips:
|
||
# 如果有无效IP,弹出提示框
|
||
QMessageBox.warning(self, "错误", f"以下行的IP地址无效:{', '.join(map(str, invalid_ips))}")
|
||
else:
|
||
# 将IP地址加载到表格
|
||
self.table_widget.setRowCount(len(lines))
|
||
for i, line in enumerate(lines):
|
||
ip = line.strip()
|
||
if i < self.table_widget.rowCount():
|
||
self.table_widget.setItem(i, 1, QTableWidgetItem(ip)) # 设置IP地址列
|
||
print(f"加载了{len(lines)}个IP地址")
|
||
|
||
def validate_ip(self, ip):
|
||
# IP地址验证正则表达式
|
||
import re
|
||
pattern = r"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
|
||
return bool(re.match(pattern, ip))
|
||
|
||
def load_all_info(self):
|
||
# 打开CSV文件选择对话框
|
||
options = QFileDialog.Options()
|
||
file_path, _ = QFileDialog.getOpenFileName(self, "选择CSV文件", "", "CSV Files (*.csv);;All Files (*)",
|
||
options=options)
|
||
if file_path:
|
||
# 读取CSV文件
|
||
with open(file_path, mode='r', encoding='utf-8') as file:
|
||
reader = csv.reader(file)
|
||
headers = next(reader) # 跳过表头
|
||
self.data = [row for row in reader]
|
||
if len(self.data) <= 20:
|
||
self.table_widget.setRowCount(len(self.data))
|
||
# 确保加载数据后更新分页
|
||
self.current_page = 0 # 每次加载新数据,默认回到第一页
|
||
self.update_table()
|
||
|
||
def update_table(self):
|
||
# 获取当前页的数据
|
||
start_row = self.current_page * self.rows_per_page
|
||
end_row = start_row + self.rows_per_page
|
||
rows_to_display = self.data[start_row:end_row]
|
||
|
||
# 更新表格内容
|
||
for row_num, row_data in enumerate(rows_to_display):
|
||
for col_num, cell_data in enumerate(row_data):
|
||
self.table_widget.setItem(row_num, col_num + 1, QTableWidgetItem(cell_data)) # +1跳过“选择”列
|
||
|
||
# 根据数据量调整上一页和下一页按钮的状态
|
||
self.prev_page_button.setEnabled(self.current_page > 0)
|
||
self.next_page_button.setEnabled((self.current_page + 1) * self.rows_per_page < len(self.data))
|
||
|
||
def prev_page(self):
|
||
if self.current_page > 0:
|
||
self.current_page -= 1
|
||
self.update_table()
|
||
|
||
def next_page(self):
|
||
if (self.current_page + 1) * self.rows_per_page < len(self.data):
|
||
self.current_page += 1
|
||
self.update_table()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
app = QApplication(sys.argv)
|
||
dialog = BatchOperationDialog()
|
||
dialog.show()
|
||
sys.exit(app.exec_())
|