Qt - Usuwanie wierszy w QSqlQueryModel

1

kolega @MarekR22 w tym poście podsunął mi pomysł na dodawanie i usuwanie wierszy poprzez odświeżenie modelu.

Zrobiłem dodawanie wierszy w ten sposób:

klasa mysqlquerymodel.h

class MySqlQueryModel : public QSqlQueryModel
{
//jakieś tam deklaracje składowych klasy

public slots:
    void addRow();
    void remRow();
};

plik mysqlquerymodel.cpp

void MySqlQueryModel::addRow()
{
    QSqlQuery lastID, addRecord;
    QString strLastID="SELECT pZamowienia FROM tZamowienia2";
    lastID.prepare(strLastID);
    lastID.exec();
    lastID.isSelect();
    int i=0, id;
    while(lastID.next()){
        i++;
    }
    QModelIndex idx;
    QVariant getId, setId, saveId;
    idx = index((i-1),0,QModelIndex());
    getId = idx.data();
    id = getId.toString().toInt();

//    insertRows(0,1,QModelIndex());

    if(lastID.last()){
        setId = id+1;
        saveId = setId.toString();

        addRecord.prepare("INSERT INTO tZamowienia2 (pZamowienia) VALUES (?)");
        addRecord.addBindValue(saveId);
        addRecord.exec();
    }
    else if(lastID.last()==false){
        addRecord.prepare("INSERT INTO tZamowienia2 (pZamowienia) VALUES ('1')");
        addRecord.exec();
    }

    refresh();
}

void MySqlQueryModel::refresh()
{
    setQuery("SELECT * FROM tZamowienia2");
    setHeaderData(0,Qt::Horizontal,QVariant(QString(QObject::tr("Lp"))),Qt::EditRole);
    //qDebug()<<"odświeżam";
}

dodawanie wierszy działa elegancko. Ale mam problem z usuwaniem wierszy i oto co zrobiłem.

w pliku mainwindow.h gdzie wyświetlam widok za pomocą QTableView zrobiłem sobie slota który pobiera numer wiersza i komórki które zostały kliknięte przez usera

private slots:
    inline int SelectItemTable(void)
    {
        QItemSelectionModel *select = TblView->selectionModel();
        QModelIndexList index = select->selectedIndexes();

        for(int i=0;i<index.size();i++)
        {
            row = index[i].row();
            col = index[i].column();
            //qDebug() << "wiersz" << row << ", kolumna" << col;
        }
        qDebug()<<"wybrany wiersz to" << row;
        return row;
    }

w pliku mainwindow.cpp zrobiłem "connecta" do tego slota

    TblView = new QTableView();
    QObject::connect(TblView, SIGNAL(clicked(const QModelIndex &)),this,SLOT(SelectItemTable(void)));
    TblView->setModel(MyModel);

widać co zostało kliknięte. Natomiast wartość row znajdującą się w slocie chciałbym móc przesłać do klasy mysqlquerymodel i zrobić z tego użytek. Domyślam się, że trzeba zrobić jakiś sygnał ? Ale nie mam pojęcia o tworzeniu sygnałów.

Kombinowałem z wywołaniem funkcji ale przy wywołaniu funkcji mam wartość zero i wartość która była kliknięta nie jest przesyłana. Planuję zrobić takie usuwanie rekordów jeżeli uda mi się przesłać klikniętą komórkę do mojej klasy

void MySqlQueryModel::remRow()
{
    QSqlQuery removeRow;
    removeRow.prepare("DELETE FROM tZamowienia2 WHERE pZamowienia = (?)");
    //removeRow.addBindValue("8"); <- tutaj wstawię wartość która zostanie odebrana ze slota
    removeRow.exec();

    refresh();
}

Czy powiedzielibyście co trzeba zrobić aby wartość kliknięta w tabeli znalazła się w tej klasie ?

0

Potrzeba ci podpiąć się pod sygnał QTableView::clicked(const QModelIndex &index), numer wiersza wyłuskasz sobie z indexu.

1

Bardzo dziękuję za wszystkie odpowiedzi w tym temacie, dzięki waszym podpowiedziom zrobiłem dodawanie i usuwanie wierszy. Powyżej przedstawiłem slota który dodaje wiersze, a w tym poście przedstawię slota który usuwa wiersze.

Na początek w klasie mysqlquerymodel.h musiałem sobie zdefiniować slota getRow

public slots:
    void addRow();
    void remRow();

    inline void getRow(QModelIndex _getRow){
        //qDebug()<< "klikniety wiersz" << _getRow.row();
        row = _getRow.row();
    }

Następnie w pliku mainwindow.cpp musiałem dodać drugiego connecta

    TblView = new QTableView(); //![1]
    QObject::connect(TblView, SIGNAL(clicked(const QModelIndex &)),this,SLOT(SelectItemTable(void)));
//********** poniżej drugi connect który musiałem zdefiniować
    QObject::connect(TblView, SIGNAL(clicked(const QModelIndex &)), MyModel, SLOT(getRow(QModelIndex)));
//**********
    TblView->setModel(MyModel); //![2]
    TblView->setItemDelegateForColumn(1, myDelegate); //![3]

w mainwindow.cpp podpięcie slota usuwania rekordu który ma wywołać kliknięcie przycisku

QObject::connect(ButtRemove, SIGNAL(clicked(bool)), MyModel, SLOT(remRow()));

i na koniec w mysqlquerymodel.cpp przyszła pora na napisanie slota który rzeczywiście usunie wybrane wiersze na podstawie tego co kliknął user na widoku tabeli

void MySqlQueryModel::remRow()
{
    QModelIndex idx;
    QVariant getDataId;

    QSqlQuery currentID, removeRow;
    QString strCurrentID="SELECT pZamowienia FROM tZamowienia2";
    currentID.prepare(strCurrentID);
    currentID.exec();
    currentID.isSelect();

    int i=0;
    while(currentID.next()){
        i=currentID.at();
        if(i==row){
            idx = index(i,0,QModelIndex());
            getDataId = idx.data();
            //qDebug()<<"wybrano wiersz"<<getDataId.toString();
        }
    }

    removeRow.prepare("DELETE FROM tZamowienia2 WHERE pZamowienia = (?)");
    removeRow.addBindValue(getDataId);
    removeRow.exec();

    //qDebug()<<"usuwam wiersz" << idx.row();

    refresh();
}

rozwiązanie mi się podoba i działa wyśmienicie ale mam niedosyt, gdyż tak naprawdę są funkcje wirtualne, które trzeba przesłonić swoimi - jak na razie nie umiem tego zrobić ale oto ten zestaw, który tak naprawdę powinien być użyty zamiast powyższych które napisałem

    bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
    bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
0

Eeee, przekombinowałeś, wystarczyło przerobić na slot removeRowa:

voidMySqlQueryModel::remRow(const QModelIndex &clickedIndex)
{
...
   if (i == clickedIndex.row())
   {
        .......
   }
....
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1