12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133 |
- # ///////////////////////////////////////////////////////////////
- #
- # BY: WANDERSON M.PIMENTA
- # PROJECT MADE WITH: Qt Designer and PySide6
- # V: 1.0.0
- #
- # This project can be used freely for all uses, as long as they maintain the
- # respective credits only in the Python scripts, any information in the visual
- # interface (GUI) can be modified without any implication.
- #
- # There are limitations on Qt licenses if you want to use your products
- # commercially, I recommend reading them on the official website:
- # https://doc.qt.io/qtforpython/licenses.html
- #
- # ///////////////////////////////////////////////////////////////
- import time
-
- from PySide6.QtTest import QTest
- from PySide6.QtWidgets import QFileDialog, QWidget, QVBoxLayout, QTreeWidget, QApplication, QTreeWidgetItem
- from PySide6.QtCore import Signal, Qt, Slot, QObject
- from PySide6.QtSql import QSqlTableModel, QSqlDatabase
- from watchdog.observers import Observer
- from watchdog.events import FileSystemEventHandler
- import sqlite3
- from PySide6.QtGui import QIcon
-
- import sys
- import os
- import platform
-
- import Back.Program_Run.database_operations
- from Back.GC.GCExport import main_function_example
- # IMPORT / GUI AND MODULES AND WIDGETS
- # ///////////////////////////////////////////////////////////////
- from modules import *
- from widgets import *
-
- os.environ["QT_FONT_DPI"] = "96" # FIX Problem for High DPI and Scale above 100%
-
- # SET AS GLOBAL WIDGETS
- # ///////////////////////////////////////////////////////////////
- widgets = None
- excelname = ''
-
- # 获取项目根目录
- project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
- # 将项目根目录添加到 sys.path
- sys.path.append(project_root)
-
-
- # 表格的模型
- class MyTableModel(QAbstractTableModel):
- def __init__(self, data):
- super().__init__()
- self._data = data
-
- # 重新定义行数
- def rowCount(self, parent=QModelIndex()):
- return len(self._data)
-
- # 重新定义列数
- def columnCount(self, parent=QModelIndex()):
- return len(self._data[0]) if self._data else 0
-
- # 重新定义数据
- def data(self, index, role=Qt.DisplayRole):
- if not index.isValid():
- return None
- if role == Qt.DisplayRole:
- return self._data[index.row()][index.column()]
- return None
-
-
- # 数据一览树状
- class TreeWidgetItem:
- def __init__(self, id: any, parent_id: any, name: str, icon: QIcon = None, extend: object = None):
- """
- 菜单数据接口
- :param id: ID
- :param parent_id: 父ID
- :param name: 菜单名称
- :param icon: 图标
- :param extend: 扩展数据
- """
- self.id: any = id
- self.parent_id: any = parent_id
- self.name: str = name
- self.extend: object = extend
- # 实例化
- self.treeWidgetItem = QTreeWidgetItem([self.name])
- # 存储相关数据
- self.treeWidgetItem.setData(0, Qt.UserRole + 1, extend)
- self.treeWidgetItem.setIcon(0, QIcon(':/icons/default.png'))
- if icon is not None:
- self.treeWidgetItem.setIcon(0, icon)
-
-
- class ElTreeData(QObject):
- """
- Data Model
- """
- items_changed: Signal = Signal(str)
- styleSheet_changed: Signal = Signal(str)
-
- def __init__(self, items: list[TreeWidgetItem] = None, styleSheet: str = None):
- super(ElTreeData, self).__init__()
- # 定义数据
- self._items: list[TreeWidgetItem]
- self._styleSheet: str
- # 初始化数据
- self.items = items
- self.styleSheet = styleSheet
-
- @property
- def items(self):
- return self._items
-
- @items.setter
- def items(self, value):
- self._items = value
- # 数据改变时发出信号
- self.items_changed.emit(self.items)
-
- @property
- def styleSheet(self):
- return self._styleSheet
-
- @styleSheet.setter
- def styleSheet(self, value):
- self._styleSheet = value
- # 数据改变时发出信号
- self.styleSheet_changed.emit(self.styleSheet)
-
-
- # 全数据库
- class ElTree(QWidget):
- """
- Control
- """
- itemClicked: Signal = Signal(object)
- itemDoubleClicked: Signal = Signal(object)
-
- def __init__(self, treeData: ElTreeData, parent=None):
- super(ElTree, self).__init__(parent=parent)
-
- self.data = treeData
- # 将按钮的点击信号绑定到当前类的点击信号
- widgets.allTreeWidget.itemClicked.connect(lambda item: self.itemClicked.emit(item.data(0, Qt.UserRole + 1)))
- widgets.allTreeWidget.itemDoubleClicked.connect(
- lambda item: self.itemDoubleClicked.emit(item.data(0, Qt.UserRole + 1)))
- self.__render_items(True)
-
- # 设置 QTreeWidget 的 contextMenuPolicy 为 Qt.CustomContextMenu
- widgets.allTreeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
- # 连接 customContextMenuRequested 信号到 contextMenuEvent 方法
- widgets.allTreeWidget.customContextMenuRequested.connect(self.contextMenuEvent)
-
- def __render_items(self, is_clear: bool):
- if is_clear:
- widgets.allTreeWidget.clear()
- widgets.qureyTreeWidget.clear()
- widgets.allTreeWidget.setColumnCount(1)
- widgets.allTreeWidget.setHeaderHidden(True)
- widgets.qureyTreeWidget.setColumnCount(1)
- widgets.qureyTreeWidget.setHeaderHidden(True)
- if self.data.items is not None:
- # 转为字典
- mapping: dict[any, TreeWidgetItem] = dict(zip([i.id for i in self.data.items], self.data.items))
- # 树容器
- treeWidgetItems: list[QTreeWidgetItem] = []
- for d in self.data.items:
- # 如果找不到父级项,则是根节点
- parent: TreeWidgetItem = mapping.get(d.parent_id)
- if parent is None:
- treeWidgetItems.append(d.treeWidgetItem)
- else:
- parent.treeWidgetItem.addChild(d.treeWidgetItem)
-
- # 挂载到树上
- widgets.allTreeWidget.insertTopLevelItems(0, treeWidgetItems)
-
- def contextMenuEvent(self, pos):
- # 创建右键菜单
- context_menu = QMenu(self)
-
- # 添加删除选项
- delete_action = QAction("删除", self)
- delete_action.triggered.connect(self.delete_item)
- context_menu.addAction(delete_action)
-
- # 添加导出选项
- export_action = QAction("导出", self)
- export_action.triggered.connect(self.export_item)
- context_menu.addAction(export_action)
-
- context_menu.exec(widgets.allTreeWidget.mapToGlobal(pos))
-
- def delete_item(self):
- # 获取当前选中的项目
- selected_items = widgets.allTreeWidget.selectedItems()
- if not selected_items:
- QMessageBox.warning(self, '警告', '请先选择一个项目')
- return
-
- item = selected_items[0]
- data = item.data(0, Qt.UserRole + 1)
- if not data:
- self.warning = QMessageBox.warning(self, '警告', '所选项目没有关联的数据')
- return
-
- # 获取数据库路径和表名
- dbname = data['listData'][0]
- tablename = data['listData'][2]
- dbpath = os.path.join(os.path.abspath('../SQL'), f"{dbname}.db")
-
- # 确保 tablename 是 UTF-8 编码的字符串
- try:
- tablename_utf8 = tablename.encode('utf-8')
- except Exception as e:
- QMessageBox.critical(self, '错误', f'表名编码转换错误: {str(e)}')
- return
- # 获取父节点
- parent_item = item.parent()
- if not parent_item:
- QMessageBox.warning(self, '警告', '所选项目没有父节点')
- return
-
- parent_name = parent_item.text(0)
-
- # 确定要删除的表
- tables_to_delete = []
- if parent_name == '水准测段高差稳定计算':
- tables_to_delete = ['GC_Input_Param', 'GC_Input_Point', 'GC_Output_Point']
- elif parent_name == '控制网复测平面基准计算':
- tables_to_delete = ['GS_Input_Param', 'GS_Input_Point', 'GS_Result_Point', 'GS_Trans_Param',
- 'GS_Trans_Point']
- elif parent_name == '平面控制网稳定性计算':
- tables_to_delete = ['WD_Input_Param', 'WD_Input_Point', 'WD_Result_Param', 'WD_Result_Point']
- else:
- QMessageBox.warning(self, '警告', '未知的父节点')
- return
-
- # 确认删除操作
- reply = QMessageBox.question(self, '确认删除', f'确定要删除项目表 {tablename} 吗?',
- QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
- if reply == QMessageBox.No:
- return
-
- # 清空表
- try:
- conn = sqlite3.connect(dbpath)
- cursor = conn.cursor()
- for table in tables_to_delete:
- cursor.execute(f"DELETE FROM {table} WHERE TableName = ?", (tablename_utf8,))
- conn.commit()
- conn.close()
- QMessageBox.information(self, '成功', f'表 {tablename} 中的数据已从相关表中删除')
-
- # 刷新树状图
- self.refresh_tree()
- except Exception as e:
- QMessageBox.critical(self, '错误', f'删除数据时出错: {str(e)}')
-
- def export_item(self):
- # 获取当前选中的项目
- selected_items = widgets.allTreeWidget.selectedItems()
- if not selected_items:
- QMessageBox.warning(self, '警告', '请先选择一个项目')
- return
-
- item = selected_items[0]
- data = item.data(0, Qt.UserRole + 1)
- if not data:
- QMessageBox.warning(self, '警告', '所选项目没有关联的数据')
- return
-
- # 获取数据库路径和表名
- dbname = data['listData'][0]
- tablename = data['listData'][2]
- tablename_utf8 = tablename.encode('utf-8')
- dbpath = os.path.join(os.path.abspath('../SQL'), f"{dbname}.db")
-
- # 获取父节点
- parent_item = item.parent()
- if not parent_item:
- QMessageBox.warning(self, '警告', '所选项目没有父节点')
- return
-
- parent_name = parent_item.text(0)
-
- # 根据父节点名称确定导出操作
- if parent_name == '水准测段高差稳定计算':
- GCExport.main_function_initial(self, tablename_utf8, dbpath)
- GCExport.main_function_result(self, tablename_utf8, dbpath)
- elif parent_name == '控制网复测平面基准计算':
- GSExport.main_function(self, dbpath, tablename)
- GSExport.main_function_initial(self, dbpath, tablename_utf8)
- elif parent_name == '平面控制网稳定性计算':
- WDExport.main_function(self, dbpath, tablename)
- WDExport.main_function_initial(self, dbpath, tablename_utf8)
- else:
- QMessageBox.warning(self, '警告', '未知的父节点')
- return
-
- def refresh_tree(self):
- # 调用 MainWindow 的 refresh_tree 方法
- main_window = QApplication.instance().activeWindow()
- if isinstance(main_window, MainWindow):
- main_window.refresh_tree()
-
-
- # 查询
- # 查询
- class ElTree1(QWidget):
- """
- Control
- """
- itemClicked: Signal = Signal(object)
- itemDoubleClicked: Signal = Signal(object)
-
- def __init__(self, treeData: ElTreeData, parent=None):
- super(ElTree1, self).__init__(parent=parent)
- self.data = treeData
- # 将按钮的点击信号绑定到当前类的点击信号
- widgets.qureyTreeWidget.itemClicked.connect(lambda item: self.itemClicked.emit(item.data(0, Qt.UserRole + 1)))
- widgets.qureyTreeWidget.itemDoubleClicked.connect(
- lambda item: self.itemDoubleClicked.emit(item.data(0, Qt.UserRole + 1)))
- self.__render_items(True)
-
- # 设置 QTreeWidget 的 contextMenuPolicy 为 Qt.CustomContextMenu
- widgets.qureyTreeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
- # 连接 customContextMenuRequested 信号到 contextMenuEvent 方法
- widgets.qureyTreeWidget.customContextMenuRequested.connect(self.contextMenuEvent)
-
- def __render_items(self, is_clear: bool):
- if is_clear:
- widgets.qureyTreeWidget.clear()
- widgets.qureyTreeWidget.setColumnCount(1)
- widgets.qureyTreeWidget.setHeaderHidden(True)
- if self.data.items is not None:
- # 转为字典
- mapping: dict[any, TreeWidgetItem] = dict(zip([i.id for i in self.data.items], self.data.items))
- # 树容器
- treeWidgetItems: list[QTreeWidgetItem] = []
- for d in self.data.items:
- # 如果找不到父级项,则是根节点
- parent: TreeWidgetItem = mapping.get(d.parent_id)
- if parent is None:
- treeWidgetItems.append(d.treeWidgetItem)
- else:
- parent.treeWidgetItem.addChild(d.treeWidgetItem)
-
- # 挂载到树上
- widgets.qureyTreeWidget.insertTopLevelItems(0, treeWidgetItems)
-
- def contextMenuEvent(self, pos):
- # 创建右键菜单
- context_menu = QMenu(self)
-
- # 添加删除选项
- delete_action = QAction("删除", self)
- delete_action.triggered.connect(self.delete_item)
- context_menu.addAction(delete_action)
-
- # 添加导出选项
- export_action = QAction("导出", self)
- export_action.triggered.connect(self.export_item)
- context_menu.addAction(export_action)
-
- context_menu.exec(widgets.qureyTreeWidget.mapToGlobal(pos))
-
- def delete_item(self):
- # 获取当前选中的项目
- selected_items = widgets.qureyTreeWidget.selectedItems()
- if not selected_items:
- QMessageBox.warning(self, '警告', '请先选择一个项目')
- return
-
- item = selected_items[0]
- data = item.data(0, Qt.UserRole + 1)
- if not data:
- self.warning = QMessageBox.warning(self, '警告', '所选项目没有关联的数据')
- return
-
- # 获取数据库路径和表名
- dbname = data['listData'][0]
- tablename = data['listData'][2]
- dbpath = os.path.join(os.path.abspath('../SQL'), f"{dbname}.db")
-
- # 确保 tablename 是 UTF-8 编码的字符串
- try:
- tablename_utf8 = tablename.encode('utf-8')
- except Exception as e:
- QMessageBox.critical(self, '错误', f'表名编码转换错误: {str(e)}')
- return
- # 获取父节点
- parent_item = item.parent()
- if not parent_item:
- QMessageBox.warning(self, '警告', '所选项目没有父节点')
- return
-
- parent_name = parent_item.text(0)
-
- # 确定要删除的表
- tables_to_delete = []
- if parent_name == '水准测段高差稳定计算':
- tables_to_delete = ['GC_Input_Param', 'GC_Input_Point', 'GC_Output_Point']
- elif parent_name == '控制网复测平面基准计算':
- tables_to_delete = ['GS_Input_Param', 'GS_Input_Point', 'GS_Result_Point', 'GS_Trans_Param',
- 'GS_Trans_Point']
- elif parent_name == '平面控制网稳定性计算':
- tables_to_delete = ['WD_Input_Param', 'WD_Input_Point', 'WD_Result_Param', 'WD_Result_Point']
- else:
- QMessageBox.warning(self, '警告', '未知的父节点')
- return
-
- # 确认删除操作
- reply = QMessageBox.question(self, '确认删除', f'确定要删除项目表 {tablename} 吗?',
- QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
- if reply == QMessageBox.No:
- return
-
- # 清空表
- try:
- conn = sqlite3.connect(dbpath)
- cursor = conn.cursor()
- for table in tables_to_delete:
- cursor.execute(f"DELETE FROM {table} WHERE TableName = ?", (tablename_utf8,))
- conn.commit()
- conn.close()
- QMessageBox.information(self, '成功', f'表 {tablename} 中的数据已从相关表中删除')
-
- # 刷新树状图
- self.refresh_tree()
- # 模拟点击 Enter 键 实现程序自动刷新的效果
- QTest.keyClick(widgets.qureyTreeWidget, Qt.Key_Return)
- except Exception as e:
- QMessageBox.critical(self, '错误', f'删除数据时出错: {str(e)}')
-
- def export_item(self):
- # 获取当前选中的项目
- selected_items = widgets.qureyTreeWidget.selectedItems()
- if not selected_items:
- QMessageBox.warning(self, '警告', '请先选择一个项目')
- return
-
- item = selected_items[0]
- data = item.data(0, Qt.UserRole + 1)
- if not data:
- QMessageBox.warning(self, '警告', '所选项目没有关联的数据')
- return
-
- # 获取数据库路径和表名
- dbname = data['listData'][0]
- tablename = data['listData'][2]
- tablename_utf8 = tablename.encode('utf-8')
- dbpath = os.path.join(os.path.abspath('../SQL'), f"{dbname}.db")
-
- # 获取父节点
- parent_item = item.parent()
- if not parent_item:
- QMessageBox.warning(self, '警告', '所选项目没有父节点')
- return
-
- parent_name = parent_item.text(0)
-
- # 根据父节点名称确定导出操作
- if parent_name == '水准测段高差稳定计算':
- GCExport.main_function_initial(self, tablename_utf8, dbpath) # 导出初始文件
- GCExport.main_function_result(self, tablename_utf8, dbpath) # 导出结果文件
- elif parent_name == '控制网复测平面基准计算':
- GSExport.main_function(self, dbpath, tablename) # 导出结果文件
- GSExport.main_function_initial(self, dbpath, tablename_utf8) # 导出初始文件
- elif parent_name == '平面控制网稳定性计算':
- WDExport.main_function(self, dbpath, tablename) # 导出结果文件
- WDExport.main_function_initial(self, dbpath, tablename_utf8) # 导出初始文件
- else:
- QMessageBox.warning(self, '警告', '未知的父节点')
- return
-
- def refresh_tree(self):
- # 调用 MainWindow 的 refresh_tree 方法
- main_window = QApplication.instance().activeWindow()
- if isinstance(main_window, MainWindow):
- main_window.refresh_tree()
-
-
- # class DatabaseChangeHandler(FileSystemEventHandler):
- # def __init__(self, main_window):
- # self.main_window = main_window
- #
- # def on_modified(self, event):
- # # 忽略 .db-journal 文件的变化
- # if event.src_path.endswith('.db-journal'):
- # return
- # if event.src_path.endswith('.db'):
- # self.main_window.refresh_tree()
-
-
- class MainWindow(QMainWindow):
-
- def __init__(self):
- QMainWindow.__init__(self)
- self.file_path = None # 初始化时文件路径设置为None
- # super().__init__()
- # SET AS GLOBAL WIDGETS
- # ///////////////////////////////////////////////////////////////
- self.ui = Ui_MainWindow()
- self.ui.setupUi(self)
- # 连接信号与槽函数,实现点击操作
- self.ui.createFile.clicked.connect(self.on_create_file_clicked)
- self.ui.export_2.clicked.connect(self.on_export_2_clicked)
- # 初始化数据库监控
- # self.observer = Observer()
- # self.observer.schedule(DatabaseChangeHandler(self), path=os.path.abspath('../SQL'), recursive=False)
- # self.observer.start()
- # self.comboBox_2 = QComboBox(self)
- # ...此处为省略代码...
- global widgets
- widgets = self.ui
- widgets.search.clicked.connect(self.buttonClick)
- # 设置 datainfo 页面的焦点策略,使其能够捕获键盘事件
- widgets.datainfo.setFocusPolicy(Qt.StrongFocus)
- widgets.datainfo.keyPressEvent = self.datainfo_keyPressEvent
- # 是否使用系统自带标题栏 True是不使用,False使用
- # ///////////////////////////////////////////////////////////////
- Settings.ENABLE_CUSTOM_TITLE_BAR = True
-
- # APP名称
- # ///////////////////////////////////////////////////////////////
- title = "控制网复测平面基准归算程序"
- description = "控制网复测平面基准归算程序"
- # APPLY TEXTS
- self.setWindowTitle(title)
- widgets.titleRightInfo.setText(description)
-
- # TOGGLE MENU
- # ///////////////////////////////////////////////////////////////
- widgets.toggleButton.clicked.connect(lambda: UIFunctions.toggleMenu(self, True))
-
- # SET UI DEFINITIONS
- # ///////////////////////////////////////////////////////////////
- UIFunctions.uiDefinitions(self)
-
- # QTableWidget PARAMETERS
- # ///////////////////////////////////////////////////////////////
- # widgets.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
-
- # 点击事件
- # ///////////////////////////////////////////////////////////////
-
- # 左边菜单
- # 首页
- widgets.btn_home.clicked.connect(self.buttonClick)
- # 输入表格
- widgets.btn_widgets.clicked.connect(self.buttonClick)
- # 成果预览
- widgets.btn_new.clicked.connect(self.buttonClick)
- # 数据一览
- widgets.btn_data.clicked.connect(self.buttonClick)
- # 皮肤切换
- widgets.btn_message.clicked.connect(self.buttonClick)
- # 打开上传文件夹
- widgets.upload.clicked.connect(self.buttonClick)
- # 文件计算
- widgets.compute.clicked.connect(self.buttonClick)
- # 数据一览的搜索键
- widgets.search.clicked.connect(self.buttonClick)
-
- # 拓展左侧栏
- # def openCloseLeftBox():
- # UIFunctions.toggleLeftBox(self, True)
- # widgets.toggleLeftBox.clicked.connect(openCloseLeftBox)
- # widgets.extraCloseColumnBtn.clicked.connect(openCloseLeftBox)
-
- # EXTRA RIGHT BOX
- def openCloseRightBox():
- UIFunctions.toggleRightBox(self, True)
-
- widgets.settingsTopBtn.clicked.connect(openCloseRightBox)
-
- # 展示APP
- # ///////////////////////////////////////////////////////////////
- self.show()
-
- # 设置主题
- # ///////////////////////////////////////////////////////////////
- if getattr(sys, 'frozen', False):
- absPath = os.path.dirname(os.path.abspath(sys.executable))
- elif __file__:
- absPath = os.path.dirname(os.path.abspath(__file__))
- useCustomTheme = True
- self.useCustomTheme = useCustomTheme
- self.absPath = absPath
- themeFile = r"themes\py_dracula_light.qss"
-
- # 设置主题和HACKS
- if useCustomTheme:
- # LOAD AND APPLY STYLE
- UIFunctions.theme(self, themeFile, True)
-
- # SET HACKS
- AppFunctions.setThemeHack(self)
-
- # 设置主页和选择菜单
- # ///////////////////////////////////////////////////////////////
- widgets.stackedWidget.setCurrentWidget(widgets.home)
- widgets.btn_home.setStyleSheet(UIFunctions.selectMenu(widgets.btn_home.styleSheet()))
- # self.bind()
-
- # # 初始化树状数据库
- # self.refresh_tree()
-
- # tree_button = self.sql_init()
- # tree_button.itemClicked.connect(self.itembuttonClick)
- # tree_button.itemDoubleClicked.connect(self.itembuttonClick)
-
- # 单元格的右键
- def show_custom_context_menu(self, pos):
- # 创建一个右键菜单
- menu = QMenu(self.ui.resultTableView1)
- menu.setStyleSheet("QMenu { background-color: #FFFFFF; }")
- # 获取选中单元格的索引
- index = self.ui.resultTableView1.indexAt(pos)
- # # 添加菜单项和对应的操作
- # action_1 = QAction("操作1", self)
- # action_1.triggered.connect(lambda: self.do_something(index))
- # menu.addAction(action_1)
- # 添加菜单项和对应的操作
- action_1 = QAction("删除该行", self)
- action_1.triggered.connect(self.del_Dataclicked)
- menu.addAction(action_1)
- action_2 = QAction("编辑单元格", self)
- action_2.triggered.connect(self.edit_dataclicked)
- menu.addAction(action_2)
- action_3 = QAction("添加数据", self)
- action_3.triggered.connect(self.add_Dataclicked)
- menu.addAction(action_3)
- menu.exec(self.ui.resultTableView1.mapToGlobal(pos))
-
- # def closeEvent(self, event):
- # # 停止监控
- # self.observer.stop()
- # self.observer.join()
- # event.accept()
-
- # 绑定组件
- def bind(self):
- # 计算
- widgets.compute.clicked.connect(self.buttonClick)
-
- # 删除tableview
- def delete_table_view(table_view):
- table_view.setParent(None)
- table_view.deleteLater()
-
- # ///////////////////////////////////////////////////////////////
- def buttonClick(self):
- # GET BUTTON CLICKED
- btn = self.sender()
- btnName = btn.objectName()
-
- # 首页
- if btnName == "btn_home":
- widgets.stackedWidget.setCurrentWidget(widgets.home)
- UIFunctions.resetStyle(self, btnName)
- btn.setStyleSheet(UIFunctions.selectMenu(btn.styleSheet()))
-
- # 输入表格
- if btnName == "btn_widgets":
- widgets.stackedWidget.setCurrentWidget(widgets.widgets)
- UIFunctions.resetStyle(self, btnName)
- btn.setStyleSheet(UIFunctions.selectMenu(btn.styleSheet()))
-
- # 成果预览
- if btnName == "btn_new":
- widgets.stackedWidget.setCurrentWidget(widgets.new_page) # SET PAGE
- UIFunctions.resetStyle(self, btnName) # RESET ANOTHERS BUTTONS SELECTED
- btn.setStyleSheet(UIFunctions.selectMenu(btn.styleSheet())) # SELECT MENU
-
- # 数据一览
- if btnName == "btn_data":
- # 初始化树状数据库
- self.refresh_tree()
- widgets.stackedWidget.setCurrentWidget(widgets.datainfo) # SET PAGE
- UIFunctions.resetStyle(self, btnName) # RESET ANOTHERS BUTTONS SELECTED
- btn.setStyleSheet(UIFunctions.selectMenu(btn.styleSheet())) # SELECT MENU
-
- # 皮肤切换
- if btnName == "btn_message":
- if self.useCustomTheme:
- themeFile = os.path.abspath(os.path.join(self.absPath, "themes/py_dracula_dark.qss"))
- UIFunctions.theme(self, themeFile, True)
- # SET HACKS
- AppFunctions.setThemeHack(self)
- self.useCustomTheme = False
- else:
- themeFile = os.path.abspath(os.path.join(self.absPath, "themes/py_dracula_light.qss"))
- UIFunctions.theme(self, themeFile, True)
- # SET HACKS
- AppFunctions.setThemeHack(self)
- self.useCustomTheme = True
- # 文件上传
- if btnName == "upload":
- # 使用 QFileDialog 获取文件路径
- file_path, _ = QFileDialog.getOpenFileName(
- self,
- "选择文件",
- "",
- "表格文件 (*.xls *.xlsx)"
- # 水准后期添加支持.xls文件
- )
- if file_path:
- # 处理选中的文件
- self.file_path = file_path # 将获取的路径保存到类的属性中
- UIFunctions.execute_script_based_on_selection(self, file_path)
-
- # 文件计算
- if btnName == "compute":
- if self.file_path: # 确保有文件路径后再进行处理
- # 计算与展示的业务代码
- UIFunctions.compute_show_process_excel_file(self, self.file_path)
- # 1秒后自动跳转
- QTimer.singleShot(1000, lambda: self.simulateButtonClick("btn_new"))
- else:
- QMessageBox.warning(self, '警告', '请先选择项目并上传文件')
-
- # 树状查询
- if btnName == "search":
- self.searchClick()
-
- # 输出点击回馈
- print(f'Button "{btnName}" pressed!')
-
- # 辅助函数,点击计算后自动跳转页面
- def simulateButtonClick(self, btnName):
- # 根据按钮名称找到对应的按钮
- btn = self.findChild(QObject, btnName)
- if btn:
- # 触发按钮点击事件
- btn.click()
-
- # 新增槽函数来调用 create_database_and_tables
- def on_create_file_clicked(self):
- Back.Program_Run.database_operations.create_database_and_tables(self, self.ui)
-
- # 定义导出数据库的槽函数
- def on_export_2_clicked(self):
- if self.file_path:
- UIFunctions.export_database_to_excel(self, self.file_path)
- else:
- QMessageBox.warning(self, '警告', '请先选择项目并上传文件')
-
- # RESIZE EVENTS
- # ///////////////////////////////////////////////////////////////
- def resizeEvent(self, event):
- # Update Size Grips
- UIFunctions.resize_grips(self)
-
- # 鼠标点击事件
- # ///////////////////////////////////////////////////////////////
- def mousePressEvent(self, event):
- # SET DRAG POS WINDOW
- # self.dragPos = event.globalPos()
- self.dragPos = event.globalPosition().toPoint() # 设置鼠标拖动位置
-
- # 输出鼠标事件
- if event.buttons() == Qt.LeftButton:
- print('Mouse click: LEFT CLICK')
- if event.buttons() == Qt.RightButton:
- print('Mouse click: RIGHT CLICK')
-
- # 设一个全局变量,存数据库中所有的包含内容(数据库-三种方法-表)
- dblist = []
-
- # 初始化数据一览(数据库全展示)
- def sql_init(self):
- # 清空 dblist 以确保每次初始化时都是空的
- self.dblist = []
- # 初始化全部数据库
- # inpath = r'D:\4work_now\20240819GS\20241211\SQL'
- inpath = os.path.abspath('../SQL')
- # 读取所有的数据库名
- sqlitem = []
- id = 1
- for filename in os.listdir(inpath):
- # 数据库
- dbname = filename.split('.', -1)[0]
- dbpath = os.path.join(inpath, filename)
- sqlitem.append(TreeWidgetItem(id, 0, dbname, icon=QIcon(
- os.path.abspath(os.path.join(self.absPath, "images/icons/cil-clone.png")))))
- pid = id
- id = id + 1
- # 三种方法
- sqlitem.append(TreeWidgetItem(id, pid, '水准测段高差稳定计算', icon=QIcon(
- os.path.join(self.absPath, "images/icons/cil-description.png"))))
- gcid = id
- id = id + 1
- sqlitem.append(TreeWidgetItem(id, pid, '控制网复测平面基准计算', icon=QIcon(
- os.path.join(self.absPath, "images/icons/cil-description.png"))))
- gsid = id
- id = id + 1
- sqlitem.append(TreeWidgetItem(id, pid, '平面控制网稳定性计算', icon=QIcon(
- os.path.join(self.absPath, "images/icons/cil-description.png"))))
- wdid = id
- id = id + 1
- # 读取所有的表名(三种方式往下)
- db1 = sqlite3.connect(dbpath)
- # 获取游标
- cursor1 = db1.cursor()
- sqlstr1 = 'SELECT TableName FROM GC_Input_Param;'
- cursor1.execute(sqlstr1)
- result1 = cursor1.fetchall()
- for re1 in result1:
- str1 = re1[0].decode('utf-8')
- list1 = []
- list1.append(dbname)
- list1.append('水准测段高差稳定计算')
- list1.append(str1)
- self.dblist.append(list1)
- sqlitem.append(TreeWidgetItem(id, gcid, str1, icon=QIcon(
- os.path.join(self.absPath, "images/icons/cil-file.png")), extend={'listData': list1}))
- id = id + 1
- sqlstr2 = 'SELECT TableName FROM GS_Input_Param;'
- cursor1.execute(sqlstr2)
- result2 = cursor1.fetchall()
- for re2 in result2:
- str2 = re2[0].decode('utf-8')
- list2 = []
- list2.append(dbname)
- list2.append('控制网复测平面基准计算')
- list2.append(str2)
- self.dblist.append(list2)
- sqlitem.append(TreeWidgetItem(id, gsid, str2,
- icon=QIcon(os.path.join(self.absPath, "images/icons/cil-file.png")),
- extend={'listData': list2}))
- id = id + 1
- sqlstr3 = 'SELECT TableName FROM WD_Input_Param;'
- cursor1.execute(sqlstr3)
- result3 = cursor1.fetchall()
- for re3 in result3:
- str3 = re3[0].decode('utf-8')
- list3 = []
- list3.append(dbname)
- list3.append('平面控制网稳定性计算')
- list3.append(str3)
- self.dblist.append(list3)
- sqlitem.append(TreeWidgetItem(id, wdid, str3,
- icon=QIcon(os.path.join(self.absPath, "images/icons/cil-file.png")),
- extend={'listData': list3}))
- id = id + 1
- button = ElTree(ElTreeData(sqlitem))
- return button
-
- # 刷新树状图
- def refresh_tree(self):
- # 清空当前的树状图
- widgets.allTreeWidget.clear()
- # 重新初始化树状图
- tree_button = self.sql_init()
- tree_button.itemClicked.connect(self.itembuttonClick)
- tree_button.itemDoubleClicked.connect(self.itembuttonClick)
-
- # 关键词查询
- def searchClick(self):
- # GET BUTTON CLICKED
- btn = self.sender()
- btnName = btn.objectName()
- # 获取文本
- text1 = self.ui.lineEdit_2.text()
- # 符合的list
- fhlist = []
- # 查询(待优化)
- for list1 in self.dblist:
- for li in list1:
- if text1 in li:
- fhlist.append(list1)
- break
- # 更新item值
- sqlitem = []
- # 前两层是否一致
- str1 = ''
- str2 = ''
- id = 1
- pid = 0
- fid = 0
- zdy = []
- for list2 in fhlist:
- dbname = list2[0]
- if dbname != str1:
- str1 = dbname
- pid = id
- str2 = ''
- sqlitem.append(TreeWidgetItem(id, 0, dbname, icon=QIcon(
- os.path.join(self.absPath, "images/icons/cil-clone.png"))))
- zdy1 = []
- zdy1.append(id)
- zdy1.append(0)
- zdy1.append(dbname)
- zdy.append(zdy1)
- id = id + 1
- mename = list2[1]
- if mename != str2:
- str2 = mename
- fid = id
- sqlitem.append(TreeWidgetItem(id, pid, mename, icon=QIcon(
- os.path.join(self.absPath, "images/icons/cil-description.png"))))
- zdy1 = []
- zdy1.append(id)
- zdy1.append(pid)
- zdy1.append(mename)
- zdy.append(zdy1)
- id = id + 1
- sqlitem.append(TreeWidgetItem(id, fid, list2[2], icon=QIcon(
- os.path.join(self.absPath, "images/icons/cil-file.png")), extend={'listData': list2}))
- zdy1 = []
- zdy1.append(id)
- zdy1.append(fid)
- zdy1.append(list2[2])
- zdy.append(zdy1)
- id = id + 1
- search_button = ElTree1(ElTreeData(sqlitem))
- search_button.itemClicked.connect(self.itembuttonClick1)
- search_button.itemDoubleClicked.connect(self.itembuttonClick1)
- # 隐藏默认label
- self.ui.defaultLabel.setVisible(False)
- #清空搜索框内容
- self.ui.lineEdit_2.clear()
-
- # 全树的item展示
- def itembuttonClick(self):
- # 判定是否获取的是根节点
- pd = 1
- select_item = self.ui.allTreeWidget.currentItem()
- # 获取点击的item的text和它对应的上两个节点
- str1 = select_item.text(0)
- current_text = '' # 初始化 current_text
- str3 = '' # 初始化 str3
- try:
- pa_item = select_item.parent()
- current_text = pa_item.text(0)
- z_item = pa_item.parent()
- str3 = z_item.text(0)
- except:
- pd = -1
- if current_text == '':
- pd = -1
- if str3 == '':
- pd = -1
- if pd == -1:
- pass
- else:
- # 数据库目录
- inpath = os.path.abspath('../SQL')
- file_path = inpath + '/' + str3 + '.db'
- # 数据库路径,哪种方法,表名
- self.selectModel = UIFunctions.search_data_to_show(self, file_path, current_text, str1)
- # self.ui.resultTableView1.doubleClicked.connect(self.seleceModel_itemclicked)
-
- # 设置右键菜单策略为CustomContextMenu
- self.ui.resultTableView1.setContextMenuPolicy(Qt.CustomContextMenu)
-
- # 关联自定义的右键菜单方法到customContextMenuRequested信号
- self.ui.resultTableView1.customContextMenuRequested.connect(self.show_custom_context_menu)
-
- # 搜索的item展示
- def itembuttonClick1(self):
- # 判定是否获取的是根节点
- pd = 1
- select_item = self.ui.qureyTreeWidget.currentItem()
- # 获取点击的item的text和它对应的上两个节点
- str1 = select_item.text(0)
- current_text = '' # 初始化 current_text
- str3 = '' # 初始化 str3
- try:
- pa_item = select_item.parent()
- current_text = pa_item.text(0)
- z_item = pa_item.parent()
- str3 = z_item.text(0)
- except:
- pd = -1
- if current_text == '':
- pd = -1
- if str3 == '':
- pd = -1
- if pd == -1:
- pass
- else:
- # 数据库目录
- inpath = os.path.abspath('../SQL')
- file_path = inpath + '/' + str3 + '.db'
- # 数据库路径,哪种方法,表名
- self.selectModel = UIFunctions.search_data_to_show(self, file_path, current_text, str1)
- # self.ui.resultTableView1.doubleClicked.connect(self.seleceModel_itemclicked)
-
- # 设置右键菜单策略为CustomContextMenu
- self.ui.resultTableView1.setContextMenuPolicy(Qt.CustomContextMenu)
-
- # 关联自定义的右键菜单方法到customContextMenuRequested信号
- self.ui.resultTableView1.customContextMenuRequested.connect(self.show_custom_context_menu)
-
- # 键盘回车事件,目前用于搜索按钮
- def datainfo_keyPressEvent(self, event):
- if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
- # 检查 lineEdit_2 中是否有内容
- if widgets.lineEdit_2.text():
- # 模拟 search 按钮点击事件
- self.ui.search.click()
- #用于编辑完成操作
- else:
- self.update_dataclicked()
- else:
- # 调用默认的 keyPressEvent 处理其他按键事件
- super(widgets.datainfo.__class__, widgets.datainfo).keyPressEvent(event)
-
- # 右键对应行可删除对应行
- def del_Dataclicked(self):
- select_item = self.ui.allTreeWidget.currentItem()
- if select_item == None:
- select_item = self.ui.qureyTreeWidget.currentItem()
- # 获取数据库路径和表名
- tablename = select_item.text(0)
- tablename_utf8 = tablename.encode('utf-8')
- # 获取父节点
- parent_item = select_item.parent()
- parent_name = parent_item.text(0)
- dbname = parent_item.parent().text(0)
- dbpath = os.path.join(os.path.abspath('../SQL'), f"{dbname}.db")
- curIndex = self.selectModel.currentIndex()
- # self.ui.resultTableView1.model().removeRow(curIndex.row())
- col = curIndex.column()
- row = curIndex.row()
- # 重新组织表的内容,方便重新计算
- UIFunctions.del_row_from_db(self, row, parent_name, tablename_utf8, dbpath)
- # 1秒后自动跳转
- QTimer.singleShot(1000, lambda: self.simulateButtonClick("btn_new"))
- # 刷新树和tableview
- self.refresh_tree()
-
- # 数据库路径,哪种方法,表名
- self.selectModel = UIFunctions.search_data_to_show(self, dbpath, parent_name, tablename)
- # self.ui.resultTableView1.doubleClicked.connect(self.seleceModel_itemclicked)
-
- # 设置右键菜单策略为CustomContextMenu
- self.ui.resultTableView1.setContextMenuPolicy(Qt.CustomContextMenu)
-
- # 关联自定义的右键菜单方法到customContextMenuRequested信号
- self.ui.resultTableView1.customContextMenuRequested.connect(self.show_custom_context_menu)
-
- def update_dataclicked(self):
- inputmodel = self.ui.resultTableView1.model()
- #转化为list
- list1 = []
- ii = 0
- while ii < inputmodel.rowCount():
- list2 = []
- jj = 0
- while jj < inputmodel.columnCount():
- index1 = inputmodel.index(ii,jj)
- list2.append(inputmodel.data(index1))
- jj = jj + 1
- list1.append(list2)
- ii = ii + 1
- #读取对应的db和方法
- select_item = self.ui.allTreeWidget.currentItem()
- if select_item == None:
- select_item = self.ui.qureyTreeWidget.currentItem()
- # 获取数据库路径和表名
- tablename = select_item.text(0)
- tablename_utf8 = tablename.encode('utf-8')
- # 获取父节点
- parent_item = select_item.parent()
- parent_name = parent_item.text(0)
- dbname = parent_item.parent().text(0)
- dbpath = os.path.join(os.path.abspath('../SQL'), f"{dbname}.db")
- # 重新组织表的内容,方便重新计算
- UIFunctions.update_to_db(self, list1, parent_name, tablename_utf8, dbpath)
- # 1秒后自动跳转
- QTimer.singleShot(1000, lambda: self.simulateButtonClick("btn_new"))
- # 刷新树和tableview
- self.refresh_tree()
-
- # 数据库路径,哪种方法,表名
- self.selectModel = UIFunctions.search_data_to_show(self, dbpath, parent_name, tablename)
- # self.ui.resultTableView1.doubleClicked.connect(self.seleceModel_itemclicked)
-
- # 设置右键菜单策略为CustomContextMenu
- self.ui.resultTableView1.setContextMenuPolicy(Qt.CustomContextMenu)
-
- # 关联自定义的右键菜单方法到customContextMenuRequested信号
- self.ui.resultTableView1.customContextMenuRequested.connect(self.show_custom_context_menu)
-
- #把编辑状态改回去
- self.ui.resultTableView1.setEditTriggers(QTableView.EditTrigger.NoEditTriggers)
-
- def edit_dataclicked(self):
- # 所有条件都可以开启编辑
- self.ui.resultTableView1.setEditTriggers(QTableView.EditTrigger.AllEditTriggers)
-
- def add_Dataclicked(self):
- # 获取显示用的model
- inputmodel = self.ui.resultTableView1.model()
- rowcount = inputmodel.rowCount()
- colcount = inputmodel.columnCount()
- # 添加一行
- self.ui.resultTableView1.model().insertRow(rowcount)
- # 所有条件都可以开启编辑
- self.ui.resultTableView1.setEditTriggers(QTableView.EditTrigger.AllEditTriggers)
-
-
- def on_download_3_clicked(self):
- # 获取应用的安装目录
- app_install_dir = os.path.dirname(os.path.abspath(__file__))
- # 构建数据库路径
- db_path = os.path.join(app_install_dir, '..', 'SQL', 'DataBase.db')
- db_path = os.path.abspath(db_path)
- file_name = "水准测段高差稳定计算示例文件.xlsx"
- utf_en = file_name.encode('utf-8')
- print(db_path)
- # 调用main_function_example函数
- main_function_example(self, utf_en, db_path)
-
-
-
-
-
-
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- app.setWindowIcon(QIcon("icon.ico"))
- window = MainWindow()
- # window.resize(1440, 960) # 高宽
- sys.exit(app.exec())
|