Search code examples
c++qtqdomdocument

Qt c++ data from XML String not being displayed properly in QTableView after parsing


I have almost finished the program in this question, but the last problem right now is this:
There is missing information within the QTableView.

Below is the new code I have: (the header file and the input xml string is the same as in the question mentioned in the first line)

//mainwindow.cpp

#include "mainwindow.h"
#include <QLabel>
#include <QLayout>
#include <QDebug>
#include <QDomDocument>
#include <QRegularExpression>

static QRegularExpression Box_Code("B");
static QRegularExpression Cylinder_Code("C");

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      SServer(new QPushButton("Start Listening")),
      ContainerView(new QTableView),
      tcpServer(new QTcpServer),
      tcpSocket(new QTcpSocket)
{
    QStringList HeaderRow;
    HMod = new QStandardItemModel(this);
    HeaderRow.append("Pallet");
    HeaderRow.append("Container");
    HeaderRow.append("Code");
    HeaderRow.append("Height");
    HeaderRow.append("Breadth/Diameter");
    HeaderRow.append("Length");
    HeaderRow.append("Weight");
    HMod->setHorizontalHeaderLabels(HeaderRow);
    ContainerView->setModel(HMod);

    setWindowTitle("QTcpServer XML String Input");
    resize(800,300);

    connect(SServer, &QPushButton::clicked, this, &MainWindow::startServer);
    connect(tcpServer, &QTcpServer::newConnection, this, &MainWindow::handleConnection);
    connect(tcpSocket, &QTcpSocket::readyRead, this, &MainWindow::handleConnection);

    connect(HMod, SIGNAL(itemchanged(QStandardItem*)), this, SLOT(updateRow(QStandardItem*)));
    QLabel *Lab1(new QLabel("Listening on Port 6164"));
    QHBoxLayout *HB(new QHBoxLayout);
    QVBoxLayout *VB(new QVBoxLayout);
    HB->addWidget(SServer);
    HB->addWidget(Lab1);
    VB->addItem(HB);
    VB->addWidget(ContainerView);
    QWidget *window(new QWidget);
    window->setLayout(VB);
    setCentralWidget(window);
}

MainWindow::~MainWindow()
{
}

void MainWindow::startServer()
{
    if(!tcpServer->listen(QHostAddress::LocalHost, 6164)){
        qDebug() << "Error connecting to Server";
        tcpServer->close();
        return;
    } else {
        qDebug() << "Started Successfully";
    }
}

void MainWindow::handleConnection()
{
    tcpSocket = tcpServer->nextPendingConnection();
    qDebug() << "New Connection!";
    connect(tcpSocket, &QTcpSocket::readyRead, this, &MainWindow::readMessage);
}

void MainWindow::readMessage()
{
    ContainerView->clearSpans(); //clear table to prepare for new XMLString
    QByteArray buffer = tcpSocket->readAll();
    QString FromContainer = QString::fromUtf8(buffer);
    ReadXML(FromContainer);
}

void MainWindow::ReadXML(QString XMLString)
{
    QDomDocument Xml_String;
    Xml_String.setContent(XMLString);
    QDomElement Xml_Root = Xml_String.documentElement();
    if(Xml_Root.tagName() == "Pallets")
    {
        QDomElement Xml_Pallet = Xml_Root.firstChildElement();
        while(!Xml_Pallet.isNull())
        {
            if(Xml_Pallet.tagName() == "Pallet")
            {
                int PN = Xml_Pallet.attribute("Number").toInt(nullptr,10);
                QDomElement Box_Cyl = Xml_Pallet.firstChildElement();
                while(!Box_Cyl.isNull())
                {
                    if(Box_Cyl.tagName() == "Box")
                    {
                        QString BC = Box_Cyl.tagName();

                        QDomElement Box_Info = Box_Cyl.firstChildElement();
                        QString BCode = "";
                        int BH, BL, BB, BW;
                        while(!Box_Info.isNull())
                        {
                            if(Box_Info.tagName() == "Code")
                            {
                                BCode = Box_Info.text();
                            }
                            if(Box_Info.tagName() == "Height")
                            {
                                BH = Box_Info.text().toInt(nullptr,10);
                            }
                            if(Box_Info.tagName() == "Length")
                            {
                                BL = Box_Info.text().toInt(nullptr, 10);
                            }
                            if(Box_Info.tagName() == "Breadth")
                            {
                                BB = Box_Info.text().toInt(nullptr,10);
                            }
                            if(Box_Info.tagName() == "Weight")
                            {
                                BW = Box_Info.text().toInt(nullptr, 10);
                            }
                            Box_Info = Box_Info.nextSiblingElement();
                        }
                        Add_to_CV(BCode, BC, PN, BH, BB, BL, BW);
                    } else if(Box_Cyl.tagName() == "Cylinder")
                    {
                        QString CC = Box_Cyl.tagName();
                        QDomElement Cylinder_Info = Box_Cyl.firstChildElement();
                        QString CCode ="";
                        int CH, CD, CW;
                        while(!Cylinder_Info.isNull())
                        {
                            if(Cylinder_Info.tagName() == "Code")
                            {
                                CCode = Cylinder_Info.text();
                            }else if(Cylinder_Info.tagName() == "Height")
                            {
                                CH = Cylinder_Info.text().toInt(nullptr,10);
                            } else if(Cylinder_Info.tagName() == "Diameter")
                            {
                                CD = Cylinder_Info.text().toInt(nullptr,10);
                            } else if(Cylinder_Info.tagName() == "Weight")
                            {
                                CW = Cylinder_Info.text().toInt(nullptr, 10);
                            }
                            Cylinder_Info = Cylinder_Info.nextSiblingElement();
                        }
                        Add_to_CV(CCode, CC, PN, CH, CD, CW);
                    }
                    Box_Cyl = Box_Cyl.nextSiblingElement();
                }
            }
            Xml_Pallet = Xml_Pallet.nextSiblingElement();
        }
    }
}

void MainWindow::Add_to_CV(QString C, QString Con, int Pn, int Bh, int Bb, int Bl, int Bw)
{
    QList<QStandardItem*> row;
    QStandardItem *Pallet_Num_Item = new QStandardItem(Pn);
    QStandardItem *Container_Type = new QStandardItem(Con);
    QStandardItem *Box_Code = new QStandardItem(C);
    QStandardItem *Box_Height = new QStandardItem(Bh);
    QStandardItem *Box_Breadth = new QStandardItem(Bb);
    QStandardItem *Box_Length = new QStandardItem(Bl);
    QStandardItem *Box_Weight = new QStandardItem(Bw);
    row << Pallet_Num_Item << Container_Type << Box_Code << Box_Height << Box_Breadth << Box_Length << Box_Weight;
    HMod->appendRow(row);
}

void MainWindow::Add_to_CV(QString C, QString Con, int Pn, int Ch, int Cd, int Cw)
{
    QList<QStandardItem*> row;
    QStandardItem *Pallet_Num_Item = new QStandardItem(Pn);
    QStandardItem *Container_Type = new QStandardItem(Con);
    QStandardItem *Cylinder_Code = new QStandardItem(C);
    QStandardItem *Cylinder_Height = new QStandardItem(Ch);
    QStandardItem *Cylinder_Diameter = new QStandardItem(Cd);
    QStandardItem *Cylinder_Blank = new QStandardItem(" "); //Cylinder does not have a Length
    QStandardItem *Cylinder_Weight = new QStandardItem(Cw);
    row <<Pallet_Num_Item << Container_Type << Cylinder_Code << Cylinder_Height << Cylinder_Diameter << Cylinder_Blank << Cylinder_Weight;
    HMod->appendRow(row);
}

void MainWindow::updateRow(QStandardItem *item)
{
    QColor colour = Qt::white;
    int row = item->row();
    if (HMod->item(row, 2)->data(Qt::DisplayRole).toFloat() >= 200)
        colour = Qt::red;
    for (int col=0; col<4; col++)
        HMod->item(row, col)->setBackground(colour);
}

Currently, this gives the the following output:
Output1

If I alter the program so that ContainerView is a QTextEdit instead of a QTableView (I did this to troubleshoot so I know which values are not getting assigned a value), and then use the following code instead:

...
                        while(!Box_Info.isNull())
                        {
                            if(Box_Info.tagName() == "Code")
                            {
                                BCode = Box_Info.text();
                                ContainerView->append("Box Code: " + BCode);
                            }
                            if(Box_Info.tagName() == "Height")
                            {
                                BH = Box_Info.text().toInt(nullptr,10);
                                ContainerView->append("Box Height: " + QString::number(BH));
                            }
                            etc.
...

Then I get the following output:
Output2


Solution

  • Thanks for the Comment, Scheff's Cat.

    My mistake was indeed in the Add_to_CV function.

    It should have been:

    void MainWindow::Add_to_CV(QString C, QString Con, int Pn, int Bh, int Bb, int Bl, int Bw)
    {
        QList<QStandardItem*> row;
        QStandardItem *Pallet_Num_Item = new QStandardItem(QString::number(Pn));
        QStandardItem *Container_Type = new QStandardItem(Con);
        QStandardItem *Box_Code = new QStandardItem(C);
        QStandardItem *Box_Height = new QStandardItem(QString::number(Bh));
        QStandardItem *Box_Breadth = new QStandardItem(QString::number(Bb));
        QStandardItem *Box_Length = new QStandardItem(QString::number(Bl));
        QStandardItem *Box_Weight = new QStandardItem(QString::number(Bw));
        row << Pallet_Num_Item << Container_Type << Box_Code << Box_Height << Box_Breadth << Box_Length << Box_Weight;
        HMod->appendRow(row);
    }
    
    void MainWindow::Add_to_CV(QString C, QString Con, int Pn, int Ch, int Cd, int Cw)
    {
        QList<QStandardItem*> row;
        QStandardItem *Pallet_Num_Item = new QStandardItem(QString::number(Pn));
        QStandardItem *Container_Type = new QStandardItem(Con);
        QStandardItem *Cylinder_Code = new QStandardItem(C);
        QStandardItem *Cylinder_Height = new QStandardItem(QString::number(Ch));
        QStandardItem *Cylinder_Diameter = new QStandardItem(QString::number(Cd));
        QStandardItem *Cylinder_Blank = new QStandardItem(" "); //Cylinder does not have a Length
        QStandardItem *Cylinder_Weight = new QStandardItem(QString::number(Cw));
        row <<Pallet_Num_Item << Container_Type << Cylinder_Code << Cylinder_Height << Cylinder_Diameter << Cylinder_Blank << Cylinder_Weight;
        HMod->appendRow(row);
    }
    

    When initializing the QStandardItem's, it needed to instantiate them using an QString. I had them being initialized using an int.

    Thanks for the help.