LargeDataSetExample Example

#include <QtGui>
#include <QMessageBox>
#include <QDialogButtonBox>

#include "window.h"

/* Window */
Window::Window()
: DemoMainWindow(QStringLiteral("QtitanDataGrid"), QStringLiteral(QTN_VERSION_DATAGRID_STR), tr("Large Model with 100.000 Rows"))
{
    Grid::loadTranslation();

    m_grid = new Qtitan::Grid(this);
    LargeDataSetModel* model = new LargeDataSetModel(m_grid);

    // Configure grid view
    m_grid->setViewType(Qtitan::Grid::TableView);
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->options().setGridLineWidth(1);
    view->options().setGestureEnabled(true);

    view->beginUpdate();

    //Connect Grid's context menu handler.
    connect(view, SIGNAL(contextMenu(ContextMenuEventArgs*)), this, SLOT(contextMenu(ContextMenuEventArgs* )));

    connect(view, SIGNAL(editorModifying(GridEditor *)), this, SLOT(editorModifying(GridEditor *)));
    connect(view, SIGNAL(editorValidating(EditorValidationEventArgs*)), this, SLOT(editorValidating(EditorValidationEventArgs*)));
    connect(view, SIGNAL(editorUpdated(GridEditor*)), this, SLOT(editorUpdated(GridEditor*)));
    connect(view, SIGNAL(editorStarting(EditorEventArgs*)), this, SLOT(editorStarting(EditorEventArgs*)));

    connect(view, SIGNAL(focusRowChanged(int, int)), this, SLOT(focusRowChanged(int, int)));

    view->setModel(model);

    GridColumn* column = (GridColumn *)view->getColumn(0);
    column->setEditorType(GridEditor::CheckBox);
//    column->editorRepository()->setImmediatePost(true);

    column = (Qtitan::GridTableColumn *)view->getColumn(1);
    column->setEditorType(GridEditor::Numeric);
    ((Qtitan::GridNumericEditorRepository *)column->editorRepository())->setMinimum(-10000);
    ((Qtitan::GridNumericEditorRepository *)column->editorRepository())->setMaximum(10000);

    column = (Qtitan::GridTableColumn *)view->getColumn(2);
    column->setEditorType(GridEditor::String);
    column->editorRepository()->setValidateOnEnter(false);
    column->editorRepository()->setEditorActivationPolicy(GridEditor::ActivationPolicy(GridEditor::ActivateByKeyPress_WithEating | GridEditor::ActivateByEnter));

    //Add cell button to the column.
    column->addButton(GridColumn::TextButtonIcon, Qtitan::AtEnd);
    column->addButton(GridColumn::ChoiceButtonIcon, Qtitan::AtEnd);
    connect(column, SIGNAL(buttonClicked(CellButtonClickEventArgs*)), this, SLOT(cellButtonClicked(CellButtonClickEventArgs*)));

    column = (Qtitan::GridTableColumn *)view->getColumn(3);
    column->setEditorType(GridEditor::Date);
    //Add cell button to the column.
    column->addButton(GridColumn::ClearButtonIcon, Qtitan::AtEnd, Qtitan::GridColumn::MouseOverPolicy);
    connect(column, SIGNAL(buttonClicked(CellButtonClickEventArgs*)), this, SLOT(cellButtonClicked(CellButtonClickEventArgs*)));
    column->editorRepository()->setAutoSelect(true);

    column = (Qtitan::GridTableColumn *)view->getColumn(4);
    column->setEditorType(GridEditor::Time);

    column = (Qtitan::GridTableColumn *)view->getColumn(5);
    column->setEditorType(GridEditor::ComboBox);
    QStringListModel* countryModel = new QStringListModel(column);
    QStringList options;
    options << tr("Germany") << tr("France") << tr("Italy") << tr("United States") << tr("United Kingdom") << tr("Russia") << tr("China") << tr("Canada");
    countryModel->setStringList(options);
    column->dataBinding()->setRelationModel(countryModel);
    column->dataBinding()->setDefaultValue(QString(), Qt::DisplayRole);
    column->dataBinding()->setForeignKey(0, Qt::DisplayRole, Qt::DisplayRole);
    column->dataBinding()->setRoleMapping(Qt::DisplayRole, 0, Qt::DisplayRole);

     //Show button menu for all column headers.
    for (int i = 0; i < view->getColumnCount(); ++i)
        static_cast<GridTableColumn *>(view->getColumn(i))->setMenuButtonVisible(true);

    view->endUpdate();

    setDemoWidget(m_grid, createSettingsWidget());
    setMinimumHeight(10);
}

QWidget* Window::createSettingsWidget()
{
    //Create settings widget
    QWidget* settings = new QWidget(this);
    QVBoxLayout* l = new QVBoxLayout(settings);

    l->addLayout(createStyleSetting());

    QCheckBox* autoWidthCheck = new QCheckBox(settings);
    autoWidthCheck->setText(tr("Column auto width"));
    connect(autoWidthCheck, SIGNAL(stateChanged(int)), this, SLOT(autoWidthStateChanged(int)));
    autoWidthCheck->setChecked(true);
    l->addWidget(autoWidthCheck);

    QCheckBox* checkBox = new QCheckBox(settings);
    checkBox->setText(tr("Show Resize Content (new)"));
    connect(checkBox, SIGNAL(stateChanged(int)), this, SLOT(showResizeContentChanged(int)));
    checkBox->setChecked(true);
    l->addWidget(checkBox);

    QCheckBox* fastScrollCheck = new QCheckBox(settings);
    fastScrollCheck->setText(tr("Fast scroll effect"));
    connect(fastScrollCheck, SIGNAL(stateChanged(int)), this, SLOT(fastScrollChanged(int)));
    l->addWidget(fastScrollCheck);
    fastScrollCheck->setChecked(true);

    QCheckBox* dottedLineCheck = new QCheckBox(settings);
    dottedLineCheck->setText(tr("Dotted grid line"));
    connect(dottedLineCheck, SIGNAL(stateChanged(int)), this, SLOT(dottedLineChanged(int)));
    l->addWidget(dottedLineCheck);
    dottedLineCheck->setChecked(true);

    QLabel* label = new QLabel(this);
    QHBoxLayout* hl = new QHBoxLayout(0);
    label->setText(tr("Grid line style:"));
    QComboBox* lineStylesSelect = new QComboBox(settings);

    lineStylesSelect->addItem(tr("None"));
    lineStylesSelect->addItem(tr("Both"));
    lineStylesSelect->addItem(tr("Both2D"));
    lineStylesSelect->addItem(tr("Horizontal"));
    lineStylesSelect->addItem(tr("Horizontal2D"));
    lineStylesSelect->addItem(tr("Vertical"));
    lineStylesSelect->addItem(tr("Vertical2D"));
    connect(lineStylesSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(selectGridLineStyles(int)));
    hl->addWidget(label);
    hl->addWidget(lineStylesSelect);
    l->addLayout(hl);
    lineStylesSelect->setCurrentIndex(2);

    QCheckBox* zoomEnable = new QCheckBox(settings);
    zoomEnable->setText(tr("Zoom enabled"));
    zoomEnable->setChecked(true);
    connect(zoomEnable, SIGNAL(stateChanged(int)), this, SLOT(zoomEnabledChanged(int)));
    l->addWidget(zoomEnable);

    QCheckBox* zoomIndicator = new QCheckBox(settings);
    zoomIndicator->setText(tr("Show zoom indicator"));
    zoomIndicator->setChecked(true);
    connect(zoomIndicator, SIGNAL(stateChanged(int)), this, SLOT(zoomIndicatorChanged(int)));
    l->addWidget(zoomIndicator);

    QSlider* zoomSlider = new QSlider(settings);
    zoomSlider->setOrientation(Qt::Horizontal);
    zoomSlider->setTickPosition(QSlider::TicksBothSides);
    zoomSlider->setMinimum(25);
    zoomSlider->setMaximum(300);
    zoomSlider->setTickInterval(25);
    zoomSlider->setSingleStep(25);
    zoomSlider->setValue(100);
    connect(zoomSlider, SIGNAL(sliderMoved(int)), this, SLOT(zoomValueChanged(int)));
    connect(m_grid->view<Qtitan::GridTableView>(), SIGNAL(zoomChanged(int)), zoomSlider, SLOT(setValue(int)));
    l->addWidget(zoomSlider);

    QCheckBox* cellAutoRaise = new QCheckBox(settings);
    cellAutoRaise->setText(tr("Auto raise cell button"));
    connect(cellAutoRaise, SIGNAL(stateChanged(int)), this, SLOT(cellButtonAutoRaiseEnabled(int)));
    cellAutoRaise->setChecked(true);
    l->addWidget(cellAutoRaise);

    QCheckBox* frozenRowsBox = new QCheckBox(settings);
    frozenRowsBox->setText(tr("Frozen Rows"));
    connect(frozenRowsBox, SIGNAL(stateChanged(int)), this, SLOT(frozenRowsEnabled(int)));
    frozenRowsBox->setChecked(true);
    l->addWidget(frozenRowsBox);

    QCheckBox* transparentBox = new QCheckBox(settings);
    transparentBox->setText(tr("Transparent Background"));
    connect(transparentBox, SIGNAL(stateChanged(int)), this, SLOT(transparentBackgroundEnabled(int)));
    transparentBox->setChecked(false);
    l->addWidget(transparentBox);

    QCheckBox* rowSizingBox = new QCheckBox(settings);
    rowSizingBox->setText(tr("Resizing row (new)"));
    connect(rowSizingBox, SIGNAL(stateChanged(int)), this, SLOT(rowSizingEnabled(int)));
    rowSizingBox->setChecked(false);
    l->addWidget(rowSizingBox);

    label = new QLabel(this);
    hl = new QHBoxLayout(0);
    label->setText(tr("Check box appearance (new):"));
    QComboBox* checkBoxAppearance = new QComboBox(settings);

    checkBoxAppearance->addItem(QStringLiteral("CheckBox"));
    checkBoxAppearance->addItem(QStringLiteral("RadioButton"));
    checkBoxAppearance->addItem(QStringLiteral("Styled"));
    connect(checkBoxAppearance, SIGNAL(currentIndexChanged(int)), this, SLOT(checkBoxAppearanceChanged(int)));
    hl->addWidget(label);
    hl->addWidget(checkBoxAppearance);
    l->addLayout(hl);
    checkBoxAppearance->setCurrentIndex(2);

    QPushButton* printButton = new QPushButton(settings);
    printButton->setText(tr("Print Preview"));
    connect(printButton, SIGNAL(clicked()), this, SLOT(printPreview()));
    l->addWidget(printButton);

    return settings;
}

void Window::setShadeColor(const QColor& color)
{
    m_grid->themeManager()->setShadeColor(color);
}

void Window::autoWidthStateChanged(int state)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->tableOptions().setColumnAutoWidth(state == Qt::Checked);
}

void Window::showResizeContentChanged(int state)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->tableOptions().setShowResizeContent(state == Qt::Checked);
}

void Window::fastScrollChanged(int state)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->options().setFastScrollEffect(state == Qt::Checked);
}

void Window::dottedLineChanged(int state)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    QPen pen = view->options().gridLinePen();
    pen.setStyle(state == Qt::Checked ? Qt::DotLine : Qt::SolidLine);
    view->options().setGridLinePen(pen);
}

void Window::selectGridLineStyles(int index)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    switch (index)
    {
    case 0:
        view->options().setGridLines(Qtitan::LinesNone);
        break;
    case 1:
        view->options().setGridLines(Qtitan::LinesBoth);
        break;
    case 2:
        view->options().setGridLines(Qtitan::LinesBoth2D);
        break;
    case 3:
        view->options().setGridLines(Qtitan::LinesHorizontal);
        break;
    case 4:
        view->options().setGridLines(Qtitan::LinesHorizontal2D);
        break;
    case 5:
        view->options().setGridLines(Qtitan::LinesVertical);
        break;
    case 6:
        view->options().setGridLines(Qtitan::LinesVertical2D);
        break;
    default:
        view->options().setGridLines(Qtitan::LinesBoth);
    }
 }

void Window::checkBoxAppearanceChanged(int index)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    GridColumn* column = (GridColumn *)view->getColumn(0);
    if (index == 0)
        ((Qtitan::GridCheckBoxEditorRepository *)column->editorRepository())->setAppearance(GridCheckBox::CheckBoxAppearance);
    else if (index == 1)
        ((Qtitan::GridCheckBoxEditorRepository *)column->editorRepository())->setAppearance(GridCheckBox::RadioButtonAppearance);
    else
        ((Qtitan::GridCheckBoxEditorRepository *)column->editorRepository())->setAppearance(GridCheckBox::StyledAppearance);
}

void Window::zoomEnabledChanged(int state)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->options().setZoomEnabled(state == Qt::Checked);
}

void Window::zoomIndicatorChanged(int state)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->options().setZoomIndicatorActive(state == Qt::Checked);
}

void Window::zoomValueChanged(int value)
{
    double factor = qCeil((double)value / 25) * 25;
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->options().setZoomFactor(factor / 100);
}

void Window::focusRowChanged(int oldRowIndex, int rowIndex)
{
    Q_UNUSED(oldRowIndex);
    Q_UNUSED(rowIndex);
}

void Window::cellButtonAutoRaiseEnabled(int state)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->options().setCellButtonAutoRaise(state == Qt::Checked);
}

void Window::frozenRowsEnabled(int state)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->tableOptions().setRowFrozenButtonVisible(state == Qt::Checked);
    view->tableOptions().setFrozenPlaceQuickSelection(state == Qt::Checked);
}

void Window::transparentBackgroundEnabled(int state)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->options().setTransparentBackground(state == Qt::Checked);
    view->options().setAlternatingRowColors(!view->options().alternatingRowColors());
}

void Window::rowSizingEnabled(int state)
{
    Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();
    view->tableOptions().setRowSizingEnabled(state == Qt::Checked);
}

void Window::editorModifying(GridEditor* editor)
{
    Q_UNUSED(editor);
}

void Window::editorValidating(EditorValidationEventArgs* args)
{
    args->setValueValid(true);
    //args->setEditingValue(args->editValue());
    args->setHandled(true);
}

void Window::editorUpdated(GridEditor* editor)
{
    Q_UNUSED(editor);
}

void Window::editorStarting(EditorEventArgs* args)
{
    if (args->activationPolicy() == GridEditor::ActivateByEnter)
    {
        args->setHandled(true);

        Qtitan::GridTableView* view = m_grid->view<Qtitan::GridTableView>();

        QDialog dialog(this);
        dialog.setWindowTitle(tr("Row Editor"));
        QGridLayout* layout = new QGridLayout(&dialog);

        for (int i = 0; i < view->getColumnCount(); ++i)
        {
            GridColumn* column = (GridColumn*)view->getColumn(i);
            QLabel* label = new QLabel();
            label->setText(column->caption());
            QLineEdit* edit = new QLineEdit();
            layout->addWidget(label, i, 0);
            layout->addWidget(edit, i, 1);

            QModelIndex index = args->row().modelIndex(column->dataBinding()->column());
            QVariant v = view->model()->data(index, Qt::EditRole);
            edit->setText(v.toString());
        }

        QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
        connect(buttons, SIGNAL(accepted()), &dialog, SLOT(accept()));
        connect(buttons, SIGNAL(rejected()), &dialog, SLOT(reject()));
        layout->addWidget(buttons, view->getColumnCount(), 0, 1, 2);

        if (dialog.exec() != 0)
        {
            for (int i = 0; i < view->getColumnCount(); ++i)
            {
                GridColumn* column = (GridColumn*)view->getColumn(i);
                QLineEdit* edit = qobject_cast<QLineEdit *>(layout->itemAtPosition(i, 1)->widget());
                if (edit == Q_NULL)
                    continue;

                QVariant v = edit->text();
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
                if (!v.convert(column->dataBinding()->defaultValue(Qt::EditRole).typeId()))
#else
                if (!v.convert(column->dataBinding()->defaultValue(Qt::EditRole).type()))
#endif
                    continue;
                QModelIndex index = args->row().modelIndex(column->dataBinding()->column());
                view->model()->setData(index, v, Qt::EditRole);
            }
        }
    }
}

void Window::contextMenu(ContextMenuEventArgs* args)
{
    args->contextMenu()->addAction(tr("Print Preview"), this, SLOT(printPreview()));
    args->contextMenu()->addSeparator();
    args->contextMenu()->addAction(tr("Developer Machines on the Web"), this, SLOT(showCompanyWebSite()));
}

void Window::cellButtonClicked(CellButtonClickEventArgs* args)
{
    QMessageBox::information(this, tr("Cell button clicked"),
        tr("Clicked: Button - %1, Column Title - %2, RowIndex - %3").arg(args->buttonIndex()).arg(args->column()->caption()).arg(args->row().rowIndex()));
}

void Window::printPreview()
{
    m_grid->view<Qtitan::GridTableView>()->printPreview();
}

static inline int rand_value(int low, int high)
{
    return rand() % ((high + 1) - low) + low;
}

/* LargeDataSetModel */
LargeDataSetModel::LargeDataSetModel(QObject *parent)
: QAbstractItemModel(parent)
{
    QStringList options;
    options << tr("Germany") << tr("France") << tr("Italy") << tr("United States") << tr("United Kingdom") << tr("Russia") << tr("China") << tr("Canada");
    m_header << QStringLiteral("Boolean") <<
        QStringLiteral("Integer") <<
        QStringLiteral("String") <<
        QStringLiteral("Date") <<
        QStringLiteral("Time") << QStringLiteral("ComboBox");
    m_values.resize(100000);
    int y = 2009;
    int m = 1;
    int d = 1;
    for (int i = 0; i < m_values.size(); ++i)
    {
        m_values[i].v0 = true;
        m_values[i].v1 = i;
        m_values[i].v2 = QStringLiteral("String = %1").arg(i);
        m_values[i].v4 = QTime(12, 0, 0);
        if (d > 28)
        {
            d = 1;
            m++;
            if (m > 12)
            {
                m = 1;
                y++;
            }
        }
        m_values[i].v3 = QDate(y, m, d);
        if (!((i + 1) % 10))
            d++;
        m_values[i].v5 = options[rand_value(0, 7)];
    }
}

LargeDataSetModel::~LargeDataSetModel()
{
}

QVariant LargeDataSetModel::headerData(int section, Qt::Orientation orientation,
                                      int role) const
{
    Q_UNUSED(role);
    if (orientation == Qt::Horizontal && section >= 0 && section < m_header.size())
        return m_header[section];
    else
        return QVariant();
}

bool LargeDataSetModel::setHeaderData(int section, Qt::Orientation orientation,
    const QVariant& value, int role)
{
    Q_UNUSED(role);
    if (orientation == Qt::Horizontal && section >= 0 && section < m_header.size())
    {
        m_header[section] = value.toString();
        headerDataChanged(orientation, section, section);
        return true;
    }
    return false;
}

QModelIndex LargeDataSetModel::parent(const QModelIndex & /*child*/) const
{
    return QModelIndex();
}

bool LargeDataSetModel::hasChildren(const QModelIndex &parent) const
{
    if (parent.model() == this || !parent.isValid())
        return rowCount(parent) > 0 && columnCount(parent) > 0;
    return false;
}

int LargeDataSetModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return m_values.size();
}

int LargeDataSetModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return 6;
}

QModelIndex LargeDataSetModel::index(int row, int column, const QModelIndex &parent) const
{
    if (parent.isValid())
        return QModelIndex();

    if (row < 0 || row >= rowCount(parent))
        return QModelIndex();

    if (column < 0 || column >= columnCount(parent))
        return QModelIndex();

    return createIndex(row, column, (void*)NULL);
}

QVariant LargeDataSetModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (index.row() < 0 || index.row() >= rowCount(index.parent()))
        return QVariant();

    if (index.column() < 0 || index.column() >= columnCount(index.parent()))
        return QVariant();

    if (role == Qt::DisplayRole || role == Qt::EditRole)
    {
        switch (index.column())
        {
        case 0:
            return m_values[index.row()].v0;
            break;
        case 1:
            return m_values[index.row()].v1;
            break;
        case 2:
            return m_values[index.row()].v2;
            break;
        case 3:
            return m_values[index.row()].v3;
            break;
        case 4:
            return m_values[index.row()].v4;
            break;
        case 5:
            return m_values[index.row()].v5;
            break;
        }
    }
    else if (role == Qt::CheckStateRole)
    {
        switch (index.column())
        {
        case 0:
            return m_values[index.row()].v0;
            break;
        }
    }
    return QVariant();
}

bool LargeDataSetModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid())
        return false;

    if (index.row() < 0 || index.row() >= rowCount(index.parent()))
        return false;

    if (index.column() < 0 || index.column() >= columnCount(index.parent()))
        return false;

    if (role != Qt::EditRole)
        return false;

    switch (index.column())
    {
    case 0:
        m_values[index.row()].v0 = value.toBool();
        break;
    case 1:
        m_values[index.row()].v1 = value.toInt();
        break;
    case 2:
        m_values[index.row()].v2 = value.toString();
        break;
    case 3:
        m_values[index.row()].v3 = value.toDate();
        break;
    case 4:
        m_values[index.row()].v4 = value.toTime();
        break;
    case 5:
        m_values[index.row()].v5 = value.toString();
        break;
    }

    emit dataChanged(index, index);
    return true;
}

Qt::ItemFlags LargeDataSetModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::ItemFlags();
    if (index.row() == 5 && (index.column() >= 0 && index.column() < 4))
        return Qt::ItemIsEditable;
    else
        return Qt::ItemIsEnabled | Qt::ItemIsEditable;
}