csvview.cpp Example File

webkit/webplugin/csvview.cpp
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtGui>
#include <QtNetwork>
#include "csvview.h"
CSVView::CSVView(const QString &mimeType, QWidget *parent)
    : QTableView(parent)
{
    this->mimeType = mimeType;
    setEditTriggers(NoEditTriggers);
    setSelectionBehavior(SelectRows);
    setSelectionMode(SingleSelection);
}
void CSVView::updateModel()
{
    QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
    if (reply->error() != QNetworkReply::NoError)
        return;
    bool hasHeader = false;
    QString charset = "latin1";
    foreach (QString piece, mimeType.split(";")) {
        piece = piece.trimmed();
        if (piece.contains("=")) {
            int index = piece.indexOf("=");
            QString left = piece.left(index).trimmed();
            QString right = piece.mid(index + 1).trimmed();
            if (left == "header")
                hasHeader = (right == "present");
            else if (left == "charset")
                charset = right;
        }
    }
    QTextStream stream(reply);
    stream.setCodec(QTextCodec::codecForName(charset.toLatin1()));
    QStandardItemModel *model = new QStandardItemModel(this);
    QList<QStandardItem *> items;
    bool firstLine = hasHeader;
    bool wasQuote = false;
    bool wasCR = false;
    bool quoted = false;
    QString text;
    while (!stream.atEnd()) {
        QString ch = stream.read(1);
        if (wasQuote) {
            if (ch == "\"") {
                if (quoted) {
                    text += ch;         // quoted "" are inserted as "
                    wasQuote = false;   // no quotes are pending
                } else {
                    quoted = true;      // unquoted "" starts quoting
                    wasQuote = true;    // with a pending quote
                }
                continue;               // process the next character
            } else {
                quoted = !quoted;       // process the pending quote
                wasQuote = false;       // no quotes are pending
            }                           // process the current character
        } else if (wasCR) {
            wasCR = false;
            if (ch == "\n") {           // CR LF represents the end of a row
                if (!text.isEmpty())
                    items.append(new QStandardItem(QString(text)));
                addRow(firstLine, model, items);
                items.clear();
                text = "";
                firstLine = false;
                continue;               // process the next character
            } else
                text += "\r";           // CR on its own is inserted
        }                               // process the current character
        // wasQuote is never true here.
        // wasCR is never true here.
        if (ch == "\"")
            wasQuote = true;            // handle the pending quote later
        else if (ch == ",") {
            if (quoted)
                text += ch;
            else {
                items.append(new QStandardItem(QString(text)));
                text = "";
            }
        }
        else if (ch == "\r") {
            if (!quoted)
                wasCR = true;
            else
                text += ch;
        }
        else if (ch == "\n")
            text += ch;
        else
            text += ch;
    }
    if (items.count() > 0)
        addRow(firstLine, model, items);
    reply->close();
    setModel(model);
    connect(selectionModel(),
            SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
            this, SLOT(exportRow(const QModelIndex &)));
    resizeColumnsToContents();
    horizontalHeader()->setStretchLastSection(true);
}
void CSVView::addRow(bool firstLine, QStandardItemModel *model,
                     const QList<QStandardItem *> &items)
{
    if (firstLine) {
        for (int j = 0; j < items.count(); ++j)
            model->setHorizontalHeaderItem(j, items[j]);
    } else
        model->appendRow(items);
}
void CSVView::exportRow(const QModelIndex &current)
{
    QString name = model()->index(current.row(), 0).data().toString();
    QString address = model()->index(current.row(), 1).data().toString();
    QString quantity = model()->index(current.row(), 2).data().toString();
    emit rowSelected(name, address, quantity);
}