получение 2 комбобоксов, работающих с QDataWidgetMapper - PullRequest
0 голосов
/ 06 мая 2020

Пожалуйста, будьте добры. Это мой первый вопрос. Я включил минимальный список, который иллюстрирует проблему.

from PyQt5 import QtWidgets, QtCore, QtGui, uic, QtSql
from PyQt5.QtCore import Qt
qtCreatorFile = "QuotesGui.ui" 

Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)

class QuotesUI(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, model):
        QtWidgets.QMainWindow.__init__(self)
        uic.loadUi(qtCreatorFile,self)
        self.setupUi(self)
        self.model = model # View owns the model    


        self.tableView.setModel(self.model._formModel)

        self.setWidgetMapping() # Map model to view widgets

        authorSRD = QtSql.QSqlRelationalDelegate(self.authorComboBox)
        self.authorComboBox.setModel(self.model._authorModel)
        self.authorComboBox.setItemDelegate(authorSRD)
        self.authorComboBox.setModelColumn(
        self.model._formModel.fieldIndex("authorName"))

        citationSRD = QtSql.QSqlRelationalDelegate(self.citationComboBox)
        self.citationComboBox.setModel(self.model._citationModel)
        self.citationComboBox.setItemDelegate(citationSRD)
        self.citationComboBox.setModelColumn(
        self.model._formModel.fieldIndex("citationText"))

        self.mainMapper.toFirst()
        self._updateButtons(0) # To disable the previous button at start up
        self.saveBtn.setEnabled(False) # Since we can't edit, we can't save


        self._connectSignals(self.model)



    def setWidgetMapping(self):
        self.mainMapper = QtWidgets.QDataWidgetMapper(self)
        self.mainMapper.setModel(self.model._formModel)
        self.mainMapper.setItemDelegate(QtSql.QSqlRelationalDelegate(self))
        self.mainMapper.addMapping(self.authorComboBox,
            self.model._formModel.fieldIndex("authorName"))
        self.mainMapper.addMapping(self.citationComboBox,
            self.model._formModel.fieldIndex("citationText"))
        self.mainMapper.addMapping(self.quoteText,
            self.model._formModel.fieldIndex("quoteText"))


    def _connectSignals(self, model):
        self.lastBtn.clicked.connect(self.mainMapper.toLast)
        self.nextBtn.clicked.connect(self.mainMapper.toNext)
        self.prevBtn.clicked.connect(self.mainMapper.toPrevious)
        self.firstBtn.clicked.connect(self.mainMapper.toFirst)
        self.mainMapper.currentIndexChanged.connect(
            self._updateButtons)




    def _updateButtons(self, row):
        self.firstBtn.setEnabled(row > 0)
        self.prevBtn.setEnabled(row > 0)
        self.nextBtn.setEnabled(row < self.model._formModel.rowCount() - 1)
        self.lastBtn.setEnabled(row < self.model._formModel.rowCount() - 1)


class QuoteModel():
    def __init__(self, data):
        # Make a database connection
        self.db = self.createConnection(data)

        # set models
        self._setFormModel()
        self._setAuthorComboTableLink()
        self._setCitationComboTableLink()   

        # Connect signals
        self._connectSignals()

    # Define a model for the form
    def _setFormModel(self):
        self._formModel = QtSql.QSqlRelationalTableModel(
            parent = None, db = self.db)
        self._formModel.setEditStrategy(
            QtSql.QSqlTableModel.OnManualSubmit)
        self._formModel.setTable("Quote")
        authorIdx = self._formModel.fieldIndex("authorId")
        citationIdx = self._formModel.fieldIndex("citationId")
        self._formModel.setJoinMode(1) # Left Join
        self._formModel.setRelation(authorIdx, QtSql.QSqlRelation(
            "Author", "authorId", "authorName"))
        self._formModel.setRelation(citationIdx, QtSql.QSqlRelation(
            "Citation", "citationId", "citationText"))
        self._formModel.select()


     # Define models and link tables for the two comboboxes
     def _setAuthorComboTableLink(self):
        self._authorModel = QtSql.QSqlTableModel(
            parent = None, db =   self.db)
        self._authorModel.setTable("Author")
        self._authorModel.setEditStrategy(
            QtSql.QSqlTableModel.OnManualSubmit)
        self._authorModel.select()
        self._authorModel.sort(1,Qt.AscendingOrder) 

    def _setCitationComboTableLink(self):
        self._citationModel = QtSql.QSqlTableModel(
            parent = None, db = self.db)
        self._citationModel.setTable("Citation")
        self._citationModel.setEditStrategy(
            QtSql.QSqlTableModel.OnManualSubmit)
        self._citationModel.select()
        self._citationModel.sort(1,Qt.AscendingOrder)   

    def _newData(self):
        print('in _newData')

    def _connectSignals(self):
        self._authorModel.rowsInserted.connect(self._newData)


#######################################################     
    # A function to connect to a named database
    def createConnection(self,dbfile):
        db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
        db.setDatabaseName(dbfile)
        db.open()

        if not db.open():
            QtWidgets.QMessageBox.critical(
            None, QtWidgets.qApp.tr("Cannot open database"),
            QtWidgets.qApp.tr("Unable to establish a database   connection.\n"),
            QtWidgets.QMessageBox.Cancel,
            )
            return False

        return db

dbFile = "Quotations.db"

if __name__=='__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)

    m = QuoteModel(dbFile)

    w = QuotesUI(m)
    w.show()

    sys.exit(app.exec_())

По-прежнему требуется загрузить файл .ui размером 8 КБ и образец базы данных размером 70 КБ для запуска. Пока я не смог понять, как это сделать ....

Когда это запускается, включая остальную часть необходимого кода, поле со списком автора работает так, как ожидалось, то есть: в раскрывающемся списке отображается все значения в таблице авторов, и когда я шагаю по записям в модели, правильный автор отображается в поле со списком.

Поле со списком цитирования НЕ работает. Как написано здесь, он не показывает значения из таблицы цитирования и не связан с таблицей цитат. По сути, это ничего не показывает.

Думаю, мне каким-то образом нужен второй делегат модели. Но я не знаю, как.

Есть идеи, как заставить это работать ??

1 Ответ

0 голосов
/ 12 мая 2020

Чтобы сделать эту работу, мне пришлось изменить:

self.authorComboBox.setModel(self.model._authorModel)

на:

authorRel = self.model._formModel.relationModel(self.model.authorIdx)
self.authorComboBox.setModel(authorRel)

QSqlRelationalTableModel имеет виртуальную функцию «RelationshipModel», которая возвращает QSqlTableModel. Когда вы используете эту модель в качестве модели для QComboBox, все работает.

...