Zaznaczenie w QSqlTableModel na QTableView

Odpowiedz Nowy wątek
2019-03-14 20:31
0

Witam, mam problem, u mnie w aplikacji jest funkcja edit przez którą edytuję się pewien obiekt. Wszystko działało na podstawie zaznaczenia w TableView i przenoszenia to do modela jako w sumie ten sam rekord przez id,
dopóki nie dodałem do programu możliwość sortowania w w QTableViewie :( teraz niestety wybiera mi rekord inny niż jest zaznaczony, myślałem długo i nie mam pomysłu jak to rozwiązać.

void Supplies_menu::on_btnedit_clicked()
{

    ///QModelIndex index = ui->tableView->selectionModel()->selectedIndexes().first();
    //  ui->tableView->setSortingEnabled(true);
    if(ui->tableView->selectionModel()->hasSelection())
    {
        QModelIndex index = ui->tableView->selectionModel()->selectedIndexes().first();

        if (index.isValid())
        {
            int selectedRow;
            selectedRow = index.row();
            Adding *add = new Adding(selectedRow,this);
            add->setModal(true);
            add->database_open();
            add->exec();
            table_display();
        }

        else {QMessageBox::critical(this,"error","error");}

    }
    else {
        QMessageBox::information(this,"Selection","You haven't selected any index");
    }
}

void Supplies_menu::on_btndel_clicked()
{
    if(ui->tableView->selectionModel()->hasSelection())
    {
        QModelIndex index = ui->tableView->selectionModel()->selectedIndexes().first();

        if (index.isValid())
        {
            ////////////////////WPISZ TU DIALOG czxy jest siur
            int row = index.row();
            Adding *add = new Adding(row,this);
            add->database_open();
            add->database_delete();
            table_display();
        }
        else {
            QMessageBox::warning(this,"Selected Index","Your selection is wrong. Try again");
        }
    }
    else {
        QMessageBox::information(this,"Selection","You haven't selected any index");
    }
}
void Adding::database_edit()
{
    database_open();
    if(db.open())
    {
           query.prepare("SELECT * FROM produkty");
        MySqlTableModel *model = new  MySqlTableModel(this,db);
        query.exec();
        model->wywSetQuery(query);
        nm = model->record(IdInView).value("name").toString();
        nt = model->record(IdInView).value("notes").toString();
        QString Kc = model->record(IdInView).value("kcal").toString();
        QString Car = model->record(IdInView).value("carbonates").toString();
        QString Pro = model->record(IdInView).value("proteins").toString();
        QString Fa = model->record(IdInView).value("fats").toString();
        QString Wei = model->record(IdInView).value("weight").toString();
        dat = model->record(IdInView).value("date").toDate();
        iconT = model->record(IdInView).value("img").toByteArray();
        Type = model->record(IdInView).value("type").toString();
        IdInBase = model->record(IdInView).value("productid").toInt();

        ui->lnname->setText(nm);
        ui->lnnotes->setText(nt);
        ui->lnkcal->setText(Kc);
        ui->lncarbonates->setText(Car);
        ui->lnproteins->setText(Pro);
        ui->lnfats->setText(Fa);
        ui->lnweight->setText(Wei);

        if(Type=="1")
        {
            ui->btn1->setVisible(true);
            ui->btn2->setVisible(false);
            ui->btn3->setVisible(false);
            ui->btn4->setVisible(false);
        }
        else if(Type=="2")
        {
            ui->btn1->setVisible(false);
            ui->btn2->setVisible(true);
            ui->btn3->setVisible(false);
            ui->btn4->setVisible(false);
        }
        else if(Type=="3")
        {
            ui->btn1->setVisible(false);
            ui->btn2->setVisible(false);
            ui->btn3->setVisible(true);
            ui->btn4->setVisible(false);
        }
        else if(Type=="4")
        {
            ui->btn1->setVisible(false);
            ui->btn2->setVisible(false);
            ui->btn3->setVisible(false);
            ui->btn4->setVisible(true);
        }

        QImage image; image.loadFromData(iconT);
        ui->icon->setPixmap(QPixmap::fromImage(image));

        //img.loadFromData(Icon);
        // ui->icon->setPixmap(QPixmap::fromImage(img));

        // QVariant currentIcon = model->data(model->index(id,2),0);
        //  QByteArray bytes = currentIcon.toByteArray();

    }
    else QMessageBox::warning(this,"Connecting","Database conection failed!");
}

Tam potem jest dodawanie do database itd spokojnie ;)

Od razu zaznaczam że ledwo ja ogarniam co się w tym kodzie dzieje, bo go pisałem, wiem że jest masa redundancji, nieprawidłowych nazw czy zbędnego kodu ale nvm to pierwszy program, potem się poprawię ^^ - Xezolpl 2019-03-14 20:32

Pozostało 580 znaków

2019-03-16 12:46
0
MasterBLB napisał(a):
Xezolpl napisał(a):

Nie do końca rozumiem, mam numer rekordu w tableviewie który jest już posortowany czyli nie pokrywa się on z numerem w bazie danych więc dostaje przez to potem do edycji czy usunięcia inny obiekt niż zaznaczyłem w tableviewie. Jak za pomocą QSqlRecourdu?

A tak - QSqlRecord QSqlTableModel::record(int row) const. Za row podstawiasz to, co otrzymałeś z selectionModelu, QSqlRecord z kolei zagwarantuje powiązanie z rzeczywistym wierszem jaki siedzi w bazie danych.

No dobra ale teraz mam coś takiego jako QSqlRecord.

QSqlRecord rec = model->record(IdInView);

A dane pobieram, edytuje i wstawiam w formie

/*String*/  nm = model->record(IdInView).value("name").toString();

I później nm jest ustawiane textem lnedita z którego zczytuje dane i umieszczam je w bazie

Czyli muszę mieć tego rec jako inta - numer wiersza w bazie danych i potem IdInView ustawić na wartość tego inta

edytowany 2x, ostatnio: Xezolpl, 2019-03-16 12:48

Pozostało 580 znaków

2019-03-16 13:23
0

A więc nazywa się MySqlTableModel:

#ifndef MYSQLTABLEMODEL_H
#define MYSQLTABLEMODEL_H
#include <QSqlTableModel>
#include <QObject>

class MySqlTableModel : public QSqlTableModel
{
public:

    explicit MySqlTableModel( QObject *parent, QSqlDatabase db);

   void wywSetQuery(const QSqlQuery &query);
   QVariant MyheaderData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
};

#endif // MYSQLTABLEMODEL_H
#include "mysqltablemodel.h"

MySqlTableModel::MySqlTableModel(QObject *parent, QSqlDatabase db)
     : QSqlTableModel(parent, db)
 {

     db = db.isValid() ? db : QSqlDatabase::database();
 }

void  MySqlTableModel::wywSetQuery(const QSqlQuery &query)
{
   setQuery(query);//setQuery() jest protected, ale wywołujesz je wewnątrz metody klasy która odziedziczyła QSqlTableModel - dla tej klasy metoda setQuery() jest traktowana jak publiczna.
}
QVariant MySqlTableModel::MyheaderData(int section, Qt::Orientation orientation, int role) const
{
    if ((section==1)||(section==4)||(section==5)||(section==6)||(section==7)||(section==8))
    {

        if (role == Qt::InitialSortOrderRole) {

            return QVariant::fromValue(Qt::DescendingOrder);
        }
        else return QVariant::fromValue(Qt::AscendingOrder);
      }

}

A tu m.in jest używany bo nie ma sensu reszty pokazywać bo byłoby to koło 10funkcji. Tutaj stylizuję tą tabelę i modela oraz podpinam do tableViewa.

void Supplies_menu::table_display(int typ)
{
    ////STWORZENIE TABELI
    Adding *add = new Adding(rec,this);
    add->database_open();
    add->getDatabase(db2);

    QSqlQuery *query2= new QSqlQuery();
    if(typ==0)
    {
        query2->prepare("SELECT * FROM produkty ORDER BY weight");
                ui->tableView->sortByColumn(8);
    }
    else if(typ==1)
    {
        query2->prepare("SELECT * FROM produkty WHERE type=1 ORDER BY weight");
        ui->tableView->sortByColumn(8);
    }
    else if(typ==2)
    {
        query2->prepare("SELECT * FROM produkty WHERE type=2 ORDER BY weight");
        ui->tableView->sortByColumn(8);
    }
    else if(typ==3)
    {
        query2->prepare("SELECT * FROM produkty WHERE type=3 ORDER BY weight");
        ui->tableView->sortByColumn(8);
    }
    else if(typ==4)
    {
        query2->prepare("SELECT * FROM produkty WHERE type=4 ORDER BY weight");
        ui->tableView->sortByColumn(8);
    }
    query2->exec();
    MySqlTableModel *model = new MySqlTableModel(this,db2);

    /// STYLIZACJA TABELI I WKLADANIE BAZY DANYCH

    model->setEditStrategy(QSqlTableModel::OnFieldChange);
    model->wywSetQuery(*query2);
    ui->tableView->setModel(model);
    ui->tableView->hideColumn(0);
    ui->tableView->hideColumn(3);
    ui->tableView->hideColumn(10);
    ui->tableView->resizeColumnsToContents();
    ui->tableView->setColumnWidth(1,35);
    ui->tableView->setColumnWidth(2,222);
    ui->tableView->setColumnWidth(8,110);
    ui->tableView->setColumnWidth(9,75);
    ui->tableView->resizeRowsToContents();

    add->database_close();

    QSortFilterProxyModel *m=new QSortFilterProxyModel(this);
    m->setDynamicSortFilter(true);
    m->setSourceModel(model);
    ui->tableView->setModel(m);
    ui->tableView->setSortingEnabled(true);
    ui->tableView->sortByColumn(8,Qt::DescendingOrder);

}

Pozostało 580 znaków

2019-03-16 17:02
1
Xezolpl napisał(a):

Właśnie nie, liczyłem na to żeby domyślnie jak user kliknie na header jakiejś kolumny mu weszło na desc (czy tam na asc w drugiej) żeby mógł sobie klikać. Bo tak to mam na razie, może sobie klikać oraz zaczyna się tabela wyświetlać posortowana wg kolumny 8 i DESC.
Czyli zamierzany przeze mnie efekt jest nieosiągalny?

Spróbuj poustawiać tryb sortowana dla wybranych kolumn ZANIM podłączysz model do widoku.

tableView->sortByColumn(0, Qt::DescendingOrder);
tableView->sortByColumn(1, Qt::AscendingOrder);
/*...*/
tableView->setModel(model);

Co do opcji z reimplementacją model::headerData() to nie wiem czy o czymś zapomniałem, ale ni huhu nie mogę złapać roli Qt::InitialSortOrderRole. Tak jakby QTableView nigdy takiego żądania nie wysyłało. Może @MasterBLB wie coś wiecej :P

edytowany 1x, ostatnio: tajny_agent, 2019-03-16 17:03
Nie kijem go, to pałą. Przeimplementuj Bracie model::setHeaderData(), ciekawe czy wtedy nadal będzie się stawiał. - MasterBLB 2019-03-16 17:51

Pozostało 580 znaków

2019-03-16 17:21
0
tajny_agent napisał(a):
Xezolpl napisał(a):

Właśnie nie, liczyłem na to żeby domyślnie jak user kliknie na header jakiejś kolumny mu weszło na desc (czy tam na asc w drugiej) żeby mógł sobie klikać. Bo tak to mam na razie, może sobie klikać oraz zaczyna się tabela wyświetlać posortowana wg kolumny 8 i DESC.
Czyli zamierzany przeze mnie efekt jest nieosiągalny?

Spróbuj poustawiać tryb sortowana dla wybranych kolumn ZANIM podłączysz model do widoku.

tableView->sortByColumn(0, Qt::DescendingOrder);
tableView->sortByColumn(1, Qt::AscendingOrder);
/*...*/
tableView->setModel(model);

Co do opcji z reimplementacją model::headerData() to nie wiem czy o czymś zapomniałem, ale ni huhu nie mogę złapać roli Qt::InitialSortOrderRole. Tak jakby QTableView nigdy takiego żądania nie wysyłało. Może @MasterBLB wie coś wiecej :P

Niestety nadal to samo, zaczynają się wszystkie z ascending :/

Pozostało 580 znaków

2019-04-13 13:32
0
MasterBLB napisał(a):
Xezolpl napisał(a):

Nie do końca rozumiem, mam numer rekordu w tableviewie który jest już posortowany czyli nie pokrywa się on z numerem w bazie danych więc dostaje przez to potem do edycji czy usunięcia inny obiekt niż zaznaczyłem w tableviewie. Jak za pomocą QSqlRecourdu?

A tak - QSqlRecord QSqlTableModel::record(int row) const. Za row podstawiasz to, co otrzymałeś z selectionModelu, QSqlRecord z kolei zagwarantuje powiązanie z rzeczywistym wierszem jaki siedzi w bazie danych.

A co mogę zrobić jeśli mój model nie dziedziczy z QSqlTableModel tylko z QIdentityProxyModel i nie ma funkcji record?

Pozostało 580 znaków

2019-04-13 15:29
0

Od biedy możesz użyć funkcji sourceModel() (klik), żeby dostać się do modelu na którym działa proxy.
Ale wygodniej po prostu trzymać wskaźnik na model jako składową klasy.

Pozostało 580 znaków

2019-04-13 16:17
0
tajny_agent napisał(a):

Od biedy możesz użyć funkcji sourceModel() (klik), żeby dostać się do modelu na którym działa proxy.
Ale wygodniej po prostu trzymać wskaźnik na model jako składową klasy.

Ok, ustawiłem na wskaźnik, zrobiłem gettera do QSqlTableModelu

int x = ui->tableView->selectionModel()->selectedIndexes().first().row();
   QSqlRecord rec = dbManager->getSqlTableModel()->record(x);
   int id = rec.value("productid").toInt();
   qDebug() << id;

lecz mimo wszystko id jest z tableviewa nie z modelu czyli zaleznie od posortowania daje rozne wyniki dla pojedynczego produktu.

Pozostało 580 znaków

2019-04-13 16:59
0

Hmm, nie rozumiem. O to chodzi w sortowaniu :>

Pozostało 580 znaków

2019-04-13 17:07
0
tajny_agent napisał(a):

Hmm, nie rozumiem. O to chodzi w sortowaniu :>

Yyyy no to tak, mam baze danych w niej tabele z tymi produktami, a w programie tableviewa który ją wyświetla z modelu. Tableview ma sorting endabled i jak user klika sobie w headery to zmienia sobie sposob sortowania. Ja chce się dostac niezaleznie od posortowania do wlasciwego id zeby moc go zmienic w bazie gdy user go zaznaczy i kliknie przycisk (edytuj/usun)

Pozostało 580 znaków

2019-04-13 17:35

Jeśli używasz proxy to spróbuj najpierw zmapować indeks

auto proxyIndex = ui->tableView->selectionModel()->selectedIndexes().first();
auto x = proxyModel->mapToSource(proxyIndex).row();
   QSqlRecord rec = dbManager->getSqlTableModel()->record(x);
   int id = rec.value("productid").toInt();
   qDebug() << id;

QModelIndex QSortFilterProxyModel::mapToSource(const QModelIndex &proxyIndex) const

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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