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(¤tlySelectedFederalStateXMLFile); 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 -
@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 HeadHello 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:
ScreenshotThanks!
Oliver -
@MeerMusik Are you sure it is a
QListView
? BecauseQListView
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.
-
@MeerMusik That's fine :) We too have been there :)
Shouldn't you use appendRow instead ofsetHorizontalHeaderItem
?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 -
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? -
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
-
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 :)
-
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.
-
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 :)