Classes - Annotated - Tree - Functions - Home - Structure

Custom cell editors: a wine order list

The following example demonstrates how to write editors other than QLineEdit with QTableItems.

The example implements a wine order list where the user can choose the amount of bottles via QSpinBoxes.

For a line-by-line explanation of the following code please refer to the walkthrough.


The API of the SpinBoxItem class (spinboxitem.h):

/*
$Id$
*/

#ifndef SPINBOXITEM_H
#define SPINBOXITEM_H

#include <qtable.h>
#include <qstring.h>

class SpinBoxItem: public QTableItem
{

public:
    SpinBoxItem( QTable *, const int, const QString &);

private:
    QWidget * createEditor() const;
    void setContentFromEditor( QWidget * );

    int getValue() const;

    QTable * table;
    QString suffix;
};

#endif

The Implementation of the SpinBoxItem class (spinboxitem.cpp):

/*
$Id$
*/

#include "spinboxitem.h"
#include <qspinbox.h>
#include <qregexp.h>

SpinBoxItem::SpinBoxItem( QTable * myTable, const int value,
                          const QString & text )
           : QTableItem( table, WhenCurrent, "" )
{
   table = myTable;
   suffix = text;
   setText( QString::number( value ) + suffix );
}

QWidget * SpinBoxItem::createEditor() const
{
    QSpinBox * quantities = new QSpinBox( table->viewport(), "quantities" );
    quantities->setSuffix( suffix );
    quantities->setMaxValue( 250 );
    quantities->setValue( getValue() );

    return quantities;
}

int SpinBoxItem::getValue() const
{
    QString value = text();
    value.replace( QRegExp( suffix ), "" );

    bool ok;
    int number;
    number = value.toInt( &ok, 10 );

    if ( ok )
        return number;

    return 0;
}

void SpinBoxItem::setContentFromEditor( QWidget * spinbox )
{
    setText( ( (QSpinBox *) spinbox )->text() );
}


The API of the ProductList class (productlist.h):

/*
$Id$
*/

#ifndef PRODUCTLIST_H
#define PRODUCTLIST_H

#include <qtable.h>
#include <qstring.h>

class ProductList: public QTable
{
Q_OBJECT

public:
    ProductList();

private slots:
    void processValueChanged( int, int );

private:
    double calcPrice( int );
    double sumUp( int );

    int discountRow;
    int totalRow;
    QString suffix;
};

#endif


Its Implementation (productlist.cpp):

/*
$Id$
*/

#include "productlist.h"
#include "spinboxitem.h"
#include <qstring.h>


struct {
    const char * product;
    double price;
} winelist[] = {
    { "Wynns Coonawarra Shiraz 1998", 15.00 },
    { "Meissner Kapitelberg Riesling Kabinett trocken 1999", 8.94 },
    { "Perdera Monica di Sardegna 1997", 7.69 }
};

const int numwines = sizeof( winelist ) / sizeof( winelist[0] );

ProductList::ProductList()
    : QTable( numwines + 2, 4, 0, "productlist" )
{
    discountRow = numRows() - 2;
    totalRow = numRows() - 1;
    suffix = " btls";

    horizontalHeader()->setLabel( 0, "Quantity" );
    horizontalHeader()->setLabel( 1, "Product" );
    horizontalHeader()->setLabel( 2, "Price/bottle (EUR)" );
    horizontalHeader()->setLabel( 3, "Sum (EUR)" );

    for ( int i = 0; i < numwines; i++ ){
        SpinBoxItem * quantity = new SpinBoxItem( this, 0, suffix );
        setItem( i, 0, quantity );
        setText( i, 1, winelist[i].product );
        setText( i, 2, QString::number( winelist[i].price ) );
        setText( i, 3, "0");
    }

    setText( discountRow, 1, "Discount" );
    QTableItem * discount = new QTableItem( this, QTableItem::Always,
                                            "-0.00" );
    setItem( discountRow, 3, discount );

    processValueChanged( 0, 0 );

    setColumnReadOnly( 1, TRUE );
    setColumnReadOnly( 2, TRUE );
    setColumnReadOnly( 3, TRUE );

    connect( this, SIGNAL( valueChanged( int, int ) ),
             this, SLOT( processValueChanged( int, int ) ) );

    adjustColumn( 1 );
    adjustColumn( 2 );
}

void ProductList::processValueChanged( int row, int )
{
    QString total;

    if ( row != discountRow ){
        total = QString::number( calcPrice( row ) );
        setText( row, 3, total );

        total = QString::number( sumUp( 0 ) );
        setText( totalRow, 0, total + suffix );
    } else {
        clearCell( discountRow, 0 );
    }

    total = QString::number( sumUp( 3 ) );
    setText( totalRow, 3, total );
}

double ProductList::calcPrice( int row )
{
    double price = text( row, 0 ).toDouble();

    return price * text( row, 2 ).toDouble();
}

double ProductList::sumUp( int col )
{
    double sum = 0;

    for ( int i = 0; i <= discountRow; i++ )
        sum += text( i, col ).toDouble();

    return sum;
}


The main program (wineorder.cpp):

/*
$Id$
*/

#include "productlist.h"

#include <qapplication.h>

int main( int argc, char ** argv )
{
    QApplication app( argc, argv );

    ProductList * productlist = new ProductList();

    app.setMainWidget( productlist );
    productlist->show();
    return app.exec();
}


Copyright © 2000 TrolltechTrademarks
Qt version main-beta1