akeg
akeg

Reputation: 151

PyQt5.How can I change Table's content?

I am working on a customers record program,that will be used in beauty saloon.

My dialog window fill the table widget pretty well,but data is only attached to exact time,but not to the date.I simply have only one page in my table. So I need my table widget to be connected with the calendar, so I can choose the date by clicking on a number in my calendar and table fills with data for that exact day. And when I choose the date in dialog in "setDateTime" widget, data should be placed in the table for that exact day. Is it even possible to accomplish it with table widget? Perhaps the data that I create in dialog window should be saved and then be used by tablewidget.

So I have my main windowenter image description here Here is full code for it

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
    MainWindow.setObjectName("MainWindow")
    MainWindow.resize(860, 803)
    self.centralwidget = QtWidgets.QWidget(MainWindow)
    self.centralwidget.setObjectName("centralwidget")
    self.calendarWidget = QtWidgets.QCalendarWidget(self.centralwidget)
    self.calendarWidget.setGeometry(QtCore.QRect(0, 0, 331, 191))
    self.calendarWidget.setObjectName("calendarWidget")
    self.addclient = QtWidgets.QPushButton(self.centralwidget)
    self.addclient.setGeometry(QtCore.QRect(0, 350, 331, 81))
    font = QtGui.QFont()
    font.setFamily("Verdana")
    font.setPointSize(10)
    self.addclient.setFont(font)
    self.addclient.setObjectName("addclient")
    self.uslugi = QtWidgets.QPushButton(self.centralwidget)
    self.uslugi.setEnabled(True)
    self.uslugi.setGeometry(QtCore.QRect(0, 270, 331, 81))
    font = QtGui.QFont()
    font.setFamily("Verdana")
    font.setPointSize(10)
    self.uslugi.setFont(font)
    self.uslugi.setObjectName("uslugi")
    self.mastera = QtWidgets.QPushButton(self.centralwidget)
    self.mastera.setGeometry(QtCore.QRect(0, 190, 331, 81))
    font = QtGui.QFont()
    font.setFamily("Verdana")
    font.setPointSize(10)
    self.mastera.setFont(font)
    self.mastera.setObjectName("mastera")
    self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
    self.tableWidget.setGeometry(QtCore.QRect(330, 0, 521, 781))
    self.tableWidget.setObjectName("tableWidget")
    self.tableWidget.setColumnCount(5)
    self.tableWidget.setRowCount(25)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(0, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(1, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(2, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(3, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(4, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(5, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(6, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(7, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(8, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(9, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(10, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(11, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(12, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(13, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(14, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(15, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(16, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(17, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(18, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(19, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(20, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(21, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(22, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(23, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setVerticalHeaderItem(24, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    font = QtGui.QFont()
    font.setStyleStrategy(QtGui.QFont.PreferAntialias)
    item.setFont(font)
    self.tableWidget.setHorizontalHeaderItem(0, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setHorizontalHeaderItem(1, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setHorizontalHeaderItem(2, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setHorizontalHeaderItem(3, item)
    item = QtWidgets.QTableWidgetItem()
    self.tableWidget.setHorizontalHeaderItem(4, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(0, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(1, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(2, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(3, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(4, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(5, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(6, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(7, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(8, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(9, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(10, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(11, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(12, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(13, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(14, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(15, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(16, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(17, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(18, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(19, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(20, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(21, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(22, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(23, 0, item)
    item = QtWidgets.QTableWidgetItem()
    item.setTextAlignment(QtCore.Qt.AlignCenter)
    self.tableWidget.setItem(24, 0, item)
    MainWindow.setCentralWidget(self.centralwidget)
    self.statusbar = QtWidgets.QStatusBar(MainWindow)
    self.statusbar.setObjectName("statusbar")
    MainWindow.setStatusBar(self.statusbar)

    self.retranslateUi(MainWindow)
    QtCore.QMetaObject.connectSlotsByName(MainWindow)

Dialog window enter image description here

class Ui_Dialog(object):
def setupUi(self, Dialog):
    Dialog.setObjectName("Dialog")
    Dialog.resize(281, 176)
    self.comboBox = QtWidgets.QComboBox(Dialog)
    self.comboBox.setGeometry(QtCore.QRect(90, 10, 71, 22))
    self.comboBox.setObjectName("comboBox")
    self.comboBox.addItem("")
    self.comboBox_2 = QtWidgets.QComboBox(Dialog)
    self.comboBox_2.setGeometry(QtCore.QRect(10, 10, 71, 22))
    self.comboBox_2.setObjectName("comboBox_2")
    self.comboBox_2.addItem("")
    self.dateTimeEdit = QtWidgets.QDateTimeEdit(Dialog)
    self.dateTimeEdit.setGeometry(QtCore.QRect(10, 60, 194, 22))
    self.dateTimeEdit.setObjectName("dateTimeEdit")
    self.label_2 = QtWidgets.QLabel(Dialog)
    self.label_2.setGeometry(QtCore.QRect(10, 40, 91, 16))
    self.label_2.setObjectName("label_2")
    self.lineEdit = QtWidgets.QLineEdit(Dialog)
    self.lineEdit.setGeometry(QtCore.QRect(150, 110, 113, 20))
    self.lineEdit.setObjectName("lineEdit")
    self.label_3 = QtWidgets.QLabel(Dialog)
    self.label_3.setGeometry(QtCore.QRect(150, 90, 121, 16))
    self.label_3.setObjectName("label_3")
    self.lineEdit_2 = QtWidgets.QLineEdit(Dialog)
    self.lineEdit_2.setGeometry(QtCore.QRect(10, 110, 113, 20))
    self.lineEdit_2.setObjectName("lineEdit_2")
    self.label_4 = QtWidgets.QLabel(Dialog)
    self.label_4.setGeometry(QtCore.QRect(10, 90, 111, 16))
    self.label_4.setObjectName("label_4")
    self.pushButton = QtWidgets.QPushButton(Dialog)
    self.pushButton.setGeometry(QtCore.QRect(150, 140, 111, 23))
    self.pushButton.setObjectName("pushButton")
    self.pushButton_2 = QtWidgets.QPushButton(Dialog)
    self.pushButton_2.setGeometry(QtCore.QRect(10, 140, 111, 23))
    self.pushButton_2.setObjectName("pushButton_2")

    self.retranslateUi(Dialog)
    QtCore.QMetaObject.connectSlotsByName(Dialog)

def retranslateUi(self, Dialog):
    _translate = QtCore.QCoreApplication.translate
    Dialog.setWindowTitle(_translate("Dialog", "Новый клиент"))
    self.comboBox.setItemText(0, _translate("Dialog", "Услуга"))
    self.comboBox_2.setItemText(0, _translate("Dialog", "Мастер"))
    self.label_2.setText(_translate("Dialog", "Дата и время:"))
    self.label_3.setText(_translate("Dialog", "Контактный номер:"))
    self.label_4.setText(_translate("Dialog", "Имя клиента"))
    self.pushButton.setText(_translate("Dialog", "Добавить клиента"))
    self.pushButton_2.setText(_translate("Dialog", "Отмена записи"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())

Here is all the functions

import sys
from interface import *
from dialog import *
from Services import *
from MastersList import *

from PyQt5 import QtCore, QtGui, QtWidgets

class Dialog(QtWidgets.QDialog, Ui_Dialog):
    def __init__(self, parent=None):
        QtWidgets.QDialog.__init__(self, parent)
        self.setupUi(self)
        # cancel
        self.pushButton_2.clicked.connect(self.reject)
        # accept
        self.pushButton.clicked.connect(self.accept)
        self.dateTimeEdit.setDisplayFormat("d/M/yy hh:mm")

    def data(self):
        master = self.comboBox_2.currentText()
        service = self.comboBox.currentText()
        name = self.lineEdit_2.text()
        contact_number = self.lineEdit.text()
        time = self.dateTimeEdit.time()
        return master, service, name, contact_number, time

class Services(QtWidgets.QDialog,Ui_SForm):
    def __init__(self, parent=None):
        QtWidgets.QDialog.__init__(self, parent)
        self.setupUi(self)

class Masters(QtWidgets.QDialog,Ui_Form):
    def __init__(self, parent=None):
        QtWidgets.QDialog.__init__(self, parent)
        self.setupUi(self)

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.setupUi(self)
        self.addclient.clicked.connect(self.onAddClient)
        self.mastera.clicked.connect(self.AddMaster)
        self.uslugi.clicked.connect(self.AddService)
        self.masters = Masters(self)
        self.services = Services(self)
        self.dialog = Dialog(self)

        proxy = QtCore.QSortFilterProxyModel()
        proxy.setSourceModel(self.masters.tableWidget.model())
        proxy.setFilterRegExp(".*\S.*")
        self.dialog.comboBox_2.setModel(proxy)

        proxy2 = QtCore.QSortFilterProxyModel()
        proxy2.setFilterRegExp(".*\S.*")
        proxy2.setSourceModel(self.services.tableWidget.model())
        self.dialog.comboBox.setModel(proxy2)
        self.dialog.comboBox.setModelColumn(0)

    def AddService(self):
        self.services.show()

    def AddMaster(self):
        self.masters.show()

    def onAddClient(self):
        if self.dialog.exec_() == QtWidgets.QDialog.Accepted:
            master, service, name, contact_number, time = self.dialog.data()
            row = int(QtCore.QTime(8, 0).secsTo(time) / (30 * 60))
            if row >= 0:
                for k, text in enumerate([master, service, name, contact_number]):
                    self.tableWidget.setItem(row, k + 1, QtWidgets.QTableWidgetItem(text))


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

Upvotes: 2

Views: 4745

Answers (1)

eyllanesc
eyllanesc

Reputation: 243887

It is impossible to implement the logic with the model provided by QTableWidget since each time you add a term you increase the memory of the application. In your comment you say that you want to change the items, if you do that delete the previous data so you could not use it again.

The correct thing is to save the information in a file that can be a .xml, .csv, etc and then with some method to filter the information and display it, in addition to creating a method to update the data. A simple way to implement the above is to use a database, and a good option in this case is to use sqlite, in it you must create the table:

def createConnection():
    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName(QDir.current().filePath("data.db"))
    if not db.open():
        QMessageBox.critical(None, "Cannot open database",
                             "Unable to establish a database connection.\n"
                             "This example needs SQLite support. Please read "
                             "the Qt SQL driver documentation for information how "
                             "to build it.\n\n"
                             "Click Cancel to exit.",
                             QMessageBox.Cancel)
        return False

    query = QSqlQuery()
    query.exec("create table IF NOT EXISTS product(id INTEGER PRIMARY KEY AUTOINCREMENT, "
               "date_and_time DATETIME, master VARCHAR(140), service VARCHAR(140), name VARCHAR(140),"
               "Contact_Number VARCHAR(140))")

    return True

Then create a model that handles that type of data, Qt offers the QSqlTableModel class that handles that type of data. But for it to work correctly you must have a pre-set date format and in your case it is observed that it is 8:00, 8:30, ..., 20:00, ie hours from 8:00 to 20:00 spaced every half hour, for this we must validate the entry and round it to the correct values, in addition if there is only the data must be updated but must be created.

self.model = QSqlTableModel()
self.model.setTable("product")

def onAddClient(self):
    client = ClientDialog(self)
    proxy = QSortFilterProxyModel()
    proxy.setSourceModel(self.view.model())
    proxy.setFilterRegExp(".*\S.*")
    client.masterCombo.setModel(proxy)
    client.masterCombo.setModelColumn(2)
    client.serviceCombo.setModel(proxy)
    client.serviceCombo.setModelColumn(3)

    if client.exec_() == ClientDialog.Accepted:
        master, service, name, contact_number, datetime = client.data()
        time = datetime.time()
        if QTime(8, 0) > time or QTime(20, 0) < time:
            return
        datetime = QDateTime(datetime.date(), QTime(8, 0).addSecs(30*60*int(QTime(8, 0).secsTo(time)/(30*60))))
        print(datetime)
        query = QSqlQuery()
        query.prepare("SELECT * FROM product WHERE date_and_time=:date_and_time")
        query.bindValue(":date_and_time", datetime)
        query.exec_()
        if query.next():
            id = query.value(0)
            query.prepare("UPDATE product SET master= :master, service=:service, name=:name, "
                          "Contact_Number=:contact_number where id = :id")
            query.bindValue(":id", id)
        else:
            query.prepare("INSERT INTO product(date_and_time, master, service, name, Contact_Number)"
                          "VALUES (:date_and_time, :master, :service, :name, :contact_number)")
            query.bindValue(":date_and_time", datetime)
        query.bindValue(":master", master)
        query.bindValue(":service", service)
        query.bindValue(":name", name)
        query.bindValue(":contact_number", contact_number)
        if not query.exec_():
            query.lastError().text()
        self.onSelectDay(self.calendarWidget.selectedDate())

With the previous model will only fill the boxes that have data, but in your case you want all a table of 25 rows for it is created the following proxy:

class CustomProxyModel(QIdentityProxyModel):
    def __init__(self, c, *args, **kwargs):
        QIdentityProxyModel.__init__(self, *args, **kwargs)
        self.mapping = [None] * 25
        self.c = c

    def rowCount(self, parent=QModelIndex()):
        return 25

    def index(self, row, column, parent=QModelIndex()):
        return self.createIndex(row, column)

    def mapToSource(self, proxyIndex):
        if proxyIndex.isValid():
            r = self.mapping[proxyIndex.row()]
            if r is not None:
                return self.sourceModel().index(r, proxyIndex.column())
        return QModelIndex()

    def mapFromSource(self, sourceIndex):
        if sourceIndex.isValid():
            return self.createIndex(self.mapping.index(sourceIndex.row()), sourceIndex.column())
        return QModelIndex()

    def data(self, proxyIndex, role=Qt.DisplayRole):
        if not proxyIndex.isValid():
            return QVariant()

        val = QIdentityProxyModel.data(self, proxyIndex, role)
        if proxyIndex.column() == self.c:
            if role == Qt.DisplayRole:
                return QTime(8, 0).addSecs(30 * 60 * proxyIndex.row()).toString("h:mm")
        return val

    def flags(self, index):
        return QIdentityProxyModel.flags(self, index) | Qt.ItemIsEnabled

    def fixModel(self):
        self.layoutAboutToBeChanged.emit()
        self.mapping = [None] * 25
        for r in range(self.sourceModel().rowCount()):
            ix = self.sourceModel().index(r, self.c)
            data = self.sourceModel().data(ix)
            self.mapping[
                QTime(8, 0).secsTo(QDateTime.fromString(data.replace("T", " "), "yyyy-MM-dd hh:mm:ss.zzz").time()) // (
                    30 * 60)] = r
        self.layoutChanged.emit()

This table must be updated every time you click on a date to do so it connects the clicked signal and filters the data:

self.calendarWidget.clicked.connect(self.onSelectDay)

def onSelectDay(self, date):
    start = QDateTime(date)
    stop = start.addDays(1)
    self.model.setFilter("date_and_time BETWEEN DATETIME('{}') AND DATETIME('{}')".
                         format(start.toString("yyyy-MM-dd hh:mm:ss.zzz"),
                                stop.toString("yyyy-MM-dd hh:mm:ss.zzz")))
    self.model.select()
    self.proxy.fixModel()

Since with the QTableWidget could not implement the logic I created the GUI from scratch having the same functionalities that you have placed except the dialogs of Master and Service.

The complete code can be found on the following link

Upvotes: 3

Related Questions