[Решен]ListView SQL как да получа ID?



  • Здравейте :)
    Имам следната ситуация:
    Таблица Song_tbl, в която имам следните колони - ID, Name, Lyrics, Genre.
    В Dialog съм сложила listView и следният код:
    @ QSqlQueryModel *model = new QSqlQueryModel;
    model->setQuery("Select Name from Song_tbl");
    ui->listView->setModel(model);
    ui->listView->show();@
    като резултат се изписват имената на песните в списък.
    Въпросът ми е, има ли начин, когато името на някоя песен е кликнато да ми се отваря друг Dialog, в който да се изпълнява заявка от типа "select lyrics from song where id = parameter_passed_from_the_clicked_Item".
    Kак да получа id-то на избрания/кликнатия елемент?



  • Ох, и аз се занимавах скоро с такива неща.
    Краткия отговор е да, може.

    @
    QModelIndex index = model->index(ui->tableView->selectionModel()->selectedRows().at(0).row(), 0, QModelIndex());
    QString id = ui->tableView->model()->data(index).toString();
    @

    Това е което аз съм ползвал. Направил съм при клик на коя да е колона да избира целия ред. Пробвай какъв ще е изхода при теб с qDebug(), предполагам ще е аналогично на това което съм ползвал аз.

    Edit: Сори, при мен е tableView, а ти питаш за listView, но все пак мисля че решението ще е аналогично.



  • Благодаря за бързия отговор :)
    Ето какво правя аз:
    на ListView(така или иначе в него са само имената, тъй че би трябвало да си се избира правилният ред) в слот on_listView_clicked написах
    @void Songs::on_listView_clicked(const QModelIndex &index)
    {
    QString id = ui->listView->model()->data(index).toString();
    qDebug() << id;
    }@
    Резултатът е, че като кликна на името на песента, ми се изписва отново името на песента.
    Идея как да получа директно ID-то? (или къде бъркам/не съм разбрала твоя код)



  • Според мен в този случай или трябва да намериш ID-то от името на песентта, или да използваш tableView където да можеш да добавиш и id и име и каквото е необходимо още в различни "клетки". Това е което аз правя на практика - извеждам информацията от базата данни (в моя случай се записва в ini файл), визуализирам я и при избор търся по уникални идентификатори с които да обработвам по- нататък. При мен няма никакъв user-interaction и информацията е сигурно че не може да съдържа еднакви стойности в два различни записа.

    В listView-то ако не се лъжа е възможно да имаш само една стойност която да ти бъде върната. Може би можеш да провериш вариант при който имаш скрита стойност която да прихванеш с помощта на parent() и children() и в която да се съдържа "скрита" стойност с ID-то(което може да звучи странно за някой който не се е занимавал с уеб разработки ;-) ), или по- добре - да си създадеш списък (QMap, QHash) в който да добавиш id-то за "ключ" и името на песента за стойност, съответно да претърсваш списъка за ключа посредством стойността.

    Сори, наистина не съм сигурен за listView, честно казано за него сигурно знам по- малко от колкото ти знаеш, тъй като не съм се занимавал с тях особено до сега (не ми се е налагало). Предполагам че някой друг ще може да ти помогне със сигурност, това е с което аз мога да помогна.



  • Кой индекс търсиш? Пореден номер в "QListView":http://doc.qt.nokia.com/latest/qlistview.html или някакво ID от таблицата в базата данни?

    Честно казно нямам особен опит с QListView, но ако само ти трябва поредния номер на селектирания ред в списъка вероятно нещо от сорта ще свърши работа:
    @
    void Songs::on_listView_clicked(const QModelIndex &index)
    {
    int nIndex = index.row();
    qDebug() << nIndex;
    }
    @



  • Търся ID-то в базата данни. Май няма директен начин да се получи, за това мисля да го търся с помощта на друг селект(select id from Song_tbl where Name = :PName). Може ли да ми кажеш как да предам параметърът в заявката?
    Преди съм ползвала борланд с++ билдер и там се използваше ParamByName, но не мога да открия еквивалента му тук.



  • Здравей,

    Ти пълниш модела само с данни от колоната Name от Song_tbl, така че няма как после от него да вземеш данните за ID-то.
    Трябва да заредиш в модела Name и ID и да показваш само колоната за име на песента. А когато се кликне на него си взимаш от модела ID-то за съответният ред.



  • Искаш да замениш :PName с името на песента предполагам.

    @
    QSqlQuery query;
    query.prepare("select id from Song_tbl where Name = ?");
    query.addBindValue(<променливата с името на песента като стринг>);
    query.exec();
    @

    Можеш да ползваш и placeholders:
    @
    query.prepare("select id from Song_tbl where Name = :PName");
    query.bindValue(":PName",<променливата с името на песента като стринг>);
    @

    Edit: Аз докато напиша... оказва се че има и по- лесен вариант :D
    Заради това казах в другата тема че ми е рано още, искам да натрупам повече опит като Qt разработчик първо :)



  • [quote author="aleksandra" date="1314098534"]Търся ID-то в базата данни. Май няма директен начин да се получи, за това мисля да го търся с помощта на друг селект(select id from Song_tbl where Name = :PName). Може ли да ми кажеш как да предам параметърът в заявката?
    Преди съм ползвала борланд с++ билдер и там се използваше ParamByName, но не мога да открия еквивалента му тук.[/quote]

    ОК, този проблем може да се разреши по няколко начина. Най-стандартните, за които се сещам веднага са да правих 2-ра заявка до БД или да направих буферна структура от данни, в която да запазиш име и id, за да имаш само една заявка.

    SQLite ли ползваш?

    Ако ползваш SQLite тези статии ще са ти полезни, за да видиш как да правиш select и да предаваш параметър:
    http://www.developer.nokia.com/Community/Wiki/CS001509_-Selecting_data_from_a_database_without_using_SQL_statements_in_Qt
    http://www.developer.nokia.com/Community/Wiki/CS001507
    -_Searching_for_data_in_a_database_in_Qt

    P.S.

    @task_struct и аз докато напиша отговор вече имаше 2 нови съобщения :)



  • Не е лошо, нека си помагаме, нека има мнения :D



  • Много се радвам на всички отговори :)
    Ползвам SQLite, ще пиша пак, като тествам дадените предложения :)



  • @void Songs::on_listView_clicked(const QModelIndex &index)
    {

    QString PName=index.data().toString() ;
    QSqlQuery query;
    QSqlQueryModel *model = new QSqlQueryModel;
    query.prepare("select id from Song_tbl where Name = :PName");
    query.bindValue(":PName",PName);
    query.exec&#40;&#41;;
    model->setQuery(query);
    ui->tableView->setModel(model);
    ui->tableView->show();
    

    }@
    това е кодът, който дава този красив резултат:!http://imageshack.us/photo/my-images/689/dosega.jpg/()!
    Много благодаря за отговорите и се надявам да се включите в следващата тема, която ще отворя за прегледност, защото е друг въпросът :)



  • Темата от операционната система ли идва? Много яко изглежда.
    На по- късен етап може би ще прегледаш варианта който предложи task_struct. Той каза че може да вземеш id и име с една заявка към базата и да ги заредиш в модела от където после можеш да ги изкараш. Аз лично ще трябва да поразгледам пак моделите....



  • [quote author="aleksandra" date="1314104474"]това е кодът, който дава този красив резултат:!http://imageshack.us/photo/my-images/689/dosega.jpg/()!
    Много благодаря за отговорите и се надявам да се включите в следващата тема, която ще отворя за прегледност, защото е друг въпросът :)[/quote]

    Честито и браво, че си разрешила проблема :)

    Редактирах заглавието и сложих решен и solved към таговете на темата ;)



  • Предложението на task_struct е много логично, но поне аз доколкото разбирам, е приложимо само ако имам tableView, защото в модела на listView мога да слагам само елементите от един списък.
    Темата идва от симулатора на Qt за нокия :)



  • QSqlQueryModel e създаден да се показва в QTableView, защото наследява QAbstractTableModel. Нищо не пречи да избереш 2 колони от таблицата и да кажеш на QListView да показва едната. Това става "така":http://doc.trolltech.com/4.7-snapshot/qlistview.html#modelColumn-prop . В момента при теб просто показва първата колона, защото по подразбиране е 0.



  • Мне, не е така, той говори за МОДЕЛА като цяло, не казва нищоз а listView или tableView. Идеята е че модела може да има повече информация от това което визуализираш. Но докато не пробвам и аз дали е така - не мога да твърдя със сигурност :D
    И май е крайно време и аз да се позанимая с симбиян/мииго/андроид разработките :D
    (то с тая идея си купих и нов телефон наскоро дори ;-) )



  • [quote author="task_struct" date="1314105824"]QSqlQueryModel e създаден да се показва в QTableView, защото наследява QAbstractTableModel. Нищо не пречи да избереш 2 колони от таблицата и да кажеш на QListView да показва едната. Това става "така":http://doc.trolltech.com/4.7-snapshot/qlistview.html#modelColumn-prop . В момента при теб просто показва първата колона, защото по подразбиране е 0.[/quote]
    опитах по каквъв ли не начин да променя 0 на 1, но явно нямам правилния подход. Когато използвам PropertyEditor-а, стойността не иска да се промени на 1(натисна ли enter се връща на 0), а когато се опитам да го направя с код
    @ ui->listView->setModelColumn(1);@
    просто нищо не се променя. Как става променянето?



  • Промени ли заявката към базата да връща двете колони вместо една?
    @
    QSqlQueryModel *model = new QSqlQueryModel;
    model->setQuery("Select Name from Song_tbl");
    ui->listView->setModel(model);
    @

    да стане така:

    @
    QSqlQueryModel *model = new QSqlQueryModel;
    model->setQuery("Select id, Name from Song_tbl");
    ui->listView->setModel(model);
    @



  • да, но се показват само ID-тата, за да се показва само името, трябва да променя property-то на listView, това не знам как да стане :)



  • @
    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    #include <QtSql/QSqlQueryModel>
    #include <QtSql/QSqlError>

    #include <QDebug>

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
    db.setHostName("localhost");
    db.setUserName( "nikolay" );
    db.setPassword( "*************" );
    db.setDatabaseName("Forum");
    
    bool ok = db.open();
    
    if( ok ) {
        qDebug() << "Database opened!!!";
    
        QSqlQueryModel *model = new QSqlQueryModel( this );
        model->setQuery("SELECT * FROM posts", db);
    
        ui->tableView->setModel( model );
        ui->listView->setModel( model );
        ui->listView->setModelColumn( 4 );
    
        connect( ui->pushButton_2, SIGNAL( clicked() ), qApp, SLOT(quit()) );
    }
    else {
        qDebug() << db.lastError().text();
    
        qApp->quit();
    }
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }
    @

    Този код при мен работи.



  • Видях къде ми беше грешката- бях сложила
    @ui->listView->setModelColumn(1); @
    преди
    @ui->listView->setModel( model ); @
    и за това не се получаваше.
    Благодаря за примера :)
    Все пак отново изникна проблема, как да взема ID-то като стойност от тази единствена заявка?



  • "http://doc.qt.nokia.com/latest/qsqlquerymodel.html#data":http://doc.qt.nokia.com/latest/qsqlquerymodel.html#data

    Вземаш индекса на избрания ред (по- горе в примерните кодове го обсъждахме това) и го вадиш от модела по тоя начин.



  • Като взема индекса получавам името на песента. Тогава пак ще опра до 2-рия селект,за да извадя ID, а нали сега идеята е той да се избегне.



  • При намирането на индекса можеш да зададеш коя колона от записите ти трябва. Ако 0 е id-то, 1 е името на песента, трябва да избереш 0. Чакай да видя дали ще мога да изровя малко код.

    @
    QSqlQueryModel *q = new QSqlQueryModel(this);

    q->index(ui->listView->selectionModel()->selectedRows().at(0).row(),0,QModelIndex());
    

    @

    Набързо го написах това, само модела за да може да ми даде аутокомплийта.
    В метода "index" на QSqlQueryModel има три параметъра - ред, колона, родителски индекс. Последния мисля че не е задлжителен. Реда го вземаш от listView-то си, колоната я слагаш такава каквато трябва да отговаря на информацията подадена към модела.

    Това е, но нямам много опит в тея модели, може и да греша.



  • @
    void MainWindow::onClickedSlot( const QModelIndex &index )
    {
    if ( m_model ) { qDebug() << "TTTTTTTTT"; }

    if( index.isValid() )
    {
    

    // qDebug() << m_model->record( index.row() ).value("post").toString();

        qDebug() << ui->listView->model()->data( ui->listView->model()->index( index.row(), 0 ) ).toString();
    
    }
    else
    {
        qDebug() << "invalid index";
    }
    

    }
    @

    Малко се забавих, но реда, който е коментира нещо гърми, заради достъпа до m_model :( m_model е private член на MainWindow, но нещо не го достъпва. За това измислих, другият начин. Изглежда грозничко, но работи. При теб "post" трябва да бъде заменено с ID, ако този ред ти проработи.



  • :) супер, още не мога да осмисля логиката, но вече работи :)))



  • Надявам се да съм бил полезен, макар че колегата task_struct май свърши по- добра работа ;-)



  • Ще се опитам да го обясня.
    Данните в модела се индексират с като матрица - ред, колона и те са независими от представянето им ( различните вюта не ги променят ). Така когато потребителя натисне ред в QListView се създава QModelIndex за този ред и колона, зададена през setModelColumn. На теб обаче ти трябват данните от друга колона, за това използваме index.row() и колоната си я задаваме сами. В нашият случай е 0.

    Решението с record().value() мисля, че е по-добро, защото там се използва хеш таблица с имената на колоните и ако си смениш броя на колоните в таблицата в базата данни, няма да се наложи да си променяш програмата.



  • И аз се оглеждах за тоя record, понеже знам че в заявките към базата ползват нещо подобно и е по- добре от колкото да пишеш само цифрите, едно заради улесняване на промените, но и заради по- лесното разбиране на написания код от друг човек (примерно, макар че много пъти и сам съм се чудил на себе си какви съм ги творил :D).
    Това което аз имах предвид е именно същото което ти обясни току-що. Знам принципа на действие, но не знам причините :D



  • За така наречените "magic numbers" решението е да се използват константи.

    В С:
    @
    #define SmislenoIme stojnost
    @

    В С++:
    @
    static const type SmislenoIme = stojnost;
    @

    или
    @
    static const type SmislenoIme(stojnost);
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.