Logo Search packages:      
Sourcecode: datakiosk version File versions  Download package

datatableedit.cpp

/***************************************************************************
*   Copyright (C) 2005 by Adam Treat                                      *
*   treat@kde.org                                                         *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************/

#include "datatableedit.h"
#include "formlayout.h"
#include "datatableeditorfactory.h"

#include <qcolor.h>
#include <qpalette.h>
#include <qpushbutton.h>

#include <qlabel.h>
#include <qpainter.h>
#include <qsqlform.h>
#include <qdrawutil.h>
#include <qsqlpropertymap.h>

#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>

ScrollForm::ScrollForm( QWidget *parent, const char *name )
        : QScrollView( parent, name ),
        m_frameColor( Qt::green )
{
    setResizePolicy( QScrollView::AutoOneFit );
}

ScrollForm::~ScrollForm()
{}

void ScrollForm::drawFrame( QPainter* p )
{
    qDrawPlainRect( p, frameRect(), m_frameColor, 2 );
}

QColor ScrollForm::getFrameColor() const
{
    return m_frameColor;
}

void ScrollForm::setFrameColor( const QColor &color )
{
    m_frameColor = color;
}

DataTableEdit::DataTableEdit( QWidget *parent, const char *name )
        : QDataBrowser( parent, name ),
        m_map( 0L ),
        m_commit( 0L ),
        m_refreshing( false ),
        m_inserting( false ),
        m_currentRow( 0 )
{

    setConfirmInsert( true );
    setConfirmDelete( true );

    setAutoEdit( false );
    setForm( new QSqlForm() );

    QVBoxLayout *topLayout = new QVBoxLayout( this, 10, 10 );

    m_scroll = new ScrollForm( this );
    m_formBox = new QFrame( m_scroll->viewport() );

    QVBoxLayout *viewPortLayout = new QVBoxLayout( m_scroll->viewport(), 0, 0 );
    viewPortLayout->add(m_formBox);

    m_formLayout = new FormLayout( m_formBox, 20, 20 );
    m_scroll->addChild( m_formBox );

    QFrame *buttonBox = new QFrame(this);
    QHBoxLayout *buttonLayout = new QHBoxLayout( buttonBox, 0, 20 );

    QPushButton *f = new QPushButton( "|< First", buttonBox );
    QPushButton *p = new QPushButton( "<< Prev", buttonBox );
    QPushButton *n = new QPushButton( "Next >>", buttonBox );
    QPushButton *l = new QPushButton( "Last >|", buttonBox );
    m_commit = new QPushButton( "Commit", buttonBox );
    m_commit->setEnabled( false );

    f->setFocusPolicy( QWidget::ClickFocus );
    p->setFocusPolicy( QWidget::ClickFocus );
    n->setFocusPolicy( QWidget::ClickFocus );
    l->setFocusPolicy( QWidget::ClickFocus );
    m_commit->setFocusPolicy( QWidget::ClickFocus );

    QSpacerItem *hSpace = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );

    buttonLayout->add( f );
    buttonLayout->add( p );
    buttonLayout->add( n );
    buttonLayout->add( l );
    buttonLayout->addItem( hSpace );
    buttonLayout->add( m_commit );

    topLayout->add( m_scroll );
    topLayout->add( buttonBox );

    QObject::connect( f, SIGNAL( clicked() ), this, SLOT( first() ) );
    QObject::connect( p, SIGNAL( clicked() ), this, SLOT( prev() ) );
    QObject::connect( n, SIGNAL( clicked() ), this, SLOT( next() ) );
    QObject::connect( l, SIGNAL( clicked() ), this, SLOT( last() ) );
    QObject::connect( m_commit, SIGNAL( clicked() ), this, SLOT( update() ) );
}

DataTableEdit::~DataTableEdit()
{}

void DataTableEdit::addEditorBase( DataEditorBase *editor, bool isVirtual )
{
    m_formLayout->add( editor );
    if ( !isVirtual )
    {
        form()->insert( editor->getEditor(), editor->getField()->name() );
        QObject::connect( editor, SIGNAL( editBufferChanged( QVariant, bool ) ),
                          this, SLOT( toggleColorBox() ) );
        QObject::connect( editor, SIGNAL( addConstraint( DataEditorBase *, const QString & ) ),
                          this, SLOT( constrainEditor( DataEditorBase *, const QString & ) ) );
    }
    editor->show();
}

void DataTableEdit::removeEditors()
{
    form()->clear();
    QLayoutIterator it = m_formLayout->iterator();
    QLayoutItem *item;
    while ( (item = it.takeCurrent()) )
    {
        DataEditorBase *editor = ::qt_cast<DataEditorBase*>( item->widget() );
        delete editor;
        delete item;
    }
}

void DataTableEdit::installPropertyMap( QSqlPropertyMap *map )
{
    m_map = map;
    form()->installPropertyMap( map );
}

FormLayout* DataTableEdit::getFormLayout() const
{
    return m_formLayout;
}

ScrollForm* DataTableEdit::getScrollView() const
{
    return m_scroll;
}

QFrame* DataTableEdit::getFormBox() const
{
    return m_formBox;
}

QVariant DataTableEdit::currentValue( const QString &field )
{
    QSqlField *f = sqlCursor()->editBuffer()->field( field );
    if ( f )
    {
        QWidget *w = form()->fieldToWidget( f );
        if ( w && m_map )
        {
            QVariant v = m_map->property( w );
            if ( !v.isNull() )
                return v;
        }

        return f->value();
    }

    return QVariant();
}

void DataTableEdit::setCurrentRow( int row )
{
    if ( row == -1 )
    {
        form()->clearValues( true );
        setEnabled( false );
        m_scroll->viewport()->hide();
    }
    else if ( !isEnabled() )
    {
        setEnabled( true );
        m_scroll->viewport()->show();
    }

    seek( row, false );
}

bool DataTableEdit::seek( int i, bool relative )
{
    m_currentRow = i;

    //If we are currently inserting, but the cursor
    //is valid then we've aborted the insert before the
    //commit.
    if ( m_inserting && sqlCursor()->at() == i )
        emit insertAborted();

    //The DataTableView sends us this extra signal
    //so we make sure the cursor is still invalid during
    //our commit.
    if ( m_inserting )
        m_inserting = sqlCursor()->at() != i;

    if ( !m_inserting )
    {
        changeColorBox( Qt::green );
        m_commit->setEnabled( false );
    }

    bool temp = QDataBrowser::seek( i, relative );

    return temp;
}

void DataTableEdit::first()
{
    emit selectedFirst();
}

void DataTableEdit::prev()
{
    emit selectedPrev();
}

void DataTableEdit::next()
{
    emit selectedNext();
}

void DataTableEdit::last()
{
    emit selectedLast();
}

void DataTableEdit::update()
{
    if ( !m_commit->isEnabled() )
        return;

    m_inserting = false;
    ///TODO Write own version of update to get rid of unnecessary seeks
    /// and invalidated updates.
    QDataBrowser::update();
    seek( m_currentRow, false );
    changeColorBox( Qt::green );
    m_commit->setEnabled( false );
    emit selectedRow( m_currentRow );
}

bool DataTableEdit::insertRecord()
{
    if ( confirmInsert() )
        if ( KMessageBox::Continue !=
             KMessageBox::warningContinueCancel( this, i18n( "You are about to insert a record. Are you sure?" ) ) )
                return false;

    m_inserting = true;
    QDataBrowser::insert();
    changeColorBox( Qt::red );
    m_commit->setEnabled( true );
    return true;
}

bool DataTableEdit::deleteRecord()
{
    if ( confirmDelete() )
        if ( KMessageBox::Continue !=
             KMessageBox::warningContinueCancel( this, i18n( "You are about to delete a record. Are you sure?" ) ) )
            return false;

    bool success = QDataBrowser::deleteCurrent();
    if ( success )
    {
        changeColorBox( Qt::green );
        m_commit->setEnabled( false );
    }
    return success;
}

void DataTableEdit::refresh()
{
    m_refreshing = true;
    QDataBrowser::refresh();
    m_refreshing = false;
}

void DataTableEdit::readFields()
{
    m_refreshing = true;
    QDataBrowser::readFields();

    QLayoutIterator it = m_formLayout->iterator();
    QLayoutItem *item;
    while ( (item = it.current()) != 0 )
    {
        DataEditorBase *editor = ::qt_cast<DataEditorBase*>( item->widget() );
        if ( !editor->getField() )
        {
            editor->calculateEditor(); //This editor points to a virtual field
            ++it;
            continue;
        }

        if ( editor->getField()->isNull() )
        {
            editor->setNullValue( "" ); //needs to sync with QDataTable::nullText
        }
        ++it;
    }

    m_refreshing = false;
}

void DataTableEdit::calculateFields()
{
    QLayoutIterator it = m_formLayout->iterator();
    QLayoutItem *item;
    while ( (item = it.current()) != 0 )
    {
        DataEditorBase *editor = ::qt_cast<DataEditorBase*>( item->widget() );
        if ( !editor->getField() )
            editor->calculateEditor(); //This editor points to a virtual field
        ++it;
    }
}

void DataTableEdit::toggleColorBox()
{
    if ( m_refreshing )
        return;

    QColor color = m_scroll->getFrameColor();

    if ( color == Qt::green && currentEdited() )
    {
        changeColorBox( Qt::red );
        m_commit->setEnabled( true );
    }
    else if ( color == Qt::red && !currentEdited() )
    {
        changeColorBox( Qt::green );
        m_commit->setEnabled( false );
    }
}

void DataTableEdit::constrainEditor( DataEditorBase *editor, const QString &field )
{
    DataEditorBase *constraint = 0;
    QLayoutIterator it = m_formLayout->iterator();
    QLayoutItem *item;
    while ( (item = it.current()) != 0 )
    {
        DataEditorBase *eb = ::qt_cast<DataEditorBase*>( item->widget() );
        if ( !eb->getField() )
        {
            ++it;
            continue;
        }

        if ( eb->getField()->name() == field )
        {
            constraint = eb;
            break;
        }
        ++it;
    }

    if ( constraint )
    {
        QObject::connect( constraint, SIGNAL( editBufferChanged( QVariant, bool ) ),
                          editor, SLOT( resetEditBuffer( QVariant, bool ) ) );
    }
}

QSql::Confirm DataTableEdit::confirmEdit( QSql::Op /*m*/ )
{
    return QSql::Yes;
}

void DataTableEdit::showEvent( QShowEvent *ev )
{
    QDataBrowser::showEvent( ev );
    if ( !m_formLayout )
        return;

    QLayoutIterator it = m_formLayout->iterator();
    QLayoutItem *item = it.current();

    if ( !item )
        return;

    if ( DataEditorBase *editor = ::qt_cast<DataEditorBase*>( item->widget() ) )
        editor->setFocus();
}

bool DataTableEdit::currentEdited()
{
    bool edited = false;
    QLayoutIterator it = m_formLayout->iterator();
    QLayoutItem *item;
    while ( (item = it.current()) != 0 )
    {
        DataEditorBase *editor = ::qt_cast<DataEditorBase*>( item->widget() );
        if ( editor->currentEdited() )
        {
            edited = true;
        }
        ++it;
    }
    return edited;
}

void DataTableEdit::handleError( const QSqlError &error )
{
    QSqlError err;
    //If currentEdited() != QDataBrowser::currentEdited()
    //we know that the user put an incorrect string in a
    //relation combo.  Eventually should track the combo and highlight it
    if ( currentEdited() && !QDataBrowser::currentEdited() )
        err = QSqlError ( error.driverText(),
            "Data Relation Error!\nCheck your dropdown boxes...",
            error.type(), error.number() );
    else
        err = error;

    kdDebug() << "Error in query = " << sqlCursor()->lastQuery() << endl;
    QDataBrowser::handleError( error );
}

void DataTableEdit::changeColorBox( QColor color )
{
    QColor cur = m_scroll->getFrameColor();
    if ( cur == color)
        return;

    m_scroll->setFrameColor( color );
    m_scroll->repaint();
    emit colorBoxChanged( color );
}

#include "datatableedit.moc"

Generated by  Doxygen 1.6.0   Back to index