Qt

Qt is cross platform library for graphical user interfaces writen in C++. It offers many classes for Databases, Network and Graphics. The C++ compilers are available for embedded devices. Native user interfaces is a strength of Qt compared to Java or Python.

Many KDE software is based on Qt libraries. Other examples are lyx and qutebrowser software. The integrated development environments QtCreator and KDevelop a very good. A downside is the extra complexity introduced by the Meta Object Compiler. The Meta Object Compiler (Moc) is used to implement a Signal/Slot connection between QObjects.

Data Binding with Models and Views

In Qt the GUI Widgets can be bound to abstract models. This separates the model from the view. The example shows an abstract model of XML data bound to a QTreeView. The XQueries can be replaced by SQL, REST or any other data model.

Qt.png
Figure 1. Image
Controller
#include "XML.h"
#include <QXmlQuery>
#include <QDebug>
#include <QBuffer>

using namespace app;

XML::XML()
{
    headers_ << tr("Sequence") << tr("Element") << tr("Attribute");
}

QModelIndex XML::index(int row, int column, const QModelIndex &parent) const
{
    return createIndex(row, column, parent.row());
}

QModelIndex XML::parent(const QModelIndex &index) const
{
    const quintptr id=index.internalId();
    if (index.isValid())
    {
        QModelIndex parent=this->index(id, 0, QModelIndex());
        return parent;
    }
    else
    {
        return QModelIndex();
    }
}

bool XML::hasChildren(const QModelIndex &parent) const
{
    return !parent.isValid() || (int) parent.internalId() < 0;
}

int XML::rowCount(const QModelIndex &parent) const
{
    QString s;
    QByteArray xml(xml_);
    QBuffer buffer(&xml);
    buffer.open(QIODevice::ReadOnly);
    QXmlQuery query;
        // query.setFocus(&buffer);
    query.bindVariable("root",&buffer);

    if(!parent.isValid())
    {
        query.setQuery("count(doc($root)/XML/Sequence)");
    }
    else
    {
        query.bindVariable("row", QVariant(parent.row()+1));
        query.setQuery("count(doc($root)/XML/Sequence[$row]/Element)");
    }

    Q_ASSERT(query.isValid());
    bool ok=query.evaluateTo(&s);
    const int i=s.trimmed().toInt();
    return ok ? i : 0;
}

int XML::columnCount(const QModelIndex &parent) const
{
        return headers_.size();
}

QVariant XML::data(const QModelIndex &index, int role) const
{
    Q_ASSERT(xml_.size());
    switch(role)
    {
    case (Qt::DisplayRole):
    {
        QByteArray xml(xml_);
        QBuffer buffer(&xml);
        buffer.open(QIODevice::ReadOnly);
        QXmlQuery query;
        QString x=QString::fromUtf8(xml);
//        query.setFocus(&buffer);
        query.bindVariable("root",&buffer);

        if((int)index.internalId() < 0)
        {
                if(index.column() == 0)
                        {
                                query.bindVariable("seq", QVariant(index.row()+1));
                                query.setQuery("doc($root)/XML/Sequence[$seq]/@Name/string()");
                        }
                        else
                        {
                                query.setQuery("''");
                        }
        }
        else
        {
            query.bindVariable("seq", QVariant(index.internalId()+1));
            query.bindVariable("ele", QVariant(index.row()+1));
            query.bindVariable("attr", QVariant(index.column()+1));
            query.setQuery("doc($root)/XML/Sequence[$seq]/Element[$ele]/@*[$attr]/string()");
        }

        Q_ASSERT(query.isValid());
        QString result;
        query.evaluateTo(&result);
        return result.trimmed();
    }
    default:
        return QVariant();
    }
}

QVariant XML::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section < headers_.size())
    {
        return headers_.at(section);
    }
    else
    {
        return QVariant();
    }
}

void XML::set(QString xml)
{
    emit layoutAboutToBeChanged();
    emit beginResetModel();
    xml_=xml.toUtf8();
    emit endResetModel();
    emit layoutChanged();
}