LineChartDataModel Example

#include "mainwindow.h"

#include <QGroupBox>
#include <QComboBox>
#include <QHeaderView>
#include <QDoubleSpinBox>
#include <QTableWidget>
#include <QToolBar>
#include <QAction>
#include <QFormLayout>

/* MainWindow */
MainWindow::MainWindow()
    : DemoChartWindow(tr("Line Chart with Model"))
{
    m_columnCount = 3;
    m_rowCount = 12;
    m_orientation = Qt::Vertical;

    setChart(createChart(), createDataBindingWidget());

    createSeriesParametrs();
    seriesChanged(m_seriesSwitcher->currentIndex());
}

Chart* MainWindow::createChart()
{
    return new Qtitan::Chart(this);
}

QWidget* MainWindow::createDataBindingWidget()
{
    m_tableWidget = new QTableWidget(this);
    m_tableWidget->setMaximumWidth(250);
    m_tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    return m_tableWidget;
}

void MainWindow::createSeriesParametrs()
{
    QGroupBox* dataBindingGroup = createGroupParameters(tr("Data Binding"));
    QFormLayout* formLayout = (QFormLayout*)dataBindingGroup->layout();
    m_seriesSwitcher = new QComboBox(dataBindingGroup);
    m_seriesSwitcher->addItem(tr("Selection Model"), QVariant(SelectionDataModel));
    m_seriesSwitcher->addItem(tr("Edit Model"),      QVariant(EditDataModel));
    connect(m_seriesSwitcher, SIGNAL(currentIndexChanged(int)), this, SLOT(seriesChanged(int)));
    formLayout->addRow(m_seriesSwitcher);

    m_seriesOrientationLabel = new QLabel(tr("Data Orientation:"), this);
    m_seriesOrientationSwitcher = new QComboBox(dataBindingGroup);
    m_seriesOrientationSwitcher->addItem(tr("Vertical"),   QVariant(Qt::Vertical));
    m_seriesOrientationSwitcher->addItem(tr("Horizontal"), QVariant(Qt::Horizontal));
    connect(m_seriesOrientationSwitcher, SIGNAL(currentIndexChanged(int)), this, SLOT(orientationChanged(int)));
    formLayout->addRow(m_seriesOrientationLabel, m_seriesOrientationSwitcher);

    m_toolBar = new QToolBar(this);
    m_actAppendRow = m_toolBar->addAction(QIcon(QStringLiteral(":\\shared\\res\\appendrow.png")), QString(tr("Append Row")));
    m_actAppendRow->setEnabled(false);
    connect(m_actAppendRow, SIGNAL(triggered()), this, SLOT(appendRow()));
    m_actDeleteRow = m_toolBar->addAction(QIcon(QStringLiteral(":\\shared\\res\\deleterow.png")), QString(tr("Delete Row")));
    m_actDeleteRow->setEnabled(false);
    connect(m_actDeleteRow, SIGNAL(triggered()), this, SLOT(deleteRow()));

    formLayout->addRow(m_toolBar);
}

void MainWindow::createSelectionModelSeries()
{
    disconnect(m_tableWidget, SIGNAL(itemSelectionChanged()), this, SLOT(updateEnableButtons()));
    connect(m_tableWidget, SIGNAL(itemSelectionChanged()), this, SLOT(setSelectionData()));

    createTitle(tr("Selection Data Model"));
    m_chart->legend()->setVisible(true);

    ChartSplineSeries2D* series = new ChartSplineSeries2D();
    series->setName(tr("Input Series"));
    m_chart->appendSeries(series);
    series->setModel(m_tableWidget->model());
}

void MainWindow::createEditModelSeries()
{
    disconnect(m_tableWidget, SIGNAL(itemSelectionChanged()), this, SLOT(setSelectionData()));
    connect(m_tableWidget, SIGNAL(itemSelectionChanged()), this, SLOT(updateEnableButtons()));

    createTitle(tr("Edit Data Model"));
    m_chart->legend()->setVisible(true);

    ChartSplineSeries2D* series = new ChartSplineSeries2D();
    series->setName(tr("Input Series"));
    m_chart->appendSeries(series);
    series->setModel(m_tableWidget->model());
}

void MainWindow::fill2DDataTable()
{
    m_tableWidget->clear();

    m_tableWidget->setColumnCount(m_columnCount);
    m_tableWidget->setRowCount(m_rowCount);

    for (int i = 0; i < m_rowCount; i++)
    {
        for (int k = 0; k < m_columnCount; k++)
        {
            QTableWidgetItem* item = new QTableWidgetItem();
            int value = 0;
            if (k % 2 == 0)
                value = i * 50 + rand() % 20;
            else
                value = rand() % 100;

            item->setText(QStringLiteral("%1").arg(value));
            m_tableWidget->setItem(i, k, item);
        }
    }
}

void MainWindow::initOrientationChanged()
{
    if (m_seriesOrientationSwitcher->isHidden())
        return;

    if (ChartPointSeries* series = qobject_cast<ChartPointSeries*>(m_chart->series().at(0)))
    {
        series->modelController()->setOrientation(m_orientation);
        m_tableWidget->clearSelection();

        if (m_orientation== Qt::Horizontal)
        {
            QTableWidgetSelectionRange range(0/*top*/, 0/*left*/, 1/*bottom*/, m_columnCount-1/*right*/);
            m_tableWidget->setRangeSelected(range, true/*select*/);
        }
        else
        {
            QTableWidgetSelectionRange range(0/*top*/, 0/*left*/, m_rowCount-1/*bottom*/, 1/*right*/);
            m_tableWidget->setRangeSelected(range, true/*select*/);
        }
    }
}

void MainWindow::updateValueParameters()
{
    DemoChartWindow::updateValueParameters();
    initOrientationChanged();
    orientationChanged(m_seriesOrientationSwitcher->currentIndex());
}

void MainWindow::seriesChanged(int index)
{
    m_chart->clearSeries();
    m_chart->clearTitles();
    m_chart->setBackgroundBrush(QBrush());

    QVariant var = m_seriesSwitcher->itemData(index);
    switch((SeriesType)var.toUInt())
    {
        case SelectionDataModel :
            {
                m_tableWidget->clearSelection();
                m_tableWidget->setSelectionMode(QAbstractItemView::ContiguousSelection);
                m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectItems);
                m_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
                m_seriesOrientationLabel->show();
                m_seriesOrientationSwitcher->show();
                m_toolBar->hide();
                m_columnCount = 3;
                m_rowCount = 12;
                fill2DDataTable();
                createSelectionModelSeries();
            }
            break;
        case EditDataModel :
            {
                m_tableWidget->clearSelection();
                m_tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
                m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
                m_tableWidget->setEditTriggers(QAbstractItemView::AllEditTriggers);
                m_seriesOrientationLabel->hide();
                m_seriesOrientationSwitcher->hide();
                m_toolBar->show();
                m_columnCount = 2;
                m_rowCount = 24;
                fill2DDataTable();
                createEditModelSeries();
            }
            break;
        default:
            break;
    }
    updateValueParameters();
}

void MainWindow::orientationChanged(int index)
{
    QVariant var = m_seriesOrientationSwitcher->itemData(index);
    m_orientation = (Qt::Orientation)var.toUInt();
    initOrientationChanged();
}

void MainWindow::setSelectionData()
{
    if (m_chart->series().count() == 0)
        return;

    if (ChartPointSeries* series = qobject_cast<ChartPointSeries*>(m_chart->series().at(0)))
    {
        QList<QTableWidgetSelectionRange> selectedRanges = m_tableWidget->selectedRanges();
        if (selectedRanges.count() == 1)
        {
            QTableWidgetSelectionRange selected = selectedRanges.at(0);
            if (m_orientation == Qt::Horizontal)
            {
                series->modelController()->setAxisXRow(selected.topRow() == selected.bottomRow() ? -1 : selected.topRow());
                series->modelController()->setAxisYRow(selected.bottomRow());
                series->modelController()->setColumnRange(selected.leftColumn(), selected.rightColumn());
            }
            else
            {
                series->modelController()->setAxisXColumn(selected.leftColumn() == selected.rightColumn() ? -1 : selected.leftColumn());
                series->modelController()->setAxisYColumn(selected.rightColumn());
                series->modelController()->setRowRange(selected.topRow(), selected.bottomRow());
            }
        }
        else
        {
            series->modelController()->setAxisXRow(-1);
            series->modelController()->setAxisYRow(-1);
            series->modelController()->setAxisXColumn(-1);
            series->modelController()->setAxisYColumn(-1);
            series->modelController()->setColumnRange(-1, -1);
            series->modelController()->setRowRange(-1, -1);
        }
    }
}

void MainWindow::appendRow()
{
    if (m_chart->series().count() == 0)
        return;

    int numNewRow = 0;

    QList<QTableWidgetSelectionRange> selectedRanges = m_tableWidget->selectedRanges();
    if (selectedRanges.count() > 0)
    {
        QModelIndex indexEdit = m_tableWidget->currentIndex();
        if (indexEdit.isValid())
        {
            if (QTableWidgetItem* itemEdit = m_tableWidget->item(indexEdit.row(), indexEdit.column()))
                m_tableWidget->closePersistentEditor(itemEdit);
        }
        m_tableWidget->reset();

        QTableWidgetSelectionRange selected = selectedRanges.at(selectedRanges.count()-1);
        numNewRow = selected.topRow() + 1;
    }

    m_rowCount++;

    m_tableWidget->insertRow(numNewRow);

    QTableWidgetItem* itemX = new QTableWidgetItem();
    itemX->setText(QStringLiteral("%1").arg(0));
    m_tableWidget->setItem(numNewRow, 0, itemX);

    QTableWidgetItem* itemY = new QTableWidgetItem();
    itemY->setText(QStringLiteral("%1").arg(0));
    m_tableWidget->setItem(numNewRow, 1, itemY);

    QTableWidgetSelectionRange range(numNewRow/*top*/, 0/*left*/, numNewRow/*bottom*/, m_columnCount-1/*right*/);
    m_tableWidget->setRangeSelected(range, true/*select*/);

    QModelIndex index = m_tableWidget->model()->index(numNewRow, 0);
    if (index.isValid())
    {
        m_tableWidget->setCurrentIndex(index);
        m_tableWidget->edit(index);
    }

    if (ChartPointSeries* series = qobject_cast<ChartPointSeries*>(m_chart->series().at(0)))
        series->modelController()->setColumnRange(0, m_rowCount-1);
}

void MainWindow::deleteRow()
{
    if (m_chart->series().count() == 0)
        return;

    QList<QTableWidgetSelectionRange> selectedRanges = m_tableWidget->selectedRanges();
    for (int i = 0; selectedRanges.count() > i; i++)
    {
        QTableWidgetSelectionRange selected = selectedRanges.at(i);
        m_tableWidget->removeRow(selected.topRow());

        m_rowCount--;
        if (ChartPointSeries* series = qobject_cast<ChartPointSeries*>(m_chart->series().at(0)))
          series->modelController()->setColumnRange(0, m_rowCount-1);
    }
    updateEnableButtons();
}

void MainWindow::updateEnableButtons()
{
    if (m_chart->series().count() == 0)
        return;

    bool isEmpty = !(m_orientation == Qt::Horizontal ? m_tableWidget->model()->rowCount() > 0 : m_tableWidget->model()->columnCount() > 0);
    QList<QTableWidgetSelectionRange> selectedRanges = m_tableWidget->selectedRanges();
    m_actDeleteRow->setEnabled(selectedRanges.count() > 0);
    m_actAppendRow->setEnabled(isEmpty || selectedRanges.count() > 0);
}