Encoding in the QTableView



  • Really need help.

    My program is a SQL query area codes

    select city-code from country
    

    The results are displayed in QTableView.
    For example, the result code will be printed 1132.

    1. What I want: is it possible to to do the encoding of these codes? At the some point it should be specified 1132 = 'Toronto', and QTableView display text value corresponding to this code?

    That is, in another related file these codes do variable and QTableView not displayed codes and their meanings. How to do that? I really have no idea...

    1. How to make a text value assignment of numbers? I apologize for not knowing such a moment, but never met with such a task) And Google is not particularly give the correct answers.
      110 int = 'Toronto'; ?

    2. How do these variables would be concerned only this widget?


  • Qt Champions 2016

    hi
    Normally u would use SQL to return a query result where the
    country ID would be used to look up the name from another table.
    such as this
    http://www.w3schools.com/sql/sql_join.asp
    where customer ID is used to get the customer name.

    Its not really the job of QTableView as it just to view the data so its
    better to do before.

    Im not really sure what u ask in 3:
    sorry



  • @mrjj all this codes(10012, 10013 etc) are not in my DB. I will write them in the program or in the support *.txt file.
    I make sql query, then I see the result in QTableView. On example, smth like that:
    Toronto-----10012
    New York-----10013

    And I need convert that into the words. For example, 10012=Jackson, 10013=White, so the result must look so:
    Toronto-----Jackson
    New Yourk-----White


  • Qt Champions 2016

    ok. then you should look into a
    QAbstractItemDelegate custom class.
    like
    http://doc.qt.io/qt-5/qtwidgets-itemviews-stardelegate-example.html
    (here a value is mapped to some stars)

    the delegate can change what is displayed.

    So in ur case look up in some table the city name and display that instead.

    You must read about
    http://doc.qt.io/qt-5.5/model-view-programming.html

    to understand the roles of model, view and delegate.

    it's not an option to include the names in the DB?



  • @mrjj thank you, I will try.
    No, I should solve the problem this way :)


  • Qt Champions 2016

    @ro12man3
    ok. the first delegate can be slightly trick if u are not deeply into c++
    as it involved subclassing and virtual function override.
    looking at samples is a good idea.



  • @mrjj I have seen the link about star delegate, but I'm not sure how to edit that for me. Can you write simple code, please?
    And what to do if I have 40 codes that I will need to change?


  • Qt Champions 2016

    @ro12man3
    hi
    Delegates are a bit involved to code so small samples is not so easy.'
    The main concept for you would to be override
    http://doc.qt.io/qt-5.5/qstyleditemdelegate.html#displayText
    so when view ask how to show data , you can then
    replace the ID with the correct text.

    for 40 codes , you might need a lookup table as pure ifs
    if ( ID == 1000) return "CITY";
    will be a bit verbose :)


  • Lifetime Qt Champion

    Hi,

    You should build a hash of your data and use it to map your numbers to your city.



  • @SGaist if I understand you correctly, I need to use QHash, yes?


  • Qt Champions 2016



  • @mrjj thank you very much! But how integrate that with QTableView?


  • Qt Champions 2016

    @ro12man3
    well when u create your delegate object
    you also give it a Hash list with the town names.
    so in displayText()
    it can look up in the list the name to use from the number from DB.



  • @mrjj unfortunately, it doesn't work. I read that for solving that problem I need to change TableView to TableWidget and use QTableWidgetItem. How to change the numbers in that variant?


  • Qt Champions 2016

    @ro12man3 said:

    How to change the numbers in that variant?

    Hi Im not sure what you ask about ?

    QTableWidgetItem is not a variant.



  • @mrjj well... I talk about how to make changing the numbers to text in my tableview(or widget). I wrote

    QHash< int, QString> hash;
     hash.insert(100, "Jackson");
    

    and it doesn't change nothing in the table


  • Lifetime Qt Champion

    Where's that hash located ?
    Did you set your custom QStyledItem delegate on the correct column of your QTableView ?
    Are you sure that the volume contains the correct values ?



  • @SGaist this is the code

    void MainWindow::on_pushButton_clicked() // I click and the quiery result is showing in the qtableview
    {
    QSqlQueryModel * model = new QSqlQueryModel(0);
    QHash< int, QString> hash;
     hash.insert(100, "Jackson");
    model->setQuery("select city-codes from country");
    ui->tableView->setModel(model);
    }
    

  • Lifetime Qt Champion

    That hash is destroyed at the end of on_pushButton_clicked



  • @SGaist so what I need to do for the correct changing values in my tableview?
    Where I need to write the QHash function?


  • Lifetime Qt Champion

    Either in your QStyledItemDelegate or as @mrjj suggested pass it to the delegate e.g. at construction time.



  • @SGaist what will be more simple? Cause I don't know how to make that. Sorry about my not big skills in qt


  • Lifetime Qt Champion

    In your QStyledItemDelegate, read your file and build the hash with its content. Then in your displayText reimplementation return _hash.value(value.toInt(), tr("Not found"));


  • Qt Champions 2016

    @ro12man3
    hi
    Starting with models and view are not best intro to Qt.
    They are very powerful but does demand some c++ skills and reading the docs.

    Sometimes code is easier to understand so I made u sample with @SGaist help.

    It has a list of names and if it sees Lars, it replaced it with BANNED.
    For your code, you will use the hash to look up the name from the code.

    https://www.dropbox.com/s/vsiqjrr41jhafqo/myfirstview.zip?dl=0

    the key points to understand is:
    we make a new class to override the default behaviour

    class MyDelegate : public QStyledItemDelegate {
    public:
    MyDelegate(QObject* parent)
    : QStyledItemDelegate(parent) {}
    virtual QString displayText(const QVariant& value, const QLocale& locale) const;
    };

    We set this delegate ONLY to the column we need.

    • ui->tableView->setItemDelegateForColumn(0, new MyDelegate(this));

    the displayText is the key function.:

    QString MyDelegate::displayText(const QVariant& value, const QLocale& locale) const {
    if (value.toString().compare("Lars") == 0) // if found
    return "BANNED";
    else
    return value.toString(); // else just return data unchanged
    }

    Here u will replace the city-code with names using the hash.

    Hope this helps you.



  • @mrjj ohhh thank you! It works!! Thank you very much.

    But I have 40 values that I will need to change(if it will be in quiery result).

    1. I can't write 40 "else if".. "else if"... "else if".... That's unlogic.
    2. I need to write all that values in support *.txt file(or another, the main is a simple format for editing), cause if I will write all that values in the program and then I will need to add new values...That's will be very uncomfortable.

    I see the method of the working the function so:
    The function is searching the values(from *.txt file) that has a quiery result. If it will find, then it will change to another every value.

    But...how make that in reality?


  • Qt Champions 2016

    hi
    it sounds like your best way would to read in
    the text file to a hash.
    and use that hash in displayText
    I agree, using if for 40 values would be nasty :)

    How does your text file look like?



  • @mrjj I didn't create that file, cause I have no idea. Well, every variant will be good. The main is the working code :D

    Do you think that *.txt file should looks so:

    hash.insert("123", "Jack Sparrow");
    hash.insert("134", "Elvis Presley");
    hash.insert("201", "Walter White");
    ........
    

    ?


  • Qt Champions 2016

    @ro12man3
    Hi
    For me it sounds like you would have a text file with
    1000, NAME1
    1001, NAME2

    so when u see int 1000, u want "NAME" etc.

    So your task is to look at QFile and read in a text file with your format and stuff it into a hash.
    Then use it.



  • @mrjj ok, I understand how to read the file and search the values. I don't understand another thing.
    On example=, the function will read the .txt file and it will find some value. Let it be 2900.
    In txt file it will be looking:
    2900, "Jackson"

    How to convert to "Jackson"? I don't know how to write that in a hash. How the hash will look the "convert value"?


  • Qt Champions 2016

    @ro12man3
    say
    u define the hash like
    QHash<int, QString> Hash;
    it means we use int as key and get string as result
    so
    QString Name=hash[2900];
    would give us "Jackson" in name;

    please read doc on how it works.
    http://doc.qt.io/qt-5/qhash.html

    so you would read all lines from text file and insert into hash.



  • @mrjj woooow thank you! You are the master! :) I understand, very clever idea!

    I will try that in the morning.


  • Qt Champions 2016

    well for 40 lookups its more fun that tons of ifs
    if u make a text file with
    ID, NAME
    like
    1000, TOWN
    1001, TOWN2
    1002, TOWN3

    so u need to ( code handwritten fast, not tested. u need to add includes)

    QFile file("c:/mynames.txt");
    if(!file.open(QIODevice::ReadOnly)) {
    QMessageBox::information(0, "error", file.errorString());
    }

    QTextStream in(&file);
    while(!in.atEnd()) {
    QString line = in.readLine(); // get a line from file
    QStringList fields = line.split(","); <<< KEY point. we ask it to split the text at "," to a list
    /// now fields[0] is first part and fields[1] is rest
    // so
    hash[fields[0].toInt()] = fields[1] ; // store name under key
    }

    file.close();



  • @mrjj thank you very much!! I will try that. If I wiil edit this, I will write here the correct code.
    Thank you for your helping!


  • Qt Champions 2016

    @ro12man3
    You are very welcome.
    One note is that if u read in text lines then
    it will be text so u need to convert to int for the key if you
    define the hash like that.
    QHash<int, QString> Hash;
    something like
    hash[ fields[0].toInt() ]=xxx
    If it gives u grief , let me know as im not 100% sure of syntax as its free writing :)



  • @mrjj Well, I can extract the second field, but it will be all second fields.

    And I have edited the code:

    QString MyDelegate::displayText(const QVariant& value, const QLocale& locale) const {
           QString line;
            QFile file("C:/QT/Test text/1.txt");
            if(!file.open(QIODevice::ReadOnly))
                   qDebug() << "Error opening file";
            QTextStream in(&file);
    
            QHash<int, QString> hash;
    
             while(!in.atEnd()) {
             QString line = in.readLine(); 
             QStringList fields = line.split(","); 
             hash[fields[0].toInt()] = fields[1] ; 
      if (value.toString().compare(fields[0]) == 0)
        return fields[1];
      else
        return value.toString(); 
    }
    }
    

    And it doesn't work. How to solve that?
    It was working when I wrote

     if (value.toString().compare("1000") == 0)
        return "Jackson";
    

    If I write

    QMessageBox::information(this, fields[0], fields[1] );
    

    it is working, but it shows ALL values.


  • Qt Champions 2016

    @ro12man3 said:

    And it doesn't work. How to solve that?

    • You really have to provide more info that that :)
      if you insert qDebug() << "f1=" << fields[0] << "f2=" << fields[1];
      does it read in the data correctly ? this is critical.

    • Also you build the hash
      hash[fields[0].toInt()] = fields[1] ;
      but don't use it. ? You dont use it to look up the text.
      QString CityName = hash[value.toInt()];
      return CityName;

    • Also you mix reading in the file with compare value. that is wrong.
      You should not read it in displayText as it will then read file each time
      it draw that column. that is not so good.
      Make Hash a member of the class. (in .h) and just use it
      in displayText. then u can read it once and use it over and over.

    • Read in the text file in the constructor of the delegate;


  • Lifetime Qt Champion

    In addition to what @mrjj wrote: make the hash a member of your delegate.



  • @mrjj said:

    • You really have to provide more info that that :)
      if you insert qDebug() << "f1=" << fields[0] << "f2=" << fields[1];
      does it read in the data correctly ? this is critical.

    Yes, I can extract this values. I tested that in QMessageBox.
    More info... http://rghost.ru/7wFZPWC4v This is the project.
    Download link(http://rghost.ru/download/7wFZPWC4v/ccf2cf56d3bbd353e8db12f377907d858f261e23/ccf2cf56d3bbd353e8db12f377907d858f261e23/myfirstviewEDITED.rar)

    It's not very difficult code structure, I don't know why it's not working.


  • Lifetime Qt Champion

    Hi,

    Because it's not buildable as is.

    MyDelegate::MyDelegate(QObject *parent)
        : QStyledItemDelegate(parent)
    {
        QString line;
        QFile file("1.txt");
        if(file.open(QIODevice::ReadOnly)) {
            QTextStream in(&file);
            while(!in.atEnd()) {
                QString line = in.readLine(); // get a line from file
                QStringList fields = line.split(","); // KEY point. we ask it to split the text at "," to a list
                hash[fields[0].toInt()] = fields[1] ; // store name under key
            }
        } else {
            qDebug() << "Error opening file";
        }
    }
    
    // this is the key delegate function!
    QString MyDelegate::displayText(const QVariant& value, const QLocale& locale) const {
         return hash.value(value.toInt());
    }
    

    [edit: code cleanup SGaist]


  • Qt Champions 2016


Log in to reply
 

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