Qstreamreader and treewidget problem



  • Hi,
    I have an xml file which contains:

    @
    <patients>
    <patient>
    <id>12345</id>
    <name>Γεώργιος</name>
    <surname> Παπαδάκης </surname>
    <birthdate><d>23</d><m>5</m><y>1954</y></birthdate>
    <admission_date><d>17</d><m>4</m><y>2010</y></admission_date>
    <clinical_department>Α’ Χειρουργική Κλινική</clinical_department>
    <ward>302</ward>
    <bed>3</bed>
    <primary_diagnosis>
    <icd9_code>155.0</icd9_code>
    <icd9_explanation>Malignant neoplasm of liver, primary</icd9_explanation>
    </primary_diagnosis>
    <surgical_operations>
    <operation>
    <oper_date><d>20</d><m>4</m><y>2010</y></oper_date>
    <description>μερική εκτομή ήπατος</description >
    </operation>
    <operation>
    <oper_date><d>27</d><m>4</m><y>2010</y></oper_date>
    <description>κάτι άλλο</description >
    </operation>
    </surgical_operations>
    </patient>

    <patient>

    </patient>
    <patient>

    </patient>
    <patients>
    @

    I want to read the file and put the surname and the birthdate in a tree widget that I have created.

    The code from which I read the file is :

    @
    QXmlStreamReader xml(file);
    while(!xml.atEnd() && !xml.hasError()) {
    QXmlStreamReader::TokenType token = xml.readNext();
    if(token == QXmlStreamReader::StartDocument) {
    continue;
    }
    if(token == QXmlStreamReader::StartElement) {
    if(xml.name() == "persons") {
    continue;
    }
    if(xml.name() == "person") {
    persons.append(this->parsePerson(xml));
    }
    if(xml.name() == "birthdate") {
    persons.append(this->parsePerson(xml));
    }

    QMap<QString, QString> QXSRExample::parsePerson(QXmlStreamReader& xml) {
    QMap<QString, QString> person;

    while(!(xml.tokenType() == QXmlStreamReader::EndElement &&
    xml.name() == "person")) {
    if(xml.tokenType() == QXmlStreamReader::StartElement) {
    if(xml.name() == "surname") {
    this->addElementDataToMap(xml, person);
    }
    if(xml.name() == "d") {
    this->addElementDataToMap(xml, person);
    }
    if(xml.name() == "m") {
    this->addElementDataToMap(xml, person);
    }
    if(xml.name() == "y") {
    this->addElementDataToMap(xml, person);
    }

        }   xml.readNext();
    }
    

    @

    How can I add the birthdate in the tree widget? It has 3 values like 2-3-11.

    [EDIT: code formatting, Volker]



  • First of all, I doubt the code above really parses the XML you give. In the code, you deal with elements called "person" and "persons", while in the XML these are called "patient" and "patients".

    Then on creating a date: your best bet would be to change the XML format, if that is an option for you. Just use the ISO standard for date formats, and don't make up your own this way. However, if you are fixed to this format, I would just create another function, just like you do to parse a person, to parse a date. You can use that function for each place where you encounter a date, like for a birth date and for the operation date. In that function, you simply collect the three values for day, month and year, and use the appropriate QDate constructor to create the correct QDate. You can add that date as a node in your tree widget.



  • You are right. I had change the name patient to person and i copied the wrong xml.
    I can't change the xml format because it is a project.

    I created another function for date as you said:

    @
    QMap<QString, QString> QXSRExample::parseDate(QXmlStreamReader& xml) {
    QMap<QString, QString> date;
    if(xml.tokenType() != QXmlStreamReader::StartElement &&
    (xml.name() == "birthdate" or xml.name()=="admission_date")) {
    return date;
    }
    QXmlStreamAttributes attributes = xml.attributes();
    if(attributes.hasAttribute("d")) {
    date["d"] = attributes.value("d").toString();
    }
    if(attributes.hasAttribute("m")) {
    date["m"] = attributes.value("m").toString();
    }
    if(attributes.hasAttribute("y")) {
    date["y"] = attributes.value("y").toString();
    }

    int d=date["d"];
    int m=date["m"];
    int y=date["y"];
    QDate birthdate= (y,m,d);
    

    }
    @

    but the QDate wants int and the date["d"],date["m"],date["y"] are QString
    and these int d=date["d"];
    int m=date["m"];
    int y=date["y"];
    have an error "cannot convert QString to int"

    What can I do?

    Edit: fixed the code tags; Andre



  • Well.... You might want to look into QString's huge array of conversion functions. Maybe, just maybe, you'll find a function that can convert a QString to an int. Note that in Qt, most conversion functions have a name that starts with "to" followed by the type you need. Check it out in the docs...

    Personally, I think your use of a QMap to store the parts of the date is a bit overdone. Why not store the results in the integers you have directly? Simply declare those integers at the top of your function and initialize them to 0. Then at the end of your function, check if any of them is still 0. If so, it is not a valid date.

    Note that an element is missing from your code: It does not feature the loop to cycle through the elements in your XML. Your XML defines the day, month and year as elements, not as attributes as you seem to think. So you need a loop similar to the one you use to parse a person, only this time to parse the date.



  • I have created the function parseDate as you told but I have a problem.
    The function is :

    @
    QMap<QString, QString> QXSRExample::parseDate(QXmlStreamReader& xml) {
    QMap<QString, QString> date;
    d=0;
    m=0;
    y=0;

    while(!(xml.tokenType() == QXmlStreamReader::EndElement &&
            xml.name() == "birthdate")) {
        if(xml.name() == "d"){
            d=date["d"].toInt();
        }
        if(xml.name() == "m")
            m=date["m"].toInt();
        if(xml.name() == "y"){
            y=date["y"].toInt();
       }
        xml.readNext();
    }
    format = "dd.MM.yyyy";
    str=QDate(y,m,d).toString(format);
    

    }
    @

    The problem is that the variables y,m,d don't get the values from xml.
    If i use d=xml.text(); is the same.
    If i use the command "str=QDate(2011,3,2).toString(format);" it works.
    What did i do wrong?



  • hi,

    are you sure you iterate correctly?

    @
    while(!(xml.tokenType() == QXmlStreamReader::EndElement &&
    xml.name() == "birthdate")) {
    @

    This loop breaks when the first tag not being birthdate is reached (e.g. a tag named d).

    Did you try to debug it?



  • To Gerolf: I think that statement is actually correct.

    To annatz:
    Well... isn't the mistake obvious?

    @
    if(xml.name() == "d"){
    d=date["d"].toInt();
    }
    @

    What does the code above actually do?
    It runs when xml.name() equals "d". Then what? It tries to convert a value that is supposedly in a map called date to an integer. However, that map is not initialized, and you don't actually use the value of the <d> element at all! Dump that QMap<QString, QString> completely, and then try to make your code work with just the XML.

    You should really learn to debug this kind of stuff for yourself. Just step through the code using a debugger and/or use qDebug() statements in your function to trace the values you get.

    Some more tips then:
    Give your parseDate function an additional argument that contains the element name the date is wrapped in, in this case "birthdate". That way, you can re-use the same function for reading an operation date, or any date encoded in this weird way for that matter. Second, I'd let the function return an actual QDate, not a QDate encoded to a string. If you need a string later on, encode it to that string then, but it is better to let a parseDate function actually return a date.



  • thanks.

    I have another question for the qtreewidget...

    I have created a qtree with three columns and when the user choose the patient from the list, it calls another function and from there i get the chosen name,surname or birthdate. But i want to pass through the function the id, not only the surname or name or birthdate. I want to use the id to search the xml and find unique patients.

    the code is:

    @ while(!patients2.isEmpty()) {
    QMap<QString,QString> patient = patients2.takeFirst();
    if (index==patient["clinical_department"]){
    QStringList columns;
    columns << patient["surname"] << patient["name"] << patient["birthdate"] << patient["id"];
    treeWidgetItem = new QTreeWidgetItem((QTreeWidget*)0, columns);
    tree->insertTopLevelItem(0, treeWidgetItem);
    }
    }
    item='0';

    connect(tree,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(details(QTreeWidgetItem*,int)));
    connect(tree,SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(highlighted(QTreeWidgetItem*,int)));
    }

    void QXSRExample::highlighted(QTreeWidgetItem* item2,int column2){
    item= item2->data(column2, Qt::DisplayRole).toString();
    }

    @



  • I don't get what the actual question is?

    Note that you can also put the ID in column 0, in a custom role.



  • how can i get the id to the highlighted function? in the first function i have created a treewidget with four columns, but if the user clicks at the surname of the patient to make his choice and not at the id, in the highlighted function i can get only the surname and if there are many patients with the same surname i have a problem.



  • First of all, because your data seems to be row-oriented, I would set the selection policy of your view to match that and have it select whole rows at a time.

    If you need the ID of the patient, you know you put that ID in column 3, right? So why are you looking at the column the user clicked on? Simply ignore the column number, and write line 17 like this:

    @
    item= item2->data(3, Qt::DisplayRole).toString();
    @



  • it works! i thought that it was more complicated.
    thanks


Log in to reply
 

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