Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
- ' Codec:utf-8
- '
- ' 简单的SQL 增删查改演示程序, 用于练习python
- '
- ' 程序很简单, 一个主窗口
- '
- ' 一个TreeWidget 控件, 用来显示所有建立的链接以及table的信息
- ' 一个ListWidget 控件, 用于显示指定的表的field头以及基本数据类型[tinyint, blob], 位域名, 长度以及小数长度\
- ' 并提供简单的插入, 删除修改操作
- ' 一个ListWidget 控件2, 用来显示当前表的所有Field的所有数据项目, [此部分增删查改可能会有BUG..]
- '
- ' 以及若干模态对话框以及菜单和 Tracker菜单
- ' 没写完, 但基础功能都有了, 后面的功能感觉写不写的区别也不大..
- '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
- import mysql.connector
- import sys
- import datetime
- # 导入Qt 库
- from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
- from PyQt5.QtGui import QIcon
- from PyQt5.QtCore import pyqtSlot
- # 导入Qt UI文件
- from DlgSQLSettings import *
- from UiMain import *
- from DlgFieldNameAppend import *
- from DlgFieldAdjust import *
- from DlgDataSettings_Int import *
- from DlgDataSettings_Float import *
- from DlgDataSettings_Char import *
- from DlgDataSettings_Datetime import *
- from DlgDataSettings_Time import *
- from DlgDataSettings_Date import *
- from DlgDataSettings_Year import *
- # 全局使用的SQL类型
- # 为了简单, 只提供一些标准SQL数据类型
- listStrSQLDataTyple =\
- [
- # FLOAT
- 'float', # 0 附带浮点精度位
- 'double', # 1 附带浮点精度位
- 'decimal', # 2 附带浮点精度位
- # CHAR
- 'char', # 3
- 'varchar', # 4
- # INT
- 'tinyint', # 5
- 'smallint', # 6
- 'mediumint', # 7
- 'integer', # 8
- 'int', # 9
- 'bigint', #10
- # DATE
- 'datetime', #11
- 'timestamp', #12
- 'time', #13
- 'date', #14 不需要长度计数
- 'year', #15 不需要长度计数
- # TEXT || BLOB
- 'tinyblob', #16 自此以下不需要长度计数
- 'tinytext', #17
- 'blob', #18
- 'text', #19
- 'mediumblob',#20
- 'mediumtext',#21
- 'longblob', #22
- 'longtext' #23
- ]
- listStrSQLDataDefault =\
- [
- # FLOAT
- '0.0', # 0 附带浮点精度位
- '0.0', # 1 附带浮点精度位
- '0.0', # 2 附带浮点精度位
- # CHAR
- "'String'", # 3
- "'String'", # 4
- # INT
- '0', # 5
- '0', # 6
- '0', # 7
- '0', # 8
- '0', # 9
- '0', #10
- # DATE
- "'1970-01-01 00:00:00'", #11
- "'1970-01-01 00:00:00'", #12
- "'00:00:00'", #13
- "'1970-01-01'", #14 不需要长度计数
- "'1970'", #15 不需要长度计数
- # TEXT || BLOB
- 'tinyblob', #16 自此以下不需要长度计数
- 'tinytext', #17
- 'blob', #18
- 'text', #19
- 'mediumblob',#20
- 'mediumtext',#21
- 'longblob', #22
- 'longtext' #23
- ]
- # 对于SQL的某些命名, 不能直接使用数字, 需要用``这种另类引号把括起来, 否则会报错
- def linkSQLVarName(strName):
- return '`' + strName + '`'
- # 获取指定参数位域拟合的数据类型长度+小数类型的字符串
- # 形如 char(200), float(3, 5)的字符串
- def makeTypeRange(intField, strFieldType, main, sub):
- strMain = str(main)
- strSub = str(sub)
- str_ = strFieldType
- if main != 0:
- if intField <= 2:
- str_ += '(' + strMain + ',' + strSub + ')'
- elif intField <= 13:
- str_ += '(' + strMain + ')'
- else:
- if intField >=3 \
- or intField <=4: # [var]char
- str_ += '(0)'
- return str_
- # 获取指定类型字符串在表中的索引位置
- def getDataTypeIndex(typeString):
- for iter, item in enumerate(listStrSQLDataTyple):
- if typeString == item:
- return iter
- else:
- pass
- return -1
- # 根据数据索引获取类型字符串
- def getDataTypeString(typeIndex):
- if typeIndex < len(listStrSQLDataTyple):
- return listStrSQLDataTyple[typeIndex]
- else:
- return None
- # SQL 位域类
- class SQL_field(object):
- def __init__(self):
- self.strName = '' # 字段名
- self.mainLen = 0 # 数据类型整数位进度
- self.subLen = 0 # 数据类型小数位进度
- self.collName = '' # 形如 char(200), float(3, 5)的字符串
- self.dataList = []
- self.intField = 0
- self.strFieldType = ''
- self.bPrimaryKey = False
- self.bAutoINC = False
- self.bNullable = False
- self.strComment = None
- def getMainlen(self):
- return self.mainLen
- def getSublen(self):
- return self.subLen
- def updateNumber(self, collName):
- self.mainLen = 0
- self.subLen = 0
- self.intField = -1
- for iter, item in enumerate(listStrSQLDataTyple):
- keyLen = len(item)
- collLen = len(collName)
- if keyLen <= collLen\
- and item == collName[:keyLen]:
- # 判断数据类型, 获取整数, 小数部分精度
- # INFORMATION_SCHEMA.COLUMNS 获取的关于此部分的信息有可能不准确
- # 需要手动提取信息 /* 附带信息, 零填充和 符号标记 */
- self.intField = iter
- if keyLen == collLen:
- pass
- elif iter <= 2:
- splitPos = collName.index(',')
- self.mainLen = int(collName[keyLen + 1:splitPos])
- self.subLen = int(collName[splitPos+ 1:collName.index(')')])
- elif iter <= 13:
- self.mainLen = int(collName[keyLen+1:collName.index(')')])
- return None
- def updateDataByTuple(self, sqlTuple):
- # python 查询 INFORMATION_SCHEMA 返回的字段元组示意组
- # [1] 数据库名
- # [2] 表名
- # [3] 字段名
- # [6] 空约束 可以返回"YES", 强制约束返回"NO"
- # [7] 数据类型
- # [15] 数据拟合字段 (e.g. int(255) unsigned)
- # [16] 主键标识 ('PRI')
- # [17] 自增字段标识 ('auto_increment')
- # [19] 注释
- self.strName = sqlTuple[3]
- self.strFieldType = sqlTuple[7]
- self.collName = sqlTuple[15]
- self.intField = getDataTypeIndex(self.strFieldType)
- self.bPrimaryKey = False
- self.bAutoINC = False
- self.bNullable = False
- if sqlTuple[16] == 'PRI':
- self.bPrimaryKey = True
- if sqlTuple[17] == 'auto_increment':
- self.bAutoINC = True
- if sqlTuple[16] == 'YES':
- self.bNullable = True
- if sqlTuple[19] != None:
- self.strComment = sqlTuple[19]
- self.updateNumber(self.collName)
- # SQL 表类, 存放表名和位域集合
- class SQL_table(object):
- def __init__(self):
- self.strName = ''
- self.fieldList = []
- # SQL 数据库类, 存放数据库名和表集合
- class SQL_database(object):
- def __init__(self):
- self.strName = ''
- self.tableList = []
- # SQL 链接简化类
- class SQL_handle_helper(object):
- def __init__(self, handle_, str_database=None, str_table=None):
- self.handle = handle_
- self.cursor = handle_.cursor(buffered=True)
- self.bDestroy = False
- self.strDatabase = str_database
- self.strTable = str_table
- def __del__(self):
- if self.bDestroy == False:
- self.handle.close()
- def close(self):
- self.handle.close()
- self.bDestroy = True
- def command(self, command_):
- self.cursor.execute(command_)
- def commandNoexcept(self, command_):
- try:
- self.cursor.execute(command_)
- return None
- except Exception as e:
- return str(e)
- def fetchone(self):
- return self.cursor.fetchone()
- def fetchall(self):
- return self.cursor.fetchall()
- def commit(self):
- self.handle.commit()
- def command_drop_table_field(self, strField):
- self.command("ALTER TABLE {TABLE} DROP COLUMN {FIELD}"\
- .format(TABLE=linkSQLVarName(self.strTable), FIELD=linkSQLVarName(strField)))
- def command_drop_table_prikey(self):
- self.command("ALTER TABLE {TABLE} DROP PRIMARY KEY"\
- .format(TABLE=linkSQLVarName(self.strTable)))
- def command_get_table_prikey(self):
- self.command( "SELECT " \
- "column_name " \
- "FROM " \
- "INFORMATION_SCHEMA.`KEY_COLUMN_USAGE` " \
- "WHERE table_name = '{TABLE}' " \
- "AND constraint_name = 'PRIMARY'" \
- .format(TABLE = self.strTable) )
- def command_get_column_infos(self):
- command_ = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS "\
- \
- "WHERE TABLE_SCHEMA = '{DATABASE}' " \
- "AND TABLE_NAME = '{TABLE}' "\
- .format(DATABASE=self.strDatabase, TABLE=self.strTable)
- self.command(command_)
- def string_alter_table(self):
- return "ALTER TABLE {TABLE} ".format(TABLE=linkSQLVarName(self.strTable))
- def string_alter_table_toadd(self, strToAdd):
- return "ALTER TABLE {TABLE} {LINK} ".format(TABLE=linkSQLVarName(self.strTable), LINK=strToAdd)
- # 迭代重载
- def __iter__(self):
- return iter(self.cursor.fetchone, None)
- # SQL 链接类, 提供基础的SQL链接句柄, 和数据库集合
- class SQL_connect(object):
- def __init__(self, _strConnectName = '', _strHost = '', _strPort = '', _strUserName = '', _strPassword = ''):
- self.strConnectName = _strConnectName
- self.strHost = _strHost
- self.strPort = _strPort
- self.strUserName = _strUserName
- self.strPassword = _strPassword
- self.databaseList = []
- def openSQLConnect(self):
- return mysql.connector.connect(host=self.strHost, port=self.strPort, user=self.strUserName, passwd=self.strPassword)
- def openSQLConnect2(self, database_):
- return mysql.connector.connect(host=self.strHost, port=self.strPort, user=self.strUserName, passwd=self.strPassword, database = database_)
- def openSQLConnect_helper(self):
- return SQL_handle_helper(self.openSQLConnect())
- def openSQLConnect2_helper(self, database, table = None):
- return SQL_handle_helper(self.openSQLConnect2(database), database, table)
- def enumALLInfos(self):
- # 打开链接句柄,
- # 打开多个, 因为SQL handle 获得的光标貌似不能同时使用多个命令\
- # 不然需要同时数个cursor上下文信息的时候, \
- # execute执行后先前需要的上下文Cursor内容会被覆盖 (不然就是我记错了....?)
- commandHelper = self.openSQLConnect_helper()
- commandHelper2 = self.openSQLConnect_helper()
- # 显示当前链接所拥有的所有数据库信息
- commandHelper.command("SHOW DATABASES")
- # 迭代, 收集数据库
- # iter是个元组, 第一个元素为数据库名字
- for iter in commandHelper:
- databaseItem = SQL_database()
- databaseItem.strName = iter[0]
- # 切换光标到当前的数据库
- commandHelper2.command("USE " + linkSQLVarName(iter[0]))
- # information_schema 这个数据库的表类型是SYSTEM VIEW\
- # 需要额外判断一下
- if iter[0] != 'information_schema':
- commandHelper2.command("SHOW FULL TABLES WHERE TABLE_TYPE = 'BASE TABLE'; ")
- else:
- commandHelper2.command("SHOW FULL TABLES WHERE TABLE_TYPE = 'SYSTEM VIEW'; ")
- # 迭代, 收集数据库下所有表信息
- # iter2也是个元组, 第一个元素为表的名字
- for iter2 in commandHelper2:
- table = SQL_table()
- table.strName = iter2[0]
- databaseItem.tableList.append(table)
- self.databaseList.append(databaseItem)
- # SQL 索引上下文
- class SQL_indexctx:
- def __init__(self, listField_, cmdHelper_, strTable_):
- self.listPrevPrimaryKey = []
- self.strIndexField = None
- self.strTable = strTable_
- self.cmdHelper = cmdHelper_
- self.listField = listField_
- self.strCommandDropAtomicINC = None
- self.strCommandResumeAtomicINC = None
- # 缓存之前的主键字段集合
- self.cmdHelper.command_get_table_prikey()
- # 增加主键缓存
- for iter in self.cmdHelper:
- self.listPrevPrimaryKey.append(iter[0])
- # 查看自增字段是否存在
- # 缓存 SQL 扔掉/ 挂上原子自增旗标命令
- for iter in listField_:
- if iter.bAutoINC != False:
- cmdBase = self.cmdHelper.string_alter_table_toadd('MODIFY COLUMN') \
- + linkSQLVarName(iter.strName) \
- + " {COLLNAME} NOT NULL".format(COLLNAME=iter.collName)
- self.strCommandDropAtomicINC = cmdBase
- self.strCommandResumeAtomicINC = cmdBase + " AUTO_INCREMENT "
- if iter.strComment != None:
- cmdComment = " COMMENT '{sComment}'".format(sComment=iter.strComment)
- self.strCommandDropAtomicINC += cmdComment
- self.strCommandResumeAtomicINC += cmdComment
- break
- def resumeOldKey(self):
- # 恢复之前的主键设置
- # FIXME:这里依赖查询语句的默认排序为键顺序从小到大升序表示
- if len(self.listPrevPrimaryKey) > 0:
- strCombin = self.cmdHelper.string_alter_table_toadd("ADD PRIMARY KEY ") \
- + "({PRI_KEY_SET})".format(PRI_KEY_SET=",".join('`' + i + '`' for i in self.listPrevPrimaryKey))
- self.cmdHelper.command(strCombin)
- if self.strCommandResumeAtomicINC != None:
- self.cmdHelper.command(self.strCommandResumeAtomicINC)
- def createIndex(self):
- if self.strIndexField == None:
- # 创建临时主键索引
- strFieldTryUpdate = 'fefefefe'
- cntTimeoutCount = 400
- cntTrySetCount = 0
- # 测试消除之前存在的主键自增旗标
- # 否则新设置尝试会报错
- if self.strCommandDropAtomicINC != None:
- self.cmdHelper.command(self.strCommandDropAtomicINC)
- if len(self.listPrevPrimaryKey) > 0:
- self.cmdHelper.command_drop_table_prikey()
- while cntTrySetCount < cntTimeoutCount:
- try:
- command_ = self.cmdHelper.string_alter_table() \
- + "ADD COLUMN {field} int(255) UNSIGNED NOT NULL AUTO_INCREMENT FIRST , " \
- "ADD PRIMARY KEY ({field})".format(field=strFieldTryUpdate)
- self.cmdHelper.command(command_)
- self.strIndexField = strFieldTryUpdate
- return self.strIndexField
- except Exception as e:
- cntTrySetCount += 1
- strFieldTryUpdate += '_'
- # 失败恢复主键设置, 按理说不应该会失败
- assert False
- self.resumeOldKey()
- return None
- def closeIndex(self):
- if self.strIndexField != None:
- self.cmdHelper.command_drop_table_field(self.strIndexField)
- self.strIndexField = None
- # 恢复之前的主键设置
- self.resumeOldKey()
- # Qt 模态对话框类- 资源对话框基类
- class CDialogUI_T(QtWidgets.QDialog):
- def __init__(self, Ui_ctor, attachFrame_ = None):
- # 执行基础的模态对话框类基类构造函数
- QtWidgets.QDialog.__init__(self)
- # 挂载 QtDesigner UI 资源文件
- self.ui = Ui_ctor()
- self.ui.setupUi(self)
- self.setModal(True)
- self.frame0 = attachFrame_
- # Qt 模态对话框类- 用于设置新链接的基本参数 [链接名, socket host, 端口, 用户名和密码]
- # 点击主窗口菜单栏 创建新链接时被启用
- class CDialogSQLSettings(CDialogUI_T):
- def __init__(self, SQL_connect_ref_list, frame_):
- # 执行基础的模态对话框类基类构造函数
- CDialogUI_T.__init__(self, Ui_Dialog, frame_)
- self.setWindowIcon(QIcon("settings.ico"))
- self.newItem = None;
- self.isInsertDone_ = False;
- self.connectList = SQL_connect_ref_list
- # 设置 Qt 槽函数映射控件消息
- self.ui.btOk.clicked.connect(self.onSettings)
- self.ui.btCancel.clicked.connect(self.close)
- # 填充控件默认参数
- self.ui.etConnectName.setPlainText('samples-link')
- self.ui.etHostName.setPlainText('localhost')
- self.ui.etPort.setPlainText('3306')
- self.ui.etUserName.setPlainText('root')
- def onSettings(self):
- # 此回调在用户设置完成按下确定按钮时被启用,
- # 用于验证链接的正确性
- # 获取 text控件上设置的文本参数
- strConnect = self.ui.etConnectName.toPlainText()
- strHost = self.ui.etHostName.toPlainText()
- strPort = self.ui.etPort.toPlainText()
- strUserName = self.ui.etUserName.toPlainText()
- strPassword = self.ui.etPassword.toPlainText()
- connectCurrent = SQL_connect(strConnect, strHost, strPort, strUserName, strPassword)
- # 尝试链接数据库
- # 如果失败会提示用户矫正错误
- try:
- handle = mysql.connector.connect(host=strHost, port=strPort, user=strUserName, passwd=strPassword)
- except Exception as e:
- QtWidgets.QMessageBox().critical(None, 'MySQL 新链接设置', str(e), QtWidgets.QMessageBox.Ok)
- else:
- # 到这一步, 新的链接没有问题, 一个可用的新链接创建成功
- # 插入到数据对象表中
- # 关闭模态对话框
- self.isInsertDone_ = True;
- self.connectList.append(connectCurrent)
- self.newItem = connectCurrent
- self.close()
- finally:
- handle.close()
- # Qt 模态对话框类- 浮点 型数据编辑
- class CDialogDataSettings_Float(CDialogUI_T):
- def __init__(self, CMainFrame_, attachFloat_):
- # 执行基础的模态对话框类基类构造函数
- CDialogUI_T.__init__(self, Ui_DlgDataSettings_Float, CMainFrame_)
- # 设置 Qt 槽函数映射控件消息/ 填充控件默认参数
- self.ui.btOk.clicked.connect(self.onSettings)
- self.ui.btCancel.clicked.connect(self.close)
- self.ui.etSettingsFloat.setPlainText(str(attachFloat_))
- def onSettings(self):
- # 获取 text控件上设置的文本参数
- strSettingsFloat = self.ui.etSettingsFloat.toPlainText()
- res = self.frame0.updateData(str(strSettingsFloat))
- if res != None:
- QtWidgets.QMessageBox().critical(None, 'CDialogDataSettings_Float', res, QtWidgets.QMessageBox.Ok)
- else:
- self.close()
- self.frame0.updateDataUI(strSettingsFloat)
- # Qt 模态对话框类- 字符 型数据编辑
- class CDialogDataSettings_Char(CDialogUI_T):
- def __init__(self, CMainFrame_, attachChar_):
- # 执行基础的模态对话框类基类构造函数
- CDialogUI_T.__init__(self, Ui_DlgDataSettings_Char, CMainFrame_)
- # 设置 Qt 槽函数映射控件消息
- self.ui.btOk.clicked.connect(self.onSettings)
- self.ui.btCancel.clicked.connect(self.close)
- # 填充控件默认参数
- self.ui.etSettingsChar.setPlainText(attachChar_)
- def onSettings(self):
- # 获取 text控件上设置的文本参数
- strSettingsChar = self.ui.etSettingsChar.toPlainText()
- res = self.frame0.updateData("'" + strSettingsChar + "'")
- if res != None:
- QtWidgets.QMessageBox().critical(None, 'CDialogDataSettings_Char', res, QtWidgets.QMessageBox.Ok)
- else:
- self.close()
- self.frame0.updateDataUI(strSettingsChar)
- # Qt 模态对话框类- INT 型数据编辑
- class CDialogDataSettings_Int(CDialogUI_T):
- def __init__(self, CMainFrame_, attachInt_):
- # 执行基础的模态对话框类基类构造函数
- CDialogUI_T.__init__(self, Ui_DlgDataSettings_Int, CMainFrame_)
- # 设置 Qt 槽函数映射控件消息 / 填充控件默认参数
- self.ui.btOk.clicked.connect(self.onSettings)
- self.ui.btCancel.clicked.connect(self.close)
- def onSettings(self):
- strSettingsInt = self.ui.etSettingsInt.toPlainText()
- res = self.frame0.updateData(str(strSettingsInt))
- if res != None:
- QtWidgets.QMessageBox().critical(None, 'CDialogDataSettings_Int', res, QtWidgets.QMessageBox.Ok)
- else:
- self.close()
- self.frame0.updateDataUI(strSettingsInt)
- # Qt 模态对话框类- 日期 型数据-datetime 编辑
- class CDialogDataSettings_Datetime(CDialogUI_T):
- def __init__(self, CMainFrame_, attachDatetime_):
- # 执行基础的模态对话框类基类构造函数
- CDialogUI_T.__init__(self, Ui_DlgDataSettings_Datetime, CMainFrame_)
- # 设置 Qt 槽函数映射控件消息
- self.ui.btOk.clicked.connect(self.onSettings)
- self.ui.btCancel.clicked.connect(self.close)
- if attachDatetime_ != None:
- self.ui.tmSettings.setTime(QtCore.QTime(attachDatetime_.hour, attachDatetime_.minute, attachDatetime_.second, 0))
- self.ui.caSettings.setSelectedDate(QtCore.QDate(attachDatetime_.year, attachDatetime_.month, attachDatetime_.day))
- def onSettings(self):
- # 获取 时间数据
- qTime = self.ui.tmSettings.time()
- qDate = self.ui.caSettings.selectedDate()
- dtSettings = "{YEAR}-{MONTH}-{DAY} {HOUR}:{MIN}:{SEC}"\
- .format(YEAR =qDate.year()\
- ,MONTH=qDate.month()\
- ,DAY = qDate.day()\
- ,HOUR=qTime.hour()\
- ,MIN=qTime.minute()\
- ,SEC=qTime.second())
- res = self.frame0.updateData("'" + dtSettings + "'")
- if res != None:
- QtWidgets.QMessageBox().critical(None, 'CDialogDataSettings_Datetime', res, QtWidgets.QMessageBox.Ok)
- else:
- self.close()
- self.frame0.updateDataUI(dtSettings)
- # Qt 模态对话框类- 日期 型数据-date 编辑
- class CDialogDataSettings_Date(CDialogUI_T):
- def __init__(self, CMainFrame_, attachDatetime_):
- # 执行基础的模态对话框类基类构造函数
- CDialogUI_T.__init__(self, Ui_DlgDataSettings_Date, CMainFrame_)
- # 设置 Qt 槽函数映射控件消息
- self.ui.btOk.clicked.connect(self.onSettings)
- self.ui.btCancel.clicked.connect(self.close)
- if attachDatetime_ != None:
- self.ui.caSettings.setSelectedDate(QtCore.QDate(attachDatetime_.year, attachDatetime_.month, attachDatetime_.day))
- def onSettings(self):
- # 获取 时间数据
- qDate = self.ui.caSettings.selectedDate()
- dtSettings = "{YEAR}-{MONTH}-{DAY}" \
- .format(YEAR=qDate.year() \
- , MONTH=qDate.month() \
- , DAY=qDate.day() )
- res = self.frame0.updateData("'" + dtSettings + "'")
- if res != None:
- QtWidgets.QMessageBox().critical(None, 'CDialogDataSettings_Date', res, QtWidgets.QMessageBox.Ok)
- else:
- self.close()
- self.frame0.updateDataUI(dtSettings)
- # Qt 模态对话框类- 日期 型数据-TIME 编辑
- class CDialogDataSettings_Time(CDialogUI_T):
- def __init__(self, CMainFrame_, attachDatetime_):
- # 执行基础的模态对话框类基类构造函数
- CDialogUI_T.__init__(self, Ui_DlgDataSettings_Time, CMainFrame_)
- # 设置 Qt 槽函数映射控件消息
- self.ui.btOk.clicked.connect(self.onSettings)
- self.ui.btCancel.clicked.connect(self.close)
- if attachDatetime_ != None:
- hour = attachDatetime_.seconds/3600
- min = attachDatetime_.seconds%3600/60
- sec = attachDatetime_.seconds%60
- self.ui.tmSettings.setTime(QtCore.QTime(hour, min, sec, 0))
- def onSettings(self):
- # 获取 时间数据
- qTime = self.ui.tmSettings.time()
- dtSettings = "{HOUR}:{MIN}:{SEC}" \
- .format(HOUR=qTime.hour() \
- , MIN=qTime.minute() \
- , SEC=qTime.second())
- res = self.frame0.updateData("'" + dtSettings + "'")
- if res != None:
- QtWidgets.QMessageBox().critical(None, 'CDialogDataSettings_Datetime', res, QtWidgets.QMessageBox.Ok)
- else:
- self.close()
- self.frame0.updateDataUI(dtSettings)
- # Qt 模态对话框类- 日期 型数据-YEAR 编辑
- class CDialogDataSettings_Year(CDialogUI_T):
- def __init__(self, CMainFrame_, attachInt_):
- # 执行基础的模态对话框类基类构造函数
- CDialogUI_T.__init__(self, Ui_DlgDataSettings_Year, CMainFrame_)
- # 设置 Qt 槽函数映射控件消息
- self.ui.btOk.clicked.connect(self.onSettings)
- self.ui.btCancel.clicked.connect(self.close)
- # 填充控件默认参数
- self.ui.etSettingsInt.setPlainText(str(attachInt_))
- def onSettings(self):
- # 此回调在用户设置完成按下确定按钮时被启用,
- # 用于验证设置整数的正确性
- # 获取 text控件上设置的文本参数
- strSettingsInt = self.ui.etSettingsInt.toPlainText()
- res = self.frame0.updateData(str(strSettingsInt))
- if res != None:
- QtWidgets.QMessageBox().critical(None, 'CDialogDataSettings_Int', res, QtWidgets.QMessageBox.Ok)
- else:
- self.close()
- self.frame0.updateDataUI(strSettingsInt)
- ''' Qt 模态对话框类- 用于在表的指定位置增加新的SQL Field
- CMainFrame_:主窗口引用指针
- pos_ : 当前选中的位置
- strFieldNameAfter_: 在当前位置之前的Field名字, 如果 pos_ 为0. 此值则为nullptr
- '''
- class CDialogAppendField(CDialogUI_T):
- def __init__(self, CMainFrame_, pos_, strFieldNameAfter_):
- assert CMainFrame_ != None
- assert CMainFrame_.pickAvailable() != False
- # 执行基础的模态对话框类基类构造函数
- CDialogUI_T.__init__(self, Ui_dlgFieldNameAppend, CMainFrame_)
- self.strFieldNameAfter = strFieldNameAfter_
- self.insertPos = pos_
- self.ui.btOk.clicked.connect(self.onSettings)
- self.ui.etFieldName.setPlainText('samples')
- # 准备comboBox 下拉信息
- for iter, item in enumerate(listStrSQLDataTyple):
- self.ui.cbField.insertItem(iter, item)
- self.ui.cbField.setCurrentIndex(4)
- def onSettings(self):
- # 用户按下设置完成按钮,
- # 进行新位域的检查, 测试, 成功则添加此Field
- assert self.frame0.pickAvailable() != False
- frame = self.frame0
- index = self.ui.cbField.currentIndex()
- strFieldName = self.ui.etFieldName.toPlainText()
- commandHelper = frame.openSQLConnect2_helper()
- strType = getDataTypeString(index)
- strColl = makeTypeRange(index, strType, 2, 0)
- command_ = commandHelper.string_alter_table_toadd("ADD COLUMN")\
- + " {FIELD} {COLLNAME}".format(FIELD=linkSQLVarName(strFieldName), COLLNAME=strColl)
- if self.strFieldNameAfter == None:
- command_ += ' FIRST' # 第一个元素
- self.insertPos = 0
- else:
- command_ += ' AFTER ' + linkSQLVarName(self.strFieldNameAfter)
- try:
- commandHelper.command(command_)
- # FIXME: 位域设置有遗漏项
- field = SQL_field()
- field.strName = strFieldName
- field.strFieldType = strType
- field.collName = strColl
- field.mainLen = 2
- field.intField = index
- # 更新 Qt的 UI视图
- frame.ui.tbField.insertRow(self.insertPos)
- frame.ui.tbData.insertColumn(self.insertPos)
- frame.fieldList.insert(self.insertPos, field)
- frame.renameTbDataColName(self.insertPos, field.strName)
- frame.ui.tbField.setItem(self.insertPos, 0, QtWidgets.QTableWidgetItem(strFieldName))
- frame.ui.tbField.setItem(self.insertPos, 1, QtWidgets.QTableWidgetItem(strType))
- frame.ui.tbField.setItem(self.insertPos, 2, QtWidgets.QTableWidgetItem('2'))
- frame.ui.tbField.setItem(self.insertPos, 3, QtWidgets.QTableWidgetItem('0'))
- self.close()
- except Exception as e:
- QtWidgets.QMessageBox().critical(None, 'MySQL Connect', str(e), QtWidgets.QMessageBox.Ok)
- finally:
- commandHelper.close()
- # Qt 模态对话框类- 用于在表的指定位置修改指定SQL Field类型
- # CMainFrame_:主窗口引用指针
- # pos_ : 当前选中的位置
- class CDialogAdjustField(CDialogUI_T):
- def __init__(self, CMainFrame_, pos_):
- assert CMainFrame_ != None
- assert CMainFrame_.pickAvailable() != False
- # 执行基础的模态对话框类基类构造函数
- CDialogUI_T.__init__(self, Ui_DlgFieldTypeAdjust, CMainFrame_)
- self.updatePos = pos_
- # 准备comboBox 下拉信息
- for iter, item in enumerate(listStrSQLDataTyple):
- self.ui.cbField.insertItem(iter, item)
- # 设置当前状态索引
- field = CMainFrame_.getField(pos_)
- if field.intField >= 0:
- self.ui.cbField.setCurrentIndex(field.intField)
- else:
- self.ui.cbField.insertItem(999999, "UnknowData") # XXX: 999999
- self.ui.cbField.setCurrentIndex(len(listStrSQLDataTyple))
- self.ui.btOk.clicked.connect(self.onSettings)
- def onSettings(self):
- assert self.frame0.pickAvailable() != False
- # 用户按下设置完成按钮,
- # 进行新位域的修改, 测试, 成功则更新此位域
- intField = self.ui.cbField.currentIndex()
- pos = self.updatePos
- frame = self.frame0
- if intField >= len(listStrSQLDataTyple):
- QtWidgets.QMessageBox().critical(None, 'MySQL Field位域矫正', '你设置了未知的数据格式!', QtWidgets.QMessageBox.Ok)
- else:
- try:
- field = frame.getField(pos)
- commandHelper = frame.openSQLConnect2_helper()
- commandHelper.command(commandHelper.string_alter_table_toadd("MODIFY COLUMN")\
- + "{FIELD} {COLLNAME}".format(FIELD=linkSQLVarName(field.strName)\
- ,COLLNAME=makeTypeRange(intField, getDataTypeString(intField), field.getMainlen(), field.getSublen())\
- )\
- )
- # 更新列数据
- commandHelper.command_get_column_infos()
- field.updateDataByTuple(commandHelper.fetchall()[pos])
- frame.ui.tbField.item(pos, 2).setText(str(field.getMainlen()))
- frame.ui.tbField.item(pos, 3).setText(str(field.getSublen()))
- frame.ui.tbField.item(pos, 1).setText(field.strFieldType)
- self.close()
- except Exception as e:
- QtWidgets.QMessageBox().critical(None, 'MySQL Connect', str(e), QtWidgets.QMessageBox.Ok)
- finally:
- commandHelper.close()
- # Qt主窗口
- class CMainFrame(QtWidgets.QMainWindow):
- def __init__(self):
- # 执行基础的主窗口帧类基类构造函数
- QtWidgets.QMainWindow.__init__(self)
- self.onFieldRemove = False
- self.catchDataRow = -1
- self.catchDataCol = -1
- self.ui = Ui_MainWindow()
- self.ui.setupUi(self)
- self.ui.cmdNewMySQLConnect.triggered.connect(self.onSQLSettings)
- self.ui.actionQt.triggered.connect(lambda state:QtWidgets.QMessageBox().aboutQt(None, "About QT"))
- self.setWindowIcon(QIcon("main.ico"))
- # 关联弹出上下文菜单 | 双击消息
- self.ui.tbField.itemDoubleClicked.connect(self.onFieldTypeAdjust)
- self.ui.tbField.currentItemChanged.connect(self.onFieldChanged)
- self.ui.tbField.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
- self.ui.tbField.customContextMenuRequested.connect(self.onFieldCtxMenu)
- self.ui.tbData.itemDoubleClicked.connect(self.onDataAdjust)
- self.ui.tbData.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
- self.ui.tbData.customContextMenuRequested.connect(self.onDataCtxMenu)
- self.ui.trConnect.itemDoubleClicked.connect(self.onSelectTreeItem)
- self.ui.trConnect.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
- self.ui.trConnect.customContextMenuRequested.connect(self.onOverviewCtxMenu)
- # 概览Tree控件的弹出菜单 | 槽回调
- self.tbOverviewMenu = QtWidgets.QMenu(self.ui.trConnect)
- self.actTableAppend = QtWidgets.QAction("添加新表", self.ui.trConnect)
- self.actTableEdit = QtWidgets.QAction("编辑当前表", self.ui.trConnect)
- self.actTableRemove = QtWidgets.QAction("删除当前表", self.ui.trConnect)
- '''
- self.actTableAppend.triggered.connect(self.onAppendTable)
- self.actTableEdit.triggered.connect(self.onEditTable)
- self.actTableRemove.triggered.connect(self.onRemoveTable)
- self.tbOverviewMenu.addAction(self.actTableAppend)
- self.tbOverviewMenu.addAction(self.actTableEdit)
- self.tbOverviewMenu.addAction(self.actTableRemove)
- self.tbDatabaseMenu = QtWidgets.QMenu(self.ui.tbField)
- self.actDatabaseAppend = QtWidgets.QAction("添加新数据库", self.ui.trConnect)
- self.actDatabaseEdit = QtWidgets.QAction("编辑当前数据库", self.ui.trConnect)
- self.actDatabaseRemove = QtWidgets.QAction("删除当前数据库", self.ui.trConnect)
- self.actDatabaseAppend.triggered.connect(self.onAppendDatabase)
- self.actDatabaseEdit.triggered.connect(self.onEditDatabase)
- self.actDatabaseRemove.triggered.connect(self.onRemoveDatabase)
- self.tbDatabaseMenu.addAction(self.actDatabaseAppend)
- self.tbDatabaseMenu.addAction(self.actDatabaseEdit)
- self.tbDatabaseMenu.addAction(self.actDatabaseRemove)
- self.tbLinkMenu = QtWidgets.QMenu(self.ui.tbField)
- self.actLinkAppend = QtWidgets.QAction("添加新链接", self.ui.trConnect)
- self.actLinkEdit = QtWidgets.QAction("编辑当前链接", self.ui.trConnect)
- self.actLinkRemove = QtWidgets.QAction("删除当前链接", self.ui.trConnect)
- self.actLinkAppend.triggered.connect(self.onAppendLink)
- self.actLinkEdit.triggered.connect(self.onEditLink)
- self.actLinkRemove.triggered.connect(self.onRemoveLink)
- self.tbLinkMenu.addAction(self.actLinkAppend)
- self.tbLinkMenu.addAction(self.actLinkEdit)
- self.tbLinkMenu.addAction(self.actLinkRemove)
- '''
- # 字段List控件的弹出菜单 | 槽回调 TODO:设置List控件的多选, 单选一次选中一行等功能
- self.tbFieldMenu = QtWidgets.QMenu(self.ui.tbField)
- self.actFieldInsertBefore = QtWidgets.QAction("新字段插入", self.ui.tbField)
- self.actFieldInsertAfter = QtWidgets.QAction("新字段添至尾部", self.ui.tbField)
- self.actFieldRemoveCurrent = QtWidgets.QAction("移除当前选择字段", self.ui.tbField)
- self.actFieldInsertBefore.triggered.connect(self.onInsertNewFieldBefore)
- self.actFieldInsertAfter.triggered.connect(self.onAppendField)
- self.actFieldRemoveCurrent.triggered.connect(self.onRemoveField)
- self.tbFieldMenu.addAction(self.actFieldInsertBefore)
- self.tbFieldMenu.addAction(self.actFieldInsertAfter)
- self.tbFieldMenu.addAction(self.actFieldRemoveCurrent)
- # 数据List控件的弹出菜单 | 槽回调
- self.tbDataMenu = QtWidgets.QMenu(self.ui.tbData)
- self.actDataInsert = QtWidgets.QAction("新数据插入", self.ui.tbData)
- self.actDataRemoveCurrent = QtWidgets.QAction("移除当前选择数据", self.ui.tbData)
- self.actDataInsert.triggered.connect(self.onInsertData)
- self.actDataRemoveCurrent.triggered.connect(self.onRemoveData)
- self.tbDataMenu.addAction(self.actDataInsert)
- self.tbDataMenu.addAction(self.actDataRemoveCurrent)
- self.fieldList = []
- self.connectList = []
- # Qt5 GUI Pick Connect/Database/Table var
- self.pickConnect = None
- self.pickDatabase= None
- self.pickTable = None
- # Ctor listview column header (SQL field header)
- self.ui.tbField.setColumnCount(4)
- self.ui.tbField.setHorizontalHeaderLabels(['字段名', '数据类型', '长度', '小数'])
- # 使用 QSplitter 切割分割窗口
- qSplitterBlock = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
- qSplitterBlock.setOpaqueResize(True)
- qSplitterSub = QtWidgets.QSplitter(QtCore.Qt.Vertical, qSplitterBlock)
- self.ui.trConnect.setParent(qSplitterSub)
- self.ui.tbField.setParent(qSplitterSub)
- self.ui.tbData.setParent(qSplitterBlock)
- qSplitterSub.addWidget(self.ui.trConnect)
- qSplitterSub.addWidget(self.ui.tbField)
- qSplitterBlock.addWidget(qSplitterSub)
- qSplitterBlock.addWidget(self.ui.tbData)
- qSplitterBlock.setStretchFactor(0, 8)
- qSplitterBlock.setStretchFactor(1, 17)
- qSplitterSub.setStretchFactor(0, 1)
- qSplitterSub.setStretchFactor(1, 1)
- self.ui.horizontalLayout.addWidget(qSplitterBlock)
- self.showMaximized()
- self.show()
- def openSQLConnect_helper(self):
- assert self.pickAvailable() != False
- return self.pickConnect.openSQLConnect2_helper()
- def openSQLConnect2_helper(self):
- assert self.pickAvailable() != False
- return self.pickConnect.openSQLConnect2_helper(self.pickDatabase.strName, self.pickTable.strName)
- # :需要外部捕获异常
- def updateData(self, strPackage):
- assert self.pickAvailable() != False
- assert self.catchDataCol >= 0
- assert self.catchDataRow >= 0
- commandHelper = self.openSQLConnect2_helper()
- indexCtx = SQL_indexctx(self.fieldList, commandHelper, self.pickTable.strName)
- try:
- strTable = linkSQLVarName(self.pickTable.strName)
- strFieldIndexKey = indexCtx.createIndex() # TODO Check
- strField = self.fieldList[self.catchDataCol].strName
- command2 = "UPDATE {TABLE} SET {FIELD}={VALUE} WHERE {KEY} IN (SELECT {KEY} FROM (SELECT {KEY} FROM {TABLE} LIMIT {ROW_},1) AS TEMP)" \
- .format(TABLE=strTable, FIELD=linkSQLVarName(strField), KEY=strFieldIndexKey, VALUE=strPackage, ROW_=self.catchDataRow)
- commandHelper.command(command2)
- return None
- except Exception as e:
- return str(e)
- finally:
- indexCtx.closeIndex()
- commandHelper.close()
- def updateDataUI(self, strPackage):
- assert self.pickAvailable() != False
- assert self.catchDataCol >= 0
- assert self.catchDataRow >= 0
- self.ui.tbData.item(self.catchDataRow, self.catchDataCol).setText(strPackage)
- def getData(self, col, row):
- assert self.pickAvailable() != False
- commandHelper = self.openSQLConnect2_helper()
- commandHelper.command("SELECT {FIELD} FROM {TABLE} LIMIT {ROW}, 1"\
- .format(FIELD=linkSQLVarName(self.fieldList[col].strName) \
- ,TABLE=linkSQLVarName(self.pickTable.strName)\
- ,ROW =str(row) \
- )\
- )
- return commandHelper.fetchone()[0]
- # 函数解耦-测试当前是否点击选中对象
- def pickAvailable(self):
- return self.pickTable != None\
- and self.pickDatabase != None\
- and self.pickConnect != None
- # 函数解耦-获取当前位域指定行field
- def getField(self, rowSpec):
- row = self.ui.tbField.rowCount()
- if rowSpec < row \
- and self.pickAvailable() != False:
- return self.fieldList[rowSpec]
- else:
- return None
- # 函数解耦-设置位域杂项信息
- def setListFieldMisc(self):
- # 设置位域List控件列1不可编辑
- row = self.ui.tbField.rowCount()
- if row >= 0 \
- and self.pickAvailable() != False:
- for iter in range(row):
- item0 = self.ui.tbField.item(iter, 1)
- item0.setFlags(item0.flags() & (~QtCore.Qt.ItemIsEditable))
- def renameTbDataColName(self, col, strName):
- item = self.ui.tbData.setHorizontalHeaderItem(col, QtWidgets.QTableWidgetItem(strName))
- # Qt 位域List控件右键菜单-增加Field到指定位置之前
- def onInsertNewFieldBefore(self):
- row = self.ui.tbField.currentRow()
- listLen = len(self.fieldList)
- if row >= 0 \
- and listLen > 0\
- and row < listLen:
- CDialogAppendField(self, row, self.fieldList[row].strName).exec()
- # Qt 位域List控件右键菜单-增加Field到末尾
- def onAppendField(self):
- listLen = len(self.fieldList)
- if listLen > 0:
- CDialogAppendField(self, listLen, self.fieldList[listLen-1].strName).exec()
- else:
- CDialogAppendField(self, 0, None).exec()
- # Qt 位域List控件右键菜单-移除指定位域
- def onRemoveField(self):
- row = self.ui.tbField.currentRow()
- if row >= 0:
- field = self.fieldList[row]
- commandHelper = self.openSQLConnect2_helper()
- try:
- # 删除指定表字段及其相关的数据结构
- commandHelper.command('ALTER TABLE ' + linkSQLVarName(self.pickTable.strName)\
- + ' DROP COLUMN ' + linkSQLVarName(field.strName))
- self.onFieldRemove = True
- self.fieldList.remove(field)
- # 更新Qt视图, 删除会触发额外的changed消息, 使用onFieldRemove屏蔽他
- self.ui.tbData.removeColumn(row)
- self.ui.tbField.removeRow(row)
- self.onFieldRemove = False
- except Exception as e:
- QtWidgets.QMessageBox().critical(None, 'MySQL Connect', str(e), QtWidgets.QMessageBox.Ok)
- finally:
- commandHelper.close()
- # Qt 数据List控件右键菜单-移除指定数据
- def onRemoveData(self):
- row = self.ui.tbData.currentRow()
- if row >= 0:
- try:
- # 删除指定表字段及其相关的数据结构
- # 根据行号删除指定数据
- # 创建一个临时的自增主键用于寻址指定的行数
- commandHelper = self.openSQLConnect2_helper()
- indexCtx = SQL_indexctx(self.fieldList, commandHelper, self.pickTable.strName)
- strTable = linkSQLVarName(self.pickTable.strName)
- strField = indexCtx.createIndex() # TODO Check
- command2 = "delete from {table} where {id} in (select {id} from (select {id} from {table} limit {row_},1) as temp)"\
- .format(table=strTable, id=strField, row_=row)
- commandHelper.command(command2)
- commandHelper.commit()
- indexCtx.closeIndex()
- self.ui.tbData.removeRow(row)
- except Exception as e:
- QtWidgets.QMessageBox().critical(None, 'MySQL Connect', str(e), QtWidgets.QMessageBox.Ok)
- finally:
- commandHelper.close()
- # Qt 数据List控件右键菜单-插入数据
- def onInsertData(self):
- try:
- assert self.pickAvailable() != False
- commandHelper = self.openSQLConnect2_helper()
- strField = None
- strValue = None
- strCommand= "INSERT INTO `{TABLE}` () VALUES ()".format(TABLE=self.pickTable.strName)
- # 只关心那些非空约束字段的值设置
- for iter in self.fieldList:
- if iter.bNullable == False:
- strVal_t = '0'
- if iter.intField < len(listStrSQLDataDefault):
- strVal_t = listStrSQLDataDefault[iter.intField]
- if strField != None:
- strField = strField + ',' + linkSQLVarName(iter.strName)
- strValue = strValue + ',' + strVal_t
- else:
- strField = linkSQLVarName(iter.strName)
- strValue = strVal_t
- if strValue != None:
- strCommand = "INSERT INTO `{TABLE}` ({FIELDS}) VALUES ({VALS})"\
- .format(TABLE =self.pickTable.strName\
- ,FIELDS=strField \
- ,VALS = strValue)
- commandHelper.command(strCommand)
- commandHelper.commit()
- self.ui.tbData.setRowCount(self.ui.tbData.rowCount() + 1)
- for iter2, item in enumerate(self.fieldList):
- uiItem = QtWidgets.QTableWidgetItem("")
- uiItem.setFlags(uiItem.flags() & (~QtCore.Qt.ItemIsEditable))
- self.ui.tbData.setItem(self.ui.tbData.rowCount() - 1, iter2, uiItem)
- except Exception as e:
- QtWidgets.QMessageBox().critical(None, 'MySQL Connect', str(e), QtWidgets.QMessageBox.Ok)
- finally:
- commandHelper.close()
- def onFieldCtxMenu(self, point):
- if self.pickAvailable() != False:
- self.tbFieldMenu.move(self.cursor().pos())
- self.tbFieldMenu.show()
- def onDataCtxMenu(self, point):
- if self.pickAvailable() != False:
- self.tbDataMenu.move(self.cursor().pos())
- self.tbDataMenu.show()
- def onOverviewCtxMenu(self, point):
- if self.pickAvailable() != False:
- self.tbDataMenu.move(self.cursor().pos())
- self.tbDataMenu.show()
- '''
- 字段List控件双击消息, 只处理数据类型列(列索引为1)
- '''
- def onFieldTypeAdjust(self, qTableItem):
- assert qTableItem != None
- if self.ui.tbField.column(qTableItem) == 1:
- dlg = CDialogAdjustField(self, self.ui.tbField.row(qTableItem))
- dlg.exec()
- def onDataAdjust(self, qTableItem):
- assert qTableItem != None
- self.catchDataRow = -1
- self.catchDataCol = -1
- # 获取点击的行列, 列指示解析类型, 行指示修改行数
- col = self.ui.tbData.column(qTableItem)
- row = self.ui.tbData.row(qTableItem)
- if col >= 0 \
- and row >= 0 \
- and self.pickAvailable() != False:
- self.catchDataRow = row
- self.catchDataCol = col
- field = self.fieldList[col]
- recv = self.getData(col, row)
- if field.intField >= 0 \
- and field.intField <= 2:
- CDialogDataSettings_Float(self, recv).exec()
- elif field.intField >= 3 \
- and field.intField <= 4:
- dlg = CDialogDataSettings_Char(self, recv).exec()
- elif field.intField >= 5 \
- and field.intField <= 10:
- dlg = CDialogDataSettings_Int(self, recv).exec()
- elif field.intField == 11:
- CDialogDataSettings_Datetime(self, recv).exec()
- elif field.intField == 12:
- QtWidgets.QMessageBox().critical(None, 'onDataAdjust', "timestamp暂时不支持编辑", QtWidgets.QMessageBox.Ok)
- elif field.intField == 13:
- CDialogDataSettings_Time(self, recv).exec()
- elif field.intField == 14:
- CDialogDataSettings_Date(self, recv).exec()
- elif field.intField == 15:
- CDialogDataSettings_Year(self, recv).exec()
- else:
- QtWidgets.QMessageBox().critical(None, 'onDataAdjust', "text和blob/其他数据暂时不支持编辑", QtWidgets.QMessageBox.Ok)
- if self.ui.tbField.column(qTableItem) == 1:
- dlg = CDialogAdjustField(self, self.ui.tbField.row(qTableItem))
- dlg.exec()
- def onFieldChanged(self, current, previous):
- if previous != None\
- and self.onFieldRemove == False:
- col = self.ui.tbField.column(previous)
- row = self.ui.tbField.row(previous)
- if col >= 0 \
- and row >= 0\
- and col != 1\
- and row < len(self.fieldList)\
- and self.pickAvailable() != False:
- field = self.fieldList[row]
- qItemfieldName = self.ui.tbField.item(row, 0)
- qItemfieldMain = self.ui.tbField.item(row, 2)
- qItemfieldSub = self.ui.tbField.item(row, 3)
- commandHelper = self.openSQLConnect2_helper()
- try:
- if col == 0:
- # Modify field-name
- commandHelper.command('ALTER TABLE ' + linkSQLVarName(self.pickTable.strName)\
- +' CHANGE COLUMN ' + linkSQLVarName(field.strName)\
- +' ' + linkSQLVarName (previous.text())\
- +' ' + field.collName)
- field.strName = previous.text()
- self.renameTbDataColName(row, field.strName)
- else:
- adjustValueMain = field.getMainlen()
- adjustValueSub = field.getSublen()
- setCurrent = int(previous.text())
- if col == 2:
- adjustValueMain = setCurrent
- else:
- adjustValueSub = setCurrent
- command_ = 'ALTER TABLE ' + linkSQLVarName(self.pickTable.strName)\
- +' MODIFY COLUMN ' + linkSQLVarName(field.strName)\
- +' ' + makeTypeRange(field.intField, field.strFieldType,\
- adjustValueMain,\
- adjustValueSub)
- commandHelper.command(command_)
- commandHelper.command_get_column_infos()
- field.updateDataByTuple(commandHelper.fetchall()[row])
- qItemfieldName.setText(field.strName)
- qItemfieldMain.setText(str(field.getMainlen()))
- qItemfieldSub.setText(str(field.getSublen()))
- except Exception as e:
- QtWidgets.QMessageBox().critical(None, 'MySQL Connect', str(e), QtWidgets.QMessageBox.Ok)
- # Reset old infos
- qItemfieldName.setText(field.strName)
- qItemfieldMain.setText(str(field.getMainlen()))
- qItemfieldSub.setText(str(field.getSublen()))
- commandHelper.close()
- def onSelectTreeItem(self, treeItem, dummyUsed):
- if treeItem.UserType & 0x80000000:
- try:
- # Enum field list
- self.fieldList = []
- connect = self.connectList [treeItem.parent().parent().UserType & 0x1FFFFFFF]
- database= connect.databaseList [treeItem.parent().UserType & 0x3FFFFFFF]
- table = database.tableList [treeItem.UserType & 0x7FFFFFFF]
- commandHelper = connect.openSQLConnect2_helper(database.strName, table.strName)
- commandHelper2 = connect.openSQLConnect2_helper(database.strName, table.strName)
- commandHelper3 = connect.openSQLConnect2_helper(database.strName, table.strName)
- # Update pick var
- self.pickConnect = connect
- self.pickDatabase= database
- self.pickTable = table
- commandHelper.command_get_column_infos()
- listHeader = []
- # Serach && Append field
- for iter in commandHelper:
- field = SQL_field()
- field.updateDataByTuple(iter)
- # Append col header
- listHeader.append(field.strName)
- self.fieldList.append(field)
- self.ui.tbData.setColumnCount(len(listHeader))
- self.ui.tbData.setHorizontalHeaderLabels(listHeader)
- commandHelper2.command("SELECT COUNT(*) FROM " + linkSQLVarName(table.strName))
- self.ui.tbData.setRowCount(commandHelper2.fetchone()[0])
- self.ui.tbField.setRowCount(len(self.fieldList))
- for iter, sqlItemField in enumerate(self.fieldList):
- QTbItem1 = QtWidgets.QTableWidgetItem("supported/unknown data")
- if sqlItemField.intField >= 0:
- QTbItem1.setText(sqlItemField.strFieldType)
- self.ui.tbField.setItem(iter, 0, QtWidgets.QTableWidgetItem(sqlItemField.strName))
- self.ui.tbField.setItem(iter, 1, QTbItem1)
- self.ui.tbField.setItem(iter, 2, QtWidgets.QTableWidgetItem(str(sqlItemField.getMainlen())))
- self.ui.tbField.setItem(iter, 3, QtWidgets.QTableWidgetItem(str(sqlItemField.getSublen())))
- commandHelper3.command("SELECT " + linkSQLVarName(sqlItemField.strName)\
- + " FROM " + linkSQLVarName(table.strName))
- for iter2, sqlItemField2 in enumerate(commandHelper3):
- item0 = QtWidgets.QTableWidgetItem(str(sqlItemField2[0]))
- item0.setFlags(item0.flags() & (~QtCore.Qt.ItemIsEditable))
- self.ui.tbData.setItem(iter2, iter, item0)
- self.setListFieldMisc()
- except Exception as e:
- QtWidgets.QMessageBox().critical(None, 'MySQL Connect', str(e), QtWidgets.QMessageBox.Ok)
- self.pickConnect = None
- self.pickDatabase= None
- self.pickTable = None
- self.ui.tbField.setRowCount(0)
- self.ui.tbData.setRowCount(0)
- finally:
- commandHelper.close()
- commandHelper2.close()
- commandHelper3.close()
- def onSQLSettings(self):
- dlgSQLSettings = CDialogSQLSettings(self.connectList, self)
- dlgSQLSettings.exec()
- if dlgSQLSettings.isInsertDone_ != False:
- # Reset all view
- # Append to tail (QTreeWidget)
- # TODO: check repeat name
- dlgSQLSettings.newItem.enumALLInfos()
- topCurrentNode = QtWidgets.QTreeWidgetItem([dlgSQLSettings.newItem.strConnectName])
- topCountNode = self.ui.trConnect.topLevelItemCount()
- topCurrentNode.UserType = topCountNode | 1 << 29
- topCurrentNode.setIcon(0, QtGui.QIcon("link.ico") )
- for iter in dlgSQLSettings.newItem.databaseList:
- levelCurrentNode = QtWidgets.QTreeWidgetItem(topCurrentNode, [iter.strName])
- levelCurrentNode.UserType = topCurrentNode.childCount() - 1 | 1 << 30
- levelCurrentNode.setIcon(0, QtGui.QIcon("database.ico"))
- for iter2 in iter.tableList:
- # FIXME: index | shift, too simple mark range and index
- levelCurrentNode2 = QtWidgets.QTreeWidgetItem(levelCurrentNode, [iter2.strName])
- levelCurrentNode2.UserType = levelCurrentNode.childCount() - 1 | 1 << 31
- levelCurrentNode2.setIcon(0, QtGui.QIcon("table.ico"))
- self.ui.trConnect.insertTopLevelItem(topCountNode, topCurrentNode)
- if __name__ == '__main__':
- app = QtWidgets.QApplication(sys.argv)
- window = CMainFrame()
- window.show()
- sys.exit(app.exec_())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement