XML Data into QTableView: Some Problems: Empty Table, Messed up Header Data etc.



  • ++++
    EDIT: Updated / Changed the Code Samples to reflect the changes I currently use. Sorry for misleading Stuff. Had a lot of old leftovers.
    ++++
    Hello Forum.

    I still have a few Problems with pulling Data from the XML File to the QTableView.
    The XML File content is:

    <?xml version="1.0" encoding="UTF-8"?>
    <Bundesland>
    <Stadt>Hannover</Stadt>
    <Stadtteil>Ahlem</Stadtteil>
    <Ratstyp>Bezirksrat</Ratstyp>
    <Name>Ronja Robbersdaughter</Name>
    <Adresse>Mustergasse 12</Adresse>
    <EMail>mail@testeintrag.de</EMail>
    <TelefonFestnetz>9876543210</TelefonFestnetz>
    <TelefonMobil>0123456789</TelefonMobil>
    <FraktionsUrl>fraktion.musterlink.de </FraktionsUrl>
    <RISUrl>ris.musterlink.de</RISUrl>
    <OpenAntragStatus>Nein</OpenAntragStatus>
    <EintragNummer>001</EintragNummer>
    </Bundesland>
    

    The QStandardItemModel HorizontalHeaderItems are set up that way:

    modelForTableViewMainView= new QStandardItemModel(0,12,this);
    modelForTableViewMainView->setHorizontalHeaderItem(0, new QStandardItem(QString("Stadt")));
    modelForTableViewMainView->setHorizontalHeaderItem(1, new QStandardItem(QString("Stadtteil")));
    modelForTableViewMainView->setHorizontalHeaderItem(2, new QStandardItem(QString("Ratstyp")));
    modelForTableViewMainView->setHorizontalHeaderItem(3, new QStandardItem(QString("Name MT/FR/AK")));
    modelForTableViewMainView->setHorizontalHeaderItem(4, new QStandardItem(QString("Adresse")));
    modelForTableViewMainView->setHorizontalHeaderItem(5, new QStandardItem(QString("eMail")));
    modelForTableViewMainView->setHorizontalHeaderItem(6, new QStandardItem(QString("Telefon Festnetz")));
    modelForTableViewMainView->setHorizontalHeaderItem(7, new QStandardItem(QString("Telefon Mobil")));
    modelForTableViewMainView->setHorizontalHeaderItem(8, new QStandardItem(QString("Link Webseite")));
    modelForTableViewMainView->setHorizontalHeaderItem(9, new QStandardItem(QString("Link Ratsinformationsystem")));
    modelForTableViewMainView->setHorizontalHeaderItem(10, new QStandardItem(QString("OpenAntrag Nutzung")));
    modelForTableViewMainView->setHorizontalHeaderItem(11, new QStandardItem(QString("Eintragnummer (ID)")));
    

    And this is how I try to read the Data from the XML File and put it in the QTableView:

    void CDatabase::readManuallySelectedFederalStateFile(const QString &FileToOpenFileString)
    {
        //Reset and re-setup the Models Header Data...
        resetAllTableViewEntries();
    
        QFile currentlySelectedFederalStateXMLFile(FileToOpenFileString);
        currentlySelectedFederalStateXMLFile.open(QIODevice::ReadOnly | QFile::Text);
        QXmlStreamReader xmlReader;
        xmlReader.setDevice(&currentlySelectedFederalStateXMLFile);
        if(xmlReader.device()->isOpen())
        {
           qDebug() << currentlySelectedFederalStateXMLFile.fileName() << "is OPEN!";
           if(!xmlReader.device()->isOpen())
           {
            qDebug() << "ERROR:" << currentlySelectedFederalStateXMLFile.fileName() << "is CLOSED!";
           }
         }
    
        if(currentlySelectedFederalStateXMLFile.error())
        {qDebug() <<"File:" << currentlySelectedFederalStateXMLFile.fileName() << "Error:" << currentlySelectedFederalStateXMLFile.errorString();
        }
        if(xmlReader.hasError())
         {
             qDebug() << xmlReader.errorString();
         }
    
         while(!xmlReader.atEnd())
         {
             QXmlStreamReader::TokenType token = xmlReader.readNext();
    
             if(token == QXmlStreamReader::StartDocument)
             {
             continue;
             }
    
             if(token == QXmlStreamReader::StartElement)
             {continue;
             }
                 //BUG Read Data are not filled into the TableView...
                 if(xmlReader.name() == "Bundesland")
                 {
                 QMessageBox::information(this,"Abschnitt 'Bundesland'", "Wurde gefunden");
                 continue;
                 }
    
                 //FIXME Clear Index but NOT Header Item(s), when the FederalState File has been changed...
                 if(xmlReader.name() == "Stadt")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),0), xmlReader.readElementText());
                 }
                 if(xmlReader.name() == "Stadtteil")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),1), xmlReader.readElementText());
                 }
                 if(xmlReader.name() == "Ratstyp")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),2), xmlReader.readElementText());
                 }
    
                 if(xmlReader.name() == "Name")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),3), xmlReader.readElementText());
                 }
    
                 if(xmlReader.name() == "Adresse")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),4), xmlReader.readElementText());
                 }
    
                 if(xmlReader.name() == "EMail")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),5), xmlReader.readElementText());
                 }
    
                 if(xmlReader.name() == "TelefonFestnetz")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),6), xmlReader.readElementText());
                 }
    
                 if(xmlReader.name() == "TelefonMobil")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),7), xmlReader.readElementText());
                 }
    
                 if(xmlReader.name() == "FraktionsUrl")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),8), xmlReader.readElementText());
                 }
    
                 if(xmlReader.name() == "RISUrl")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),9), xmlReader.readElementText());
                 }
    
                 if(xmlReader.name() == "OpenAntragStatus")
                 {
                     modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                     modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),10), xmlReader.readElementText());
                 }
    
                 if(xmlReader.name() == "EintragNummer")
                 {
                    QMessageBox::information(this,"Abschnitt 'EintragNummer'", "Wurde gefunden");
                    modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
                    modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),11), xmlReader.readElementText());
                 }
    
             if(xmlReader.hasError())
             {
                     QMessageBox::critical(this, "XML Parse Error",xmlReader.errorString(), QMessageBox::Ok);
             }
    
             if(xmlReader.atEnd())
             {
                 currentlySelectedFederalStateXMLFile.close();
                 qDebug() << currentlySelectedFederalStateXMLFile.fileName() << "xmlReader.atEnd() reached!";
                 
             }}
             xmlReader.clear();
             currentlySelectedFederalStateXMLFile.close();
    
             if(currentlySelectedFederalStateXMLFile.isOpen())
             {
               currentlySelectedFederalStateXMLFile.close();
               qDebug() << currentlySelectedFederalStateXMLFile.fileName() << "closed after reading";
             }
    }
    

    The Problems I have:
    After reading the Data from the XML File:
    1.) In the TableView, the HeaderDataItem get created like:
    Stadt / Stadtteil / Ratstyp /... / EintragNummer / 13 / 14 / (up to 24) (the Amount of read Entries in the XML File)

    2.) The Table itself is Empty: No Data show up.

    3.) More like a Question: If I read another XML File (with the same Structure), how I can I reset the Table Data without resetting / deleting the HeaderData (as they stay the same).

    Thanks People :)
    Oliver


  • Moderators

    @MeerMusik Probably it is going into infinite loop because of the first statement in while loop.



  • Hello.

    Sorry for the late reply.
    You are right - the first "continue;" Statement the everything into an infinite Loop.

    Now the XML Files and Data are correctly read.
    Another Problem that I still have: 10 Rows for 10 XML Names - so far so good. But the Data dont show up in the TableView. Must have the wrong SetData or Index Parameter as it looks. But this is for another Day.

    Good Night
    Oliver



  • --
    EDIT: Sorry I meant QListView the whole time. Not QTableView! I tested a QTableView first. Must have gotten stuck somehow in my Head

    Hello again.

    I still have the Problem that the Data, that get read from the XML File, will not be added in Column 0, Column 1 etc. But instead they are added after the last manually added HeaderItem. How can I correct this? And what did I wrong, that the (existent and found) Entries in the XML File, does not get added to the QListView Index?

    Here is a Screenshot:
    Screenshot

    Thanks!
    Oliver


  • Moderators

    @MeerMusik Are you sure it is a QListView ? Because QListView doesn't have columns. It represents a list.



  • @p3c0 You are right. It is a QTableView. //DoubleFacePalm

    In a hurry, I changed the title wrong. It was for a similar Topic in a different Forum. And some descriptions in the Code are copied from another "playground" Sorry. Head is off today.


  • Moderators

    @MeerMusik That's fine :) We too have been there :)
    Shouldn't you use appendRow instead of setHorizontalHeaderItem ? setHorizontalHeaderItem as the name says works on header.



  • @p3c0 appendRow puts a "hard-coded" list into the Table. But the Data, that should be put into the Table, are in the XML File. So this is not exactly what I want. Putting and getting hundreds of Names, Adresses, Links etc. into and from a QList<QStandardItem *> is just too much.
    ++
    I have setup the Horizontal Labels now. All are in correct order. So the Horizontal Labels are fine - for now.

    1 (or more?) Problem(s) still exists: After a lot of Code changes, I am sure that this Part is somehow wrong:

    if(xmlReader.name() == "Stadt")
    {
      modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
      modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),0), xmlReader.readElementText());
    }
    //And so on for the other Names in the XML Files.
    

    As 12 additional Labels [Labeled 13 to 24] get added after "Eintragnummer (ID)" [the last Name in the XML File], when xmlReader.readElementText() has been executed. One Label per Name in the XML File. But what I want here is:

    All Data found in the XML File which i.e.:

    • Have the Name "Stadt" should be put in Column 0, Row 0 (and ongoing).
    • Have the Name "Stadtteil" should be in Column 1, Row 0 (and ongoing).

    As with the rest of the Database Entries.

    Can it be, that I have mixed up / twisted some parts of QTableView and the Model for the QTableView?

    Thanks for your patience!!



  • Alright.

    When I try:

    if(xmlReader.name() == "Stadt")
    {
    //New Part - Start
    QString lolopolo;
    lolopolo = xmlReader.readElementText();
    QMessageBox::information(this, "Teste Abfrage Stadt:", lolopolo);
    //New Part - End
    
    modelForTableViewMainView->insertColumn(modelForTableViewMainView->columnCount());
    modelForTableViewMainView->setData(modelForTableViewMainView->index(modelForTableViewMainView->columnCount(),0), xmlReader.readElementText());
    }
    

    The QMessageBox shows the correct Element Text.
    But I am stuck right now, how to put the read Element Text into the QTable.

    I think, I try to play around with reading the Database File to a QStringList and put everything from there into the TableView. Not sure if this will work.

    Any Hint(s) where I did a fatal Error, would be appreciated :)
    Oliver


  • Lifetime Qt Champion

    Hi,

    You are trying to access an index that doesn't exist. Indexes goes from 0 to columnCount() - 1 (same rule applies for rows)



  • @SGaist
    Ouch. I thought by using it this way, I set up a new Index. sigh
    And what is the correct way? The QXmlStreamReader should be fine for this. Or not?


  • Lifetime Qt Champion

    It won't because you are asking an index for a column that doesn't exist. Just call the function with the correct value for column and you'll be fine. No problem with the use of QXmlStreamReader



  • @SGaist

    Oh my. My schizophrenic Brain make such easy things some times really hard. C++ is absolutely different than Delphi.
    With the following code, it finally reads the first Entry in the XML File:

    if(xmlReader.name() == "Stadt")
    {
        QString setItemTestCity;
        setItemTestCity = xmlReader.readElementText();
    
        xmlReader.readElementText();
        QMessageBox::information(this, "Teste Abfrage Stadt:", setItemTestCity);
        modelForTableViewMainView->setItem(0,0, new QStandardItem(setItemTestCity));
    }
    

    Next step: Pull more than 1 "Stadt" Entry from the XML File.

    Thanks :)


  • Lifetime Qt Champion

    You old technique, basically, was good, it was just missing the -1 to get the last available column



  • @SGaist The problem was, I was too dumb to see where to put the "-1". :(

    Now I must find a way to read not only 1 but all "Stadt" Elements.


  • Lifetime Qt Champion

    Follow the XBel example, it should give you what you need



  • @SGaist Thanks for the hint. I will take a look at it - tomorrow. Good night. And thanks for being continuously helpful and patient :) I am sure I will be back.

    Oliver



  • Hello.

    I decided to try my Luck for one more time without the XBEL Example. The following Code (Snippet) puts the Data from the XML File in the QTableView:

    if(xmlReader.name() == "Stadt")
    {
    QString setItemTestStadt;
    setItemTestStadt = xmlReader.readElementText();
    
    int row = tableViewMainViewIndex.row();
    int column = tableViewMainViewIndex.column();
    row = 0;
    column = 0;
    
    QStandardItem *item = new QStandardItem(QString(setItemTestStadt));
    modelForTableViewMainView->insertRow(xmlReader.readElementText().count());
    modelForTableViewMainView->setData(modelForTableViewMainView->index(row,column,tableViewMainViewIndex), xmlReader.readElementText());
    modelForTableViewMainView->setItem(row, column, item);
    }
    

    Cant believe that I have been so close for 2 weeks. //Facepalm

    <s>Next "Problem" that I have: The Header Labels are correctly resized to fit their Content. But the Items Text is not. Already looked through the Web and through the Forum. Do I really have to subClass $Something?

    Currently I try the following Settings:

    tableViewMainView->setVisible(false);
    QRect originalViewport = tableViewMainView->viewport()->geometry();
    QRect newViewport = originalViewport;
    newViewport.setWidth(std::numeric_limits<int>::max());
     tableViewMainView->viewport()->setGeometry(newViewport);
     tableViewMainView->resizeRowsToContents();
     tableViewMainView->resizeColumnsToContents();
     tableViewMainView->viewport()->setGeometry(originalViewport);
     tableViewMainView->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents);
     tableViewMainView->verticalHeader()->resizeSections(QHeaderView::ResizeToContents);
    
    //And after reading the Data into the TableView
    tableViewMainView->setVisible(true);
    ```</s>
    EDIT: Never  mind. I forgot that that I must call resetColumnsToContents each time I update the TableView.
    
    Thanks again :)
    Oliver


  • Morning Folks.

    A new Question:

    I have different Views where the different Data from the XML File get split. 1 thing I will try is:
    When

    • Row 0 in tableViewMainView is active / selected, then select
    • all Items in Row 0 in tableViewAdditionalInfo

    I tried different things but no luck yet.

    //Not sure which Slot to use. Or if any of those SLOTs are even correct.
    connect(tableViewMainView,SIGNAL(pressed(QModelIndex)),this,SLOT(selectCurrentRowDependingOnTableViewMainView()));
    //What I try right now:
    tableViewMainView->setSelectionBehavior(QAbstractItemView::SelectRows);
    tableViewAdditionalInfo->setSelectionBehavior(QAbstractItemView::SelectRows);
    
    int selectedRow;
    selectedRow = tableViewMainView->rowAt(tableViewMainViewIndex.row());
    tableViewMainView->rowAt(tableViewMainViewIndex.row());
    
    tableViewAdditionalInfo->selectRow(selectedRow);
    

    Thanks



  • And another Problem.
    I want to display the Text of the XML Element "Name" in 2 different Views. But the Rows 0 + Column + of the 2nd View stay empty:

    if(xmlReader.name() == "Name")
    {
    //Set the Name in first View:
    QString setItemName;
    setItemName = xmlReader.readElementText();
    int row1 = tableViewMainViewIndex.row();
    int column1 = tableViewMainViewIndex.column();
    row1 = 0;
    column1 = 3;
    QStandardItem *item = new QStandardItem(QString(setItemName));
    modelForTableViewMainView->insertRows(modelForTableViewMainView->rowCount(),  xmlReader.readElementText().count(), tableViewMainViewIndex);
    modelForTableViewMainView->setData(modelForTableViewMainView->index(row1,column1,tableViewMainViewIndex), xmlReader.readElementText());
    modelForTableViewMainView->setItem(row1, column1, item);
    if(xmlReader.readElementText().isEmpty())
    {
    xmlReader.readNext();
    }
    
    //Set the Name in the 2nd View:
    QString setItemName2;
    setItemName2 = xmlReader.readElementText();
    int row2 = tableViewAdditionalInfoIndex.row();
    int column2 = tableViewAdditionalInfoIndex.column();
    row2 = 0;
    column2 = 0;
    QStandardItem *item2 = new QStandardItem(QString(setItemName2));
    modelForTableViewAdditionalInfo->insertRow(xmlReader.readElementText().count(), tableViewAdditionalInfoIndex);
                     modelForTableViewAdditionalInfo->setData(modelForTableViewAdditionalInfo->index(row2,column2,tableViewAdditionalInfoIndex), xmlReader.readElementText());
    modelForTableViewAdditionalInfo->setItem(row2, column2, item2);
    if(xmlReader.readElementText().isEmpty())
    {
    xmlReader.readNext();
    }
    }
    

    I am not sure whats wrong. Even calling the "xmlReader.name() == "Name" at a later point , let the cells stay empty.
    ++++
    EDIT: I finally found a workaround:

    //Instead of:
    QStandardItem *item2 = new QStandardItem(QString(setItemName2));
    //I do:
    QStandardItem *item2 = new QStandardItem(modelForTableViewMainView->item(0,3)->text());
    

    But I still have the Problem mentioned 2 posts above: How can I select 2 Rows in different Views simultaneously?

    Any hint is welcome :)


  • Lifetime Qt Champion

    You can use the first view selectionChanged signal and then the second view selection model to do what you want.



  • Morning.

    I connected the tableViewMainView:

    connect(tableViewMainView->selectionModel(),SIGNAL(selectionChanged(QItemSelection,QItemSelection)),this,SLOT(selectCurrentRowDependingOnTableViewMainView()));
    

    I try to scrollTo() by using the following Method:

    void CDatabase::selectCurrentRowDependingOnTableViewMainView()
    {
    QPoint pos;
    int row=tableViewMainView->rowAt(pos.y());
    int column=tableViewMainView->columnAt(pos.x());
    if(modelForTableViewMainView->item(row,column)->isSelectable())
    {
    QModelIndex selectedRow1Index=modelForTableViewMainView->index(row,column);
    tableViewAdditionalInfo->scrollTo(selectedRow1Index,QAbstractItemView::EnsureVisible);
    }
    }
    

    I get no Error Messages but it still does not work as intended.


  • Lifetime Qt Champion

    Should the items rows/cols from the second view be the same has the one from the main view ?



  • Evening.
    What I want is:

    • If I select any Column in Row 0 in Table 1 = select Row 0 in Table 2
    • If I select any Column in Row 5 in Table 1 = select Row 5 in Table 2
      etc. etc.

  • Lifetime Qt Champion

    In that case, use the QItemSelection parameters from the selectionChanged signal to retrieve these rows you want to select


Log in to reply
 

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