data-manipulation/gui.py

527 lines
21 KiB
Python
Raw Normal View History

2017-03-13 15:18:52 +03:00
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
2017-03-21 16:47:18 +03:00
from PyQt5.QtCore import *
from PyQt5.QtGui import *
2017-03-17 17:17:17 +03:00
from PyQt5.QtWidgets import *
2017-03-15 15:58:26 +03:00
#import pymysql
2017-03-13 15:18:52 +03:00
import dm
class MyTable(QTableWidget):
2017-04-06 15:59:26 +03:00
def __init__(self, dbTableName = 'NULL', *args):
self.dbTableName = dbTableName
QTableWidget.__init__(self, *args)
2017-03-16 16:10:47 +03:00
self.resizeColumnsToContents()
self.horizontalHeader().setSortIndicatorShown(True)
self.horizontalHeader().setStretchLastSection(True)
self.horizontalHeader().setCascadingSectionResizes(True)
# равномерное изменение ширины столбцов
self.horizontalHeader().setSectionResizeMode(1)
2017-03-16 16:10:47 +03:00
# изменение ширины столбцов по размеру текста
2017-03-20 12:38:14 +03:00
#self.horizontalHeader().setSectionResizeMode(3)
2017-03-22 17:17:46 +03:00
self.horizontalHeader().setStyleSheet("color: black; font-weight:bold; background-color: lightblue;")
2017-03-20 12:38:14 +03:00
self.setWordWrap(True)
self.setSortingEnabled(True)
2017-03-17 17:17:17 +03:00
# обработка нажатия мышой на таблице
self.doubleClicked.connect(self.on_click)
# self.doubleClicked.connect(self.contextMenuEvent(self.cursor()))
# показ контекстного меню
def contextMenuEvent(self, event):
Rmenu = QMenu(self)
2017-03-20 12:38:14 +03:00
addRecord = Rmenu.addAction("Добавить запись")
2017-03-17 17:17:17 +03:00
delRecord = Rmenu.addAction("Удалить запись")
showRelations = Rmenu.addAction("Показать связанные документы")
2017-03-17 17:17:17 +03:00
action = Rmenu.exec_(self.mapToGlobal(event.pos()))
if action == delRecord:
row = self.rowAt(event.pos().y())
col = self.columnAt(event.pos().x())
2017-03-21 16:47:18 +03:00
print("Удаляем row:%d, col:%d" % (row, col))
2017-03-17 17:17:17 +03:00
item = self.item(self.currentIndex().row(), self.currentIndex().column())
2017-03-21 16:47:18 +03:00
print("Запись" + item.text())
2017-04-06 15:59:26 +03:00
self.delRecord(row)
elif action == addRecord:
2017-03-21 16:47:18 +03:00
print("Добавить запись ")
addNewRecord()
elif action == showRelations:
item = self.item(self.currentIndex().row(), self.currentIndex().column())
showRelationsRecords(self.currentIndex().column(), item.text())
2017-03-21 16:47:18 +03:00
2017-03-17 17:17:17 +03:00
def on_click(self):
#print(self.cursor().pos().x())
2017-03-17 17:17:17 +03:00
#self.contextMenuEvent(self.cursor())
for currentQTableWidgetItem in self.selectedItems():
print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text())
2017-04-06 15:59:26 +03:00
# удаление записи
def delRecord(self, row):
valueList = []
#print(self.dbTableName, row, self.statusTip())
i = 0
print(self.columnCount())
while i < self.columnCount():
valueList.append(self.item(row, i).text())
print(self.item(row, i).text())
i += 1
dm.deleteRecordsFromDB(self.dbTableName, valueList)
2017-03-17 17:17:17 +03:00
# Диалог выбора связанных данных
class RelationDataView(QMainWindow):
lblList = []
editList = []
def __init__(self, tblName, editWidget, field, lbl, rel):
super().__init__()
self.tblName = tblName
self.editWidget = editWidget
self.lbl = lbl
self.tblDescr = dm.getTablesDescriptionOfName(tblName)
self.field = field
self.rel = rel
self.setWindowTitle(self.tblDescr)
self.setGeometry(300, 300, 640, 480)
scroll_widget = QWidget()
self.general_layout = QVBoxLayout()
#scroll_area = QScrollArea()
l = QVBoxLayout()
headBox = QHBoxLayout()
lblHeader = QLabel("<B>Таблица: " + self.tblDescr)
l.addLayout(headBox)
headBox.addWidget(lblHeader)
hboxData = QHBoxLayout()
2017-04-06 15:59:26 +03:00
self.tableViewData = MyTable(tblName)
#print(self.widgetsList)
hboxData.addWidget(self.tableViewData)
hboxBtn = QHBoxLayout()
btnOk = QPushButton('Ок')
btnOk.clicked.connect(lambda: self.ok())
btnCancel = QPushButton('Закрыть')
btnCancel.clicked.connect(lambda: self.close())
l.addLayout(hboxData)
hboxBtn.addWidget(btnOk)
hboxBtn.addWidget(btnCancel)
l.addLayout(hboxBtn)
self.general_layout.addLayout(l)
scroll_widget.setLayout(self.general_layout)
#scroll_area.setWidget(scroll_widget)
self.setCentralWidget(scroll_widget)
addDataIntoTable(self.tblName, self.tableViewData)
def ok(self):
#listData = [self.tblName]
#listFieldData = []
# выбираем из выделенной строки значение нужной ячейки
# соответсвующей полю связанной таблицы
for currentQTableWidgetItem in self.tableViewData.selectedItems():
lstFields = dm.getTableStructure(self.tblName)
i = 0
for fieldItem in lstFields:
if fieldItem[0] == self.field:
#print(fieldItem, i)
self.editWidget.setText(self.tableViewData.item(currentQTableWidgetItem.row(), i).text())
# пррячем воле ввода
self.editWidget.hide()
print(self.lbl.text())
# в метку добавляем значения для подставновки соответсвенно связи
txt = '<b>'+str(self.getDataFromTableWidget(currentQTableWidgetItem.row()))
# устанавливаем текст на метку и включаем её
self.lbl.setText(txt)
self.lbl.setVisible(True)
break
i = i+1
self.close()
# получаем данные из таблицы для соответсвующих полей
# для подставновки в форму редактирования(добавления) для связей
def getDataFromTableWidget(self, row):
fields = self.rel.split(',')
lstFields = dm.getTableStructure(self.tblName)
print(fields)
print(lstFields)
txt = ''
for item in fields:
item = item.rstrip(' ').lstrip(' ')
print(item)
i = 0
for fieldItem in lstFields:
if fieldItem[0] == item:
print(item, fieldItem)
print(self.tableViewData.item(row, i).text())
txt = txt + ' ' +self.tableViewData.item(row, i).text()
i = i + 1
print(txt)
return txt
# Форма добавления записи в БД
2017-03-22 17:17:46 +03:00
class EditForm(QMainWindow):
lblList = []
editList = []
2017-03-21 20:10:38 +03:00
def __init__(self, tblName, tblDescr):
2017-03-21 16:47:18 +03:00
super().__init__()
2017-03-22 17:17:46 +03:00
self.tblName = tblName
self.setWindowTitle("Добавление записи")
#self.setGeometry(300, 300, 400, 400)
2017-03-22 17:17:46 +03:00
scroll_widget = QWidget()
self.general_layout = QVBoxLayout()
scroll_area = QScrollArea()
2017-03-21 16:47:18 +03:00
l = QVBoxLayout()
2017-03-21 20:10:38 +03:00
headBox = QHBoxLayout()
2017-03-22 17:17:46 +03:00
lblHeader = QLabel("<B>Таблица: " + tblDescr)
2017-03-21 20:10:38 +03:00
l.addLayout(headBox)
2017-03-22 17:17:46 +03:00
#palet = QPalette(lblHeader.palette())
#lblHeader.setPalette(palet)
2017-03-21 20:10:38 +03:00
headBox.addWidget(lblHeader)
hboxBtn = QHBoxLayout()
btnOk = QPushButton('Записать')
2017-03-22 17:17:46 +03:00
btnOk.clicked.connect(lambda: self.save())
2017-03-21 20:10:38 +03:00
btnCancel = QPushButton('Закрыть')
btnCancel.clicked.connect(lambda: self.close())
2017-03-22 17:17:46 +03:00
# цифровой валидатор, для проверки ввода
integerRegex = QRegExp("^[0-9]+$")
integerValidator = QRegExpValidator(integerRegex, self)
# список соответствия полей и QEdit
self.widgetsList = []
self.btnRelationsList = []
2017-03-22 17:17:46 +03:00
# добавляем динамически поля на форму в зависимости от типов данных
for item in dm.getFields(tblName):
#print(item)
fName = item[0]
fType = item[1]
fAutoIncr = item[2]
2017-03-22 17:17:46 +03:00
fDescr = dm.getFieldDescription(tblName, fName)
hboxEdit = QHBoxLayout()
lbl = QLabel(fDescr)
lbl2 = QLabel(fDescr)
lbl2.hide()
#listRelationTableAndField = []
btnRelations = ''
tableRelation = ''
2017-03-22 17:17:46 +03:00
# создаем поле ввода соответсвующее типу данных
if fType == 'datetime':
edit = QDateTimeEdit()
edit.setCalendarPopup(True)
edit.setFrame(False)
now = QDateTime.currentDateTime()
edit.setDateTime(now)
elif fType == 'date':
edit = QDateEdit()
edit.setCalendarPopup(True)
edit.setFrame(False)
now = QDate.currentDate()
edit.setDate(now)
elif fType == 'time':
edit = QTimeEdit()
edit.setCalendarPopup(True)
edit.setFrame(False)
now = QTime.currentTime()
edit.setTime(now)
elif fType == 'integer':
edit = QLineEdit()
# отключаем поле если оно автоинкрементное
if fAutoIncr == 'AUTOINCREMENT' or fAutoIncr == 'AUTO_INCREMENT':
edit.setDisabled(True)
2017-03-22 17:17:46 +03:00
# проверка на ввод цифр
edit.setValidator(integerValidator)
else:
edit = QLineEdit()
# создаём список полей и соответсвующих им QEdit
self.widgetsList.append([fName, edit])
hboxEdit.addWidget(lbl)
hboxEdit.addWidget(lbl2)
2017-03-22 17:17:46 +03:00
hboxEdit.addWidget(edit)
# добавляем к полю кнопку для вызова связанных
print(fName)
listRelationTableAndField = dm.getRelationsForField(tblName, fName)
print(listRelationTableAndField)
if listRelationTableAndField != 'q':
tableRelation = listRelationTableAndField[0]
fieldRelation = listRelationTableAndField[1]
replaceField = listRelationTableAndField[2]
print(tableRelation + '-' + fieldRelation +'-'+replaceField)
btnRelations = QPushButton('...')
btnRelations.setFixedWidth(30)
# добавляем название виджета в список соответсвия кнопок и таблиц БД
# пиздец извращения =(
self.btnRelationsList.append([btnRelations, tableRelation, fieldRelation, replaceField, edit, lbl2, replaceField])
btnRelations.clicked.connect(lambda: self.openRelationTable())
hboxEdit.addWidget(btnRelations)
2017-03-22 17:17:46 +03:00
l.addLayout(hboxEdit)
#print(self.widgetsList)
2017-03-21 20:10:38 +03:00
hboxBtn.addWidget(btnOk)
hboxBtn.addWidget(btnCancel)
l.addLayout(hboxBtn)
2017-03-22 17:17:46 +03:00
self.general_layout.addLayout(l)
scroll_widget.setLayout(self.general_layout)
scroll_area.setWidget(scroll_widget)
self.setCentralWidget(scroll_area)
2017-03-21 20:10:38 +03:00
2017-03-22 17:17:46 +03:00
def save(self):
listData = [self.tblName]
listFieldData = []
for item in self.widgetsList:
#print(item[0] + ' ' + item[1].text())
if item[1].isEnabled:
listFieldData.append([item[0], item[1].text()])
2017-03-22 17:17:46 +03:00
listData.append(listFieldData)
#print(listData)
dm.insertDataIntoBD(listData)
self.close()
# выбираем данные для связанной таблицы
def openRelationTable(self):
sender = self.sender()
# ищем в списке соответсвующую кнопоку и связанные с ней данные
for item in self.btnRelationsList:
if sender == item[0]:
btn = item[0]
tbl = item[1]
fld = item[2]
lbl = item[5]
rel = item[6]
editWidget = item[4]
# выбираем данные из БД
#data = dm.selectData(tbl)
#print(data)
relForm = RelationDataView(tbl, editWidget, fld, lbl, rel)
relForm.show()
#relForm.setParent(self)
2017-04-06 15:59:26 +03:00
# обработка нажатия на списке таблиц БД
def clickTablesList(tbl_name, tblDataWidget, data='NULL'):
global tblList, tabRelationsData
# удаляем все открытые табы
i=0
if tabRelationsData.count():
tabRelationsData.clear()
#print(tabRelationsData.count())
while i <= tabRelationsData.count():
#print(i)
2017-03-20 12:38:14 +03:00
tabRelationsData.removeTab(i)
2017-04-06 15:59:26 +03:00
i += 1
2017-03-21 20:10:38 +03:00
addDataIntoTable(dm.getTablesNameOfDescription(listTables.model().data(listTables.currentIndex())), tblDataWidget)
2017-04-06 15:59:26 +03:00
# Пишем название активной таблицы БД в строку статуса, эадакая замена глобальной переменной
# как оно и где вылезет будем посмотреть.
tblDataWidget.setStatusTip(dm.getTablesNameOfDescription(listTables.model().data(listTables.currentIndex())))
tblDataWidget.dbTableName = dm.getTablesNameOfDescription(listTables.model().data(listTables.currentIndex()))
2017-03-13 15:18:52 +03:00
2017-04-06 15:59:26 +03:00
# вставка данных в табличный виджет
def addDataIntoTable(tbl_name, tblDataWidget, data='NULL'):
global tblList, tabRelationsData
if data == 'NULL':
data = dm.selectData(tbl_name)
2017-03-21 20:10:38 +03:00
fieldNames = dm.getTableStructure(tbl_name)
2017-04-06 15:59:26 +03:00
#print(fieldNames)
2017-03-21 16:47:18 +03:00
# проверка на наличие записей в таблице
if data:
# количество строк
rows = len(data)
# КОЛИЧЕСТВО КОЛОНОК
cols = len(data[0])
else:
rows = 0
cols = len(fieldNames)
n = 0
tblDataWidget.setRowCount(rows)
tblDataWidget.setColumnCount(cols)
for item in fieldNames:
2017-03-22 17:17:46 +03:00
fName = item[0]
fDescr = item[1]
2017-04-06 15:59:26 +03:00
#### определяем наличие связей и добавляем дополнительные столбцы
####print(fName, fDescr, dm.getRelationsForField(tbl_name, fName))
2017-03-21 16:47:18 +03:00
# установка заголовков столбцов таблицы
2017-03-22 17:17:46 +03:00
tblDataWidget.setHorizontalHeaderItem(n, QTableWidgetItem(fDescr))
2017-04-06 15:59:26 +03:00
n += 1
2017-03-21 16:47:18 +03:00
n = 0
for key in data:
m = 0
for item in key:
# преобразуем все типы в строку
newitem = QTableWidgetItem(str(item))
tblDataWidget.setItem(m, n, newitem)
n += 1
m += 1
2017-04-06 15:59:26 +03:00
# Показ менб и панели инструментов
2017-03-21 16:47:18 +03:00
def showMenuToolbar(window):
newAction = QAction(QIcon('img/new.gif'), 'Добавить', window)
newAction.setShortcut('Ins')
newAction.setStatusTip('Добавить')
newAction.triggered.connect(addNewRecord)
deleteAction = QAction(QIcon('img/delete.gif'), 'Удалить', window)
deleteAction.setShortcut('Del')
deleteAction.setStatusTip('Удалить')
# deleteAction.triggered.connect(window.qqqq)
exitAction = QAction(QIcon('img/exit.gif'), 'Выход', window)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Выход')
exitAction.triggered.connect(window.close)
cutAction = QAction(QIcon('img/cut.gif'), 'Вырезать', window)
cutAction.setShortcut('Ctrl+X')
cutAction.setStatusTip('Вырезать')
# cutAction.triggered.connect(window.close)
copyAction = QAction(QIcon('img/copy.gif'), 'Копировать', window)
copyAction.setShortcut('Ctrl+С')
copyAction.setStatusTip('Копировать')
# copyAction.triggered.connect(window.close)
pasteAction = QAction(QIcon('img/paste.gif'), 'Вставить', window)
pasteAction.setShortcut('Ctrl+V')
pasteAction.setStatusTip('Вставить')
# pasteAction.triggered.connect(window.close)
findAction = QAction(QIcon('img/find.gif'), 'Копировать', window)
findAction.setShortcut('Ctrl+F')
findAction.setStatusTip('Искать')
# findAction.triggered.connect(window.close)
printAction = QAction(QIcon('img/print.gif'), 'Печатать', window)
printAction.setShortcut('Ctrl+P')
printAction.setStatusTip('Печатать')
# printAction.triggered.connect(window.close)
window.statusBar()
menubar = window.menuBar()
fileMenu = menubar.addMenu('&Файл')
fileMenu.addAction(newAction)
fileMenu.addAction(deleteAction)
fileMenu.addAction(printAction)
fileMenu.addAction(exitAction)
editMenu = menubar.addMenu('&Редактирование')
editMenu.addAction(copyAction)
editMenu.addAction(cutAction)
editMenu.addAction(pasteAction)
editMenu.addAction(printAction)
helpMenu = menubar.addMenu('&Помощь')
# toolbar = window.addToolBar('Редактирование')
toolbar = window.addToolBar('Панель инструментов')
toolbar.addAction(newAction)
toolbar.addAction(deleteAction)
toolbar.addAction(copyAction)
toolbar.addAction(cutAction)
toolbar.addAction(pasteAction)
toolbar.addAction(findAction)
toolbar.addAction(printAction)
# toolbar.addAction(exitAction)
# форма для добавления новой записи
2017-03-21 16:47:18 +03:00
def addNewRecord():
global listTables, tblRelationsData
tblDescr = listTables.model().data(listTables.currentIndex())
for i in tblList:
if i[1] == tblDescr:
tblName = i[0]
#print(tblName)
2017-03-21 20:10:38 +03:00
editForm = EditForm(tblName, tblDescr)
editForm.show()
2017-03-21 16:47:18 +03:00
#editForm.setParent(listTables)
#editForm.show()
#editForm.setParent(tblRelationsData)
#editForm = Example()
# отображение списка связанных данных
def showRelationsRecords(fieldIndex, fieldValue):
global tabRelationsData, listTables
tblDescr = listTables.model().data(listTables.currentIndex())
i=0
if tabRelationsData.count():
while i <= tabRelationsData.count():
tabRelationsData.removeTab(i)
i = i+1
for i in tblList:
if i[1] == tblDescr:
tblName = i[0]
fieldNamesList = dm.getTableStructure(tblName)
fieldName = fieldNamesList[fieldIndex][0]
# print(fieldNamesList)
# print(fieldName)
# print("showRelations")
# print(tblName)
# print(fieldValue)
data = dm.selectRelationsDataFromDB(tblName, fieldName, fieldValue)
#print(data)
for item in data:
tbl = item[0]
qweryResult = item[1]
if qweryResult:
#print('report' + str(qweryResult) + 'report')
2017-04-06 15:59:26 +03:00
tblRelationsData = MyTable(tbl)
tblRelationsData.setParent(tabRelationsData)
tabRelationsData.addTab(tblRelationsData, dm.getTablesDescriptionOfName(tbl))
addDataIntoTable(tbl, tblRelationsData, qweryResult)
2017-04-06 15:59:26 +03:00
# пишем название активной таблицы БД в строку статуса
tblRelationsData.setStatusTip(tbl)
2017-03-21 16:47:18 +03:00
def main():
global tblList, listTables, tabRelationsData
2017-03-13 15:18:52 +03:00
app = QApplication(sys.argv)
2017-03-21 16:47:18 +03:00
mainWin = QMainWindow()
workArea = QWidget()
mainWin.setCentralWidget(workArea)
hbox = QHBoxLayout()
listTables = QListWidget()
listTables.setFrameShape(QFrame.StyledPanel)
listTables.setFixedWidth(200)
2017-04-06 15:59:26 +03:00
# выводим список таблиц в левом поле
2017-03-21 16:47:18 +03:00
tblData = MyTable()
tblData.setFrameShape(QFrame.StyledPanel)
tabRelationsData = QTabWidget()
#tabRelationsData.setFrameShape(QFrame.StyledPanel)
2017-03-21 16:47:18 +03:00
splitter1 = QSplitter(Qt.Horizontal)
splitter1.addWidget(listTables)
splitter2 = QSplitter(Qt.Vertical)
splitter2.addWidget(tblData)
splitter2.addWidget(tabRelationsData)
2017-03-21 16:47:18 +03:00
splitter1.addWidget(splitter2)
hbox.addWidget(splitter1)
workArea.setLayout(hbox)
showMenuToolbar(mainWin)
listTables.itemClicked.connect(lambda: clickTablesList(dm.getTablesNameOfDescription(listTables.model().data(listTables.currentIndex())), tblData))
2017-04-06 15:59:26 +03:00
2017-03-21 16:47:18 +03:00
tblList = dm.initDBstructure()
for i in tblList:
listTables.addItem(i[1])
2017-04-06 15:59:26 +03:00
#tblData = QTableWidget()
print(dm.getTablesNameOfDescription(listTables.model().data(listTables.currentIndex())))
2017-03-21 16:47:18 +03:00
mainWin.setGeometry(300, 300, 800, 600)
mainWin.setWindowTitle('Data manipulator')
mainWin.show()
return app.exec_()
2017-03-21 16:47:18 +03:00
if __name__ == '__main__':
main()