Qt World Summit: Submit your Presentation

Model view insert row validation question isDirty()???

  • I have two sql relational tables and two delegates. The first model stores the recipes. The second table stores the join between recipe and ingredients. The second table has a proxy set to only show rows for each recipe. I am achieving this with a proxy model. This would be a left outer join.

    I have a sql relational table model with a delegate. What is the best way to prevent the user from adding more rows before the user specifies a value? I am using on manual submit. The first two columns are populated programmatically. The third column needs user input. I only want to submit the row once the user specifies a value. And I only want the user to be able to add a new row once the user defines the third column?

    Can I use isDirty() for this?

    self.join_model.dataChanged.connect(partial(self.submitrow, MissData = self.MissData))
    def submitrow(self, MissData):
        self.MissData = MissData
        # Do not evaluate value when GUI loads data on initalization
        if self.MissData == False:
            # Set this to true because the user entered a value identical to another CFR
            self.MissData = True
        if self.join_model.lastError().isValid():
            #print self.join_model.lastError().text()
            if self.join_model.lastError().text() == "columns planning_obj_id, cfr_lu_id are not unique Unable to fetch row":
                msg = "rows are not unique in the table"
                QtGui.QMessageBox.warning(self, "warning", msg, QtGui.QMessageBox.Ok)
                self.MissData = False
    def AddJoinRow(self):
            """this will allow one to add a row into the bottom model.
            This tool is a many to many relationship between recipes and ingrendents.
            Ingredients are popluated by the program. This is a many to many relationship.
            This tool has to models and two views the top model handles the recipes and
             the bottom model handles the ingredients.
            ## recipe row count
            recipe_count = self.obj_model.rowCount()
            ## this is to test if there is at least one recipe id.
            if recipe_count == 0:
                msg = "you must add a recipe before you can add a row to the join table."
                QtGui.QMessageBox.warning(self, "warning", msg, QtGui.QMessageBox.Ok)
            ## else there is at least one row in the recipe model.
                ## get the selected row in the recipe table.
                selected_index = self.obj_tableView.currentIndex()
                ## this tests if there is not a selected index in the recipe model.
                if not selected_index.isValid():
                    msg = "you must select a recipe row before adding a row in the "
                    QtGui.QMessageBox.warning(self, "warning", msg, QtGui.QMessageBox.Ok)
                ## else there is a selected index in the planning objective model.
                    ## get the row index of the selected recipe
                    row_index = selected_index.row()
                    max_id = 1
                    query = QtSql.QSqlQuery()
                    ##Query the join database table to get the max id
                    query.exec_("SELECT MAX(id) FROM join_recipe_ingredents")
                    if query.next():
                        max_id = query.value(0).toInt()[0]
                    ## query the recipe model to get the recipe id from the top model.
                    ## cannot use rowcount because a user can remove a row.
                    recipe_id = self.obj_model.data(self.obj_model.index(row_index, ID)).toInt()[0]
                    ## get the row count of the join table.
                    join_row = self.join_model.rowCount()
                    if join_row <4:
                        ## insert a row into the model.
                        ## set column 1 value to be the max id + 1
                        self.join_model.setData(self.join_model.index(0, JOIN_ID), max_id + 1)
                        ## set column 2 value to be the recipe_id
                        self.join_model.setData(self.join_model.index(0, PLANNING_ID), recipe_id)
                        ## column 3 is a combo box of all the ingrendents. I am using setRelation to populate this combobox.
                        msg = "Cannot have more than 4 rows"
                        QtGui.QMessageBox.warning(self, "warning", msg, QtGui.QMessageBox.Ok)

  • Lifetime Qt Champion


    Then why not use a dialog where you ask for the user input and only then update your database ?

  • That seems harder. Shouldn't I be able to do this within the same table?

  • Lifetime Qt Champion

    Sure you can, but it's not the table's role to ask for more information if something is missing.

  • Can I add a row to the model and only add it to the database when the user specifies a value? Isn't that what OnManualSubmit is for?

  • Maybe I am not asking the right question. How do you wait for the user to input a value and only then call submitAll? It cant be in the add row method because that would only get called when the user pushes the button to add a row. I need to wait and allow the user to choose a value before submitAll is called.

  • Lifetime Qt Champion

    If you have e.g. a button to add a new row, have a custom slot connected to the button clicked signal and in that slot request input from the user and only once your have it, add the row.

  • Do you have an example of this?