Python Forum
[PyQt] PyQt5 QTableView SQLite : edit cell
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyQt] PyQt5 QTableView SQLite : edit cell
#2
You can use

model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)

This is an old project where I used it. Double click and edit cell.

from PyQt5 import QtSql, QtPrintSupport
from PyQt5.QtGui import QTextDocument, QIcon, QTextCursor, QTextTableFormat
from PyQt5.QtCore import QFileInfo, Qt, QSettings, QSize, QFile, QTextStream
from PyQt5.QtWidgets import (QMainWindow, QTableView, QDialog, QGridLayout, QPushButton, 
                                                            QLineEdit, QWidget, QFileDialog, QComboBox, QMessageBox, QApplication)
import sys
###################################
class MyWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MyWindow, self).__init__()
        self.setObjectName("SqliteViewer")
        root = QFileInfo(__file__).absolutePath()
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.settings = QSettings('Axel Schneider', self.objectName())
        self.viewer = QTableView()
        self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
        self.model = QtSql.QSqlTableModel()
        self.delrow = -1
        self.dbfile = ""
        self.tablename = ""
        self.headers = []
        self.results = ""
        self.mycolumn = 0
        self.viewer.verticalHeader().setVisible(False)
        self.setStyleSheet(stylesheet(self))        
        self.viewer.setModel(self.model)
        self.viewer.clicked.connect(self.findrow)
        self.viewer.selectionModel().selectionChanged.connect(self.getCellText)
        
        self.dlg = QDialog()
        self.layout = QGridLayout()
        self.layout.addWidget(self.viewer,0, 0, 1, 4)
        
        addBtn = QPushButton("insert row")
        addBtn.setIcon(QIcon.fromTheme("add"))
        addBtn.setFixedWidth(110)
        addBtn.clicked.connect(self.addrow)
        self.layout.addWidget(addBtn, 1, 0)
        
        delBtn = QPushButton("delete row")
        delBtn.setIcon(QIcon.fromTheme("remove"))
        delBtn.setFixedWidth(110)
        delBtn.clicked.connect(self.deleteRow)
        self.layout.addWidget(delBtn,1, 1)

        self.editor = QLineEdit()
        self.editor.returnPressed.connect(self.editCell)
        self.editor.setStatusTip("ENTER new value")
        self.editor.setToolTip("ENTER new value")
        self.layout.addWidget(self.editor,1, 2)

        self.findfield = QLineEdit()
        self.findfield.addAction(QIcon.fromTheme("edit-find"), 0)
        self.findfield.returnPressed.connect(self.findCell)
        self.findfield.setFixedWidth(200)
        self.findfield.setPlaceholderText("find")
        self.findfield.setStatusTip("ENTER to find")
        self.findfield.setToolTip("ENTER to find")
        self.layout.addWidget(self.findfield,1, 3)

        self.myWidget = QWidget()
        self.myWidget.setLayout(self.layout)

        self.createToolbar()
        self.statusBar().showMessage("Ready")
        self.setCentralWidget(self.myWidget)
        self.setWindowIcon(QIcon.fromTheme("office-database"))
        self.setGeometry(20,20,600,450)
        self.setWindowTitle("SqliteViewer")
        self.readSettings()
        self.msg("Ready")
        self.viewer.setFocus()

    def createToolbar(self):
        self.actionOpen = QPushButton("Open DB")
        self.actionOpen.clicked.connect(self.fileOpen)
        icon = QIcon.fromTheme("document-open")
        self.actionOpen.setShortcut("Ctrl+O")
        self.actionOpen.setShortcutEnabled(True)
        self.actionOpen.setIcon(icon)
        self.actionOpen.setObjectName("actionOpen")
        self.actionOpen.setStatusTip("Open Database")
        self.actionOpen.setToolTip("Open Database")

        self.actionHide = QPushButton()
        self.actionHide.clicked.connect(self.toggleVerticalHeaders)
        icon = QIcon.fromTheme("pane-hide-symbolic")
        self.actionHide.setIcon(icon)
        self.actionHide.setToolTip("toggle vertical Headers")
        self.actionHide.setShortcut("F3")
        self.actionHide.setShortcutEnabled(True)
        self.actionHide.setStatusTip("toggle vertical Headers")

        ### first row as headers
        self.actionHeaders = QPushButton()
        self.actionHeaders.clicked.connect(self.selectedRowToHeaders)
        icon = QIcon.fromTheme("ok")
        self.actionHeaders.setIcon(icon)
        self.actionHeaders.setToolTip("selected row to headers")
        self.actionHeaders.setShortcut("F5")
        self.actionHeaders.setShortcutEnabled(True)
        self.actionHeaders.setStatusTip("selected row to headers")

        self.actionPreview = QPushButton()
        self.actionPreview.clicked.connect(self.handlePreview)
        icon = QIcon.fromTheme("document-print-preview")
        self.actionPreview.setShortcut("Shift+Ctrl+P")
        self.actionPreview.setShortcutEnabled(True)
        self.actionPreview.setIcon(icon)
        self.actionPreview.setObjectName("actionPreview")
        self.actionPreview.setStatusTip("Print Preview")
        self.actionPreview.setToolTip("Print Preview")

        self.actionPrint = QPushButton()
        self.actionPrint.clicked.connect(self.handlePrint)
        icon = QIcon.fromTheme("document-print")
        self.actionPrint.setShortcut("Shift+Ctrl+P")
        self.actionPrint.setShortcutEnabled(True)
        self.actionPrint.setIcon(icon)
        self.actionPrint.setObjectName("actionPrint")
        self.actionPrint.setStatusTip("Print")
        self.actionPrint.setToolTip("Print")

        ###############################
        self.tb = self.addToolBar("ToolBar")
        self.tb.setIconSize(QSize(16, 16))
        self.tb.setMovable(False)
        self.tb.addWidget(self.actionOpen)
        self.tb.addSeparator()
        self.tb.addWidget(self.actionPreview)
        self.tb.addWidget(self.actionPrint)
        ### sep
        self.tb.addSeparator()
        self.tb.addSeparator()
        ### popupMenu
        self.pop = QComboBox()
        self.pop.setFixedWidth(200)
        self.pop.currentIndexChanged.connect(self.setTableName)
        self.tb.addWidget(self.pop)
        self.tb.addSeparator()
        self.tb.addWidget(self.actionHide)
        self.addToolBar(self.tb)

    def deleteRow(self):
        row = self.viewer.currentIndex().row()
        self.model.removeRow(row)
        self.initializeModel()
        self.viewer.selectRow(row)

    def selectedRowToHeaders(self):
        if self.model.rowCount() > 0:
            headers = []
            row = self.selectedRow()
            for column in range(self.model.columnCount()):
                headers.append(self.model.data(self.model.index(row, column)))
                self.model.setHeaderData(column, Qt.Horizontal, headers[column], Qt.EditRole)
            print(headers)

    def findCell(self):
        column = 0
        ftext = self.findfield.text()
        model = self.viewer.model()
        if self.viewer.selectionModel().hasSelection():
            row =  self.viewer.selectionModel().selectedIndexes()[0].row() 
            row = row + 1
        else:
            row = 0
        start = model.index(row, column)
        matches = model.match(start, Qt.DisplayRole,ftext, 1, Qt.MatchContains)
        if matches:
            print("found", ftext, matches)
            index = matches[0]
            self.viewer.selectionModel().select(index, QItemSelectionModel.Select)
        else:
            column = column + 1
            self.findNextCell(column)

    def findNextCell(self, column):
        self.viewer.clearSelection()
        ftext = self.findfield.text()
        model = self.viewer.model()
        if self.viewer.selectionModel().hasSelection():
            row =  self.viewer.selectionModel().selectedIndexes()[0].row()
            row = row + 1
        else:
            row = 0
        start = model.index(row, column)
        matches = model.match(start, Qt.DisplayRole,ftext, 1, Qt.MatchContains)
        if matches:
            print("found", ftext)
            index = matches[0]
            self.viewer.selectionModel().select(index, QItemSelectionModel.Select)
        else:
            column = column + 1
            self.findNextCell(column)

    def toggleVerticalHeaders(self):
        if self.viewer.verticalHeader().isVisible() == False:
            self.viewer.verticalHeader().setVisible(True)
        else:
            self.viewer.verticalHeader().setVisible(False)

    def fileOpen(self):
        tablelist = []
        fileName, _ = QFileDialog.getOpenFileName(None, "Open Database File", "/home/brian/Dokumente/DB", "DB (*.sqlite *.db *.sql3);; All Files (*.*)")
        if fileName:
            self.fileOpenStartup(fileName)

    def fileOpenStartup(self, fileName):
        tablelist = []
        if fileName:
            self.db.close()
            self.dbfile = fileName
            self.db.setDatabaseName(self.dbfile)
            self.db.open()
            print("Tables:", self.db.tables())
            tablelist = self.db.tables()
            self.fillComboBox(tablelist)
            self.msg("please choose Table from the ComboBox")

    def setAutoWidth(self):
        self.viewer.resizeColumnsToContents()

    def fillComboBox(self, tablelist):
        self.pop.clear()
        self.pop.insertItem(0, "choose Table ...")
        self.pop.setCurrentIndex(0)
        for row in tablelist:
            self.pop.insertItem(self.pop.count(), row)
        if self.pop.count() > 1:
            self.pop.setCurrentIndex(1)
            self.setTableName()

    def getCellText(self):
        if self.viewer.selectionModel().hasSelection():
            item = self.viewer.selectedIndexes()[0]
            if not item == None:
                name = item.data()
            else:
                name = ""
            self.editor.setText(str(name))
        else:
            self.editor.clear()

    def editCell(self):
        item = self.viewer.selectedIndexes()[0]
        row = self.selectedRow()
        column = self.selectedColumn()
        self.model.setData(item, self.editor.text())

    def setTableName(self):
        if not self.pop.currentText() == "choose Table ...":
            self.tablename = self.pop.currentText()
            print("DB is:", self.dbfile)
            self.msg("initialize")
            self.initializeModel()

    def initializeModel(self):
        print("Table selected:", self.tablename)
        self.model.setTable(self.tablename)
        self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
        self.model.select()
        self.setAutoWidth()
        self.msg(self.tablename + " loaded *** " + str(self.model.rowCount()) + " records")

    def addrow(self):
        row =  self.viewer.selectionModel().selectedIndexes()[0].row()
        ret = self.model.insertRow(row)
        if ret:
            self.viewer.selectRow(row)
            item = self.viewer.selectedIndexes()[0]
            self.model.setData(item, str(row))
        
    def findrow(self, i):
        self.delrow = i.row()

    def selectedRow(self):
        if self.viewer.selectionModel().hasSelection():
            row =  self.viewer.selectionModel().selectedIndexes()[0].row()
            return int(row)

    def selectedColumn(self):
        column =  self.viewer.selectionModel().selectedIndexes()[0].column()
        return int(column)

    def closeEvent(self, e):
        self.writeSettings()
        e.accept()

    def readSettings(self):
        print("reading settings")
        if self.settings.contains('geometry'):
            self.setGeometry(self.settings.value('geometry'))

    def writeSettings(self):
        print("writing settings")
        self.settings.setValue('geometry', self.geometry())

    def msg(self, message):
        self.statusBar().showMessage(message)

    def handlePrint(self):
        if self.model.rowCount() == 0:
            self.msg("no rows")
        else:
            dialog = QtPrintSupport.QPrintDialog()
            if dialog.exec_() == QDialog.Accepted:
                self.handlePaintRequest(dialog.printer())
                self.msg("Document printed")

    def handlePreview(self):
        if self.model.rowCount() == 0:
            self.msg("no rows")
        else:
            dialog = QtPrintSupport.QPrintPreviewDialog()
            dialog.setFixedSize(1000,700)
            dialog.paintRequested.connect(self.handlePaintRequest)
            dialog.exec_()
            self.msg("Print Preview closed")

    def handlePaintRequest(self, printer):
        printer.setDocName(self.tablename)
        document = QTextDocument()
        cursor = QTextCursor(document)
        model = self.viewer.model()
        tableFormat = QTextTableFormat()
        tableFormat.setBorder(0.2)
        tableFormat.setBorderStyle(3)
        tableFormat.setCellSpacing(0);
        tableFormat.setTopMargin(0);
        tableFormat.setCellPadding(4)
        table = cursor.insertTable(model.rowCount() + 1, model.columnCount(), tableFormat)
        model = self.viewer.model()
        ### get headers
        myheaders = []
        for i in range(0, model.columnCount()):
            myheader = model.headerData(i, Qt.Horizontal)
            cursor.insertText(myheader)
            cursor.movePosition(QTextCursor.NextCell)
        ### get cells
        for row in range(0, model.rowCount()):
           for col in range(0, model.columnCount()):
               index = model.index( row, col )
               cursor.insertText(str(index.data()))
               cursor.movePosition(QTextCursor.NextCell)
        document.print_(printer)

def stylesheet(self):
        return """
        QTableView
        {
            border: 1px solid grey;
            border-radius: 0px;
            font-size: 8pt;
            background-color: #e8eaf3;
            selection-color: #ffffff;
        }
        QTableView::item:hover
        {   
            color: black;
            background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #729fcf, stop:1 #d3d7cf);           
        }
        
        QTableView::item:selected 
        {
            color: #F4F4F4;
            background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #6169e1, stop:1 #3465a4);
        } 

        QStatusBar
        {
            font-size: 7pt;
            color: #57579e;
        }

        QPushButton
        {
            font-size: 8pt;
            icon-size: 16px;
        }

        QPushButton:hover
        {   
            color: black;
            background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #729fcf, stop:1 #d3d7cf);           
            border: 1px solid #b7b7b7 inset;
            border-radius: 3px;
        }
        QComboBox
        {
            font-size: 8pt;
        }
    """
###################################     
if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setApplicationName('MyWindow')
    main = MyWindow("")
    main.show()
    if len(sys.argv) > 1:
        print(sys.argv[1])
        main.fileOpenStartup(sys.argv[1])
    sys.exit(app.exec_())
Reply


Messages In This Thread
PyQt5 QTableView SQLite : edit cell - by HeinKurz - Mar-27-2023, 09:45 AM
RE: PyQt5 QTableView SQLite : edit cell - by Axel_Erfurt - Mar-27-2023, 10:04 AM

Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyQt] QStyledItemDelegate and QTableView malonn 1 1,733 Feb-07-2023, 07:15 PM
Last Post: malonn
  [PyQt] QTableView set header labels HeinKurz 2 7,403 Jan-23-2023, 08:46 AM
Last Post: HeinKurz
  [PyQt] Determine whether text in QTableView cell is fully visible or not random_nick 0 1,054 Oct-27-2022, 09:29 PM
Last Post: random_nick
  [PyQt] QTableView: scroll to top cell of the screen random_nick 2 3,018 Oct-08-2022, 12:29 AM
Last Post: random_nick
  [PyQt] [Solved]Add a Blank Row To QTableView Extra 3 5,851 Oct-02-2022, 04:53 PM
Last Post: Extra
  How to update the list of a combo box in a QTableView panoss 10 6,445 Feb-05-2022, 03:24 PM
Last Post: panoss
  [PyQt] How to Copy-Paste a table from Office apps to QTableView? Vittorio 5 7,467 Aug-05-2021, 11:14 AM
Last Post: Axel_Erfurt
  [PyQt] Qtableview adapte size to WBPYTHON 3 11,590 Mar-23-2020, 01:51 AM
Last Post: deanhystad
  PyQt5: How do you set the user input of a line edit to a specific variable? YoshikageKira 17 12,055 Dec-26-2019, 03:18 PM
Last Post: Denni
  Huge code problems (buttons(PyQt5),PyQt5 Threads, Windows etc) ZenWoR 0 2,911 Apr-06-2019, 11:15 PM
Last Post: ZenWoR

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020