Я использовал класс из stackoverflow, который применяет функцию перетаскивания к строкам таблицы, но не сохраняет изображения от удаления из ячеек при перетаскивании любой строки, мне нужна помощь, чтобы выяснить, как исправить код, чтобы сделать это жоп! код всего проекта с базой данных: используемая база данных: https://gofile.io/d/c0srQ0
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import (QApplication, QComboBox, QDialog,
QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
QVBoxLayout, QStyledItemDelegate, QCheckBox, QTableWidgetItem, QAbstractItemView, QTableWidget)
import sqlite3
import random
import ast
#import qdarkstyle
class Main(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.cashed = []
self.setWindowTitle('Arabic Math Project')
self.setContentsMargins(20,20,20,20)
# create table:
#Options()
#self.setStyleSheet(qdarkstyle.load_stylesheet())
layout = QVBoxLayout()
self.searchBar = QtWidgets.QLineEdit()
self.searchBar.setAlignment(QtCore.Qt.AlignCenter)
self.searchBar.setPlaceholderText("search")
self.searchBar.textChanged.connect(self.startSearchThreading) #editingFinished()
#self.table = QtWidgets.QTableWidget()
self.table = TableWidgetDragRows()
conn = sqlite3.connect("math.db")
conn.text_factory = bytes
self.cur = conn.cursor()
data = self.cur.execute("select * from problems;").fetchall();conn.close()
self.dims = (lambda x: (len(x), len(x[0])))(data) #(rows number, col number)
[self.table.insertRow(i) for i in [i for i in range(self.dims[0])]]
[self.table.insertColumn(i) for i in [i for i in range(self.dims[1]+1)]]
#changing h-header names .
self.table.setHorizontalHeaderLabels(["Unique", "Image", "Test", "Year", "Lesson", "Page","Comment", "Options", "Options-advanced"])
for c in range(self.dims[1]):
for r in range(self.dims[0]):
if c!=1:self.table.setItem(r, c, QtWidgets.QTableWidgetItem(data[r][c].decode("utf-8")))
else:self.table.setCellWidget(r, c, self.getImage(data[r][c]))
for r in range(self.dims[0]):self.table.setCellWidget(r, self.dims[1], Options(ops=[data[r][self.dims[1]-1].decode("utf-8")], row=data[r]))
#table h & v auto - resizing .
header = self.table.horizontalHeader()
header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.Interactive)
header.setSectionResizeMode(7, QtWidgets.QHeaderView.Interactive)
headerv = self.table.verticalHeader()
headerv.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
#hide the options column cuz it doesn't concern user to see it.
self.table.setColumnHidden(7, True)
#layout setting up.
layout.addWidget(self.searchBar)
layout.addWidget(self.table)
self.setLayout(layout)
def getImage(self, image):
imageLabel = ScaledPixmapLabel()
pixmap = QtGui.QPixmap()
pixmap.loadFromData(image, "jpg")
imageLabel.setPixmap(pixmap)
return imageLabel
def startSearchThreading(self):
self.table.setRowCount(0)
self.update = updateTable(data= self.searchBar.text())
self.update.new_signal.connect(self.Search)
self.update.start()
def create(self):
self.createFormGroupBox()
return self.formGroupBox
@QtCore.pyqtSlot(int, int, bytes, bool, bytes)
def Search(self, r, c, d, newRowOrder, ops):
if newRowOrder:self.table.insertRow(self.table.rowCount()) # create new row.
if c!=1:self.table.setItem(r, c, QtWidgets.QTableWidgetItem(d.decode("utf-8")))
else:self.table.setCellWidget(r, c, self.getImage(d))
self.cashed.append(d)
if c ==self.dims[1]-1:
self.table.setCellWidget(r, self.dims[1], Options(ops=[ops.decode("utf-8")], row=self.cashed))
self.cashed = []
class updateTable(QtCore.QThread):
def __init__(self, parent=None, data=True):
super(QtCore.QThread, self).__init__()
self.data = data
new_signal = QtCore.pyqtSignal(int, int, bytes, bool, bytes)
def run(self):
currRow = 0
conn = sqlite3.connect("math.db")
conn.text_factory = bytes
self.cur = conn.cursor()
searched = self.cur.execute(" SELECT * FROM problems WHERE text LIKE ('%' || ? || '%') ", (self.data,)).fetchall()
dims = (lambda x: (len(x), len(x[0])))(searched) if searched!=[] else (0, 0)
for r in range(dims[0]):
for c in range(dims[1]):
self.new_signal.emit(r, c, searched[r][c], True if c==0 else False, searched[r][dims[1]-1])
class ScaledPixmapLabel(QtWidgets.QLabel):
def __init__(self):
super().__init__()
self.setScaledContents(True)
def paintEvent(self, event):
if self.pixmap():
pm = self.pixmap()
originalRatio = pm.width() / pm.height()
currentRatio = self.width() / self.height()
if originalRatio != currentRatio:
qp = QtGui.QPainter(self)
pm = self.pixmap().scaled(self.size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
rect = QtCore.QRect(0, 0, pm.width(), pm.height())
rect.moveCenter(self.rect().center())
qp.drawPixmap(rect, pm)
return
super().paintEvent(event)
class Options(QtWidgets.QWidget):
def __init__(self, parent=None,row=[], ops=[]):
super(Options, self).__init__(parent)
self.i = random.randint(1, 100)
self.row = [j.decode("utf-8") if i!=1 else "image" for i,j in enumerate(row)]
self.formLayout = QFormLayout()
self.setStyleSheet(open("styles.css").read())
ops = ast.literal_eval(ops[0]) if ops!=[] else {}
for i,j in ops.items():
widget = {"lineedit": QLineEdit(), "combobox": QComboBox(), "spinbox": QSpinBox(), "checkbox": QCheckBox()}
title = j.get("title", "")
combos = j.get("combos", [])
if i == "lineedit":widget[i].setText(j.get("default", ""))
elif i == "combobox":widget[i].addItems(combos)
elif i == "checkbox":
widget[i].setCheckState((lambda x: {1:2, 2:2, 0:0}[x])(j.get("default", 0)))
widget[i].setText(j.get("text", ""))
elif i == "spinbox":
widget[i].setMaximum(j.get("max", 100))
widget[i].setMinimum(j.get("min", 0))
self.formLayout.addRow(QLabel(title), widget[i])
self.btn = QtWidgets.QPushButton("Submit")
self.btn.clicked.connect(self.do)
self.formLayout.addWidget(self.btn)
self.formLayout.setFormAlignment(QtCore.Qt.AlignVCenter)
self.setLayout(self.formLayout)
def do(self):
#[STOPED HERE]
heads, tails = [], []
for i in range(self.formLayout.count()):
w = self.formLayout.itemAt(i).widget()
if i%2==0:heads.append(w.text())
elif isinstance(w, QLineEdit):tails.append(w.text())
elif isinstance(w, QComboBox):tails.append(w.currentText())
elif isinstance(w, QSpinBox):tails.append(w.value())
elif isinstance(w, QCheckBox):tails.append(w.checkState())
values = {i:j for i,j in zip(heads, tails)}
print(self.row[:-1]+[values])
class TableWidgetDragRows(QTableWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setDragEnabled(True)
self.setAcceptDrops(True)
self.viewport().setAcceptDrops(True)
self.setDragDropOverwriteMode(False)
self.setDropIndicatorShown(True)
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
#self.setSelectionBehavior(QAbstractItemView.SelectRows)
self.setDragDropMode(QAbstractItemView.InternalMove)
def dropEvent(self, event: QDropEvent):
if not event.isAccepted() and event.source() == self:
drop_row = self.drop_on(event)
rows = sorted(set(item.row() for item in self.selectedItems()))
print(rows)
rows_to_move = [[QTableWidgetItem(self.item(row_index, column_index)) for column_index in range(self.columnCount())]
for row_index in rows]
for row_index in reversed(rows):
self.removeRow(row_index)
if row_index < drop_row:
drop_row -= 1
for row_index, data in enumerate(rows_to_move):
row_index += drop_row
self.insertRow(row_index)
for column_index, column_data in enumerate(data):
self.setItem(row_index, column_index, column_data)
event.accept()
for row_index in range(len(rows_to_move)):
self.item(drop_row + row_index, 0).setSelected(True)
self.item(drop_row + row_index, 1).setSelected(True)
super().dropEvent(event)
def drop_on(self, event):
index = self.indexAt(event.pos())
if not index.isValid():
return self.rowCount()
return index.row() + 1 if self.is_below(event.pos(), index) else index.row()
def is_below(self, pos, index):
rect = self.visualRect(index)
margin = 2
if pos.y() - rect.top() < margin:
return False
elif rect.bottom() - pos.y() < margin:
return True
# noinspection PyTypeChecker
return rect.contains(pos, True) and not (int(self.model().flags(index)) & Qt.ItemIsDropEnabled) and pos.y() >= rect.center().y()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
main = Main()
main.resize(600,600)
main.show()
app.exec_()