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

definition.cpp

/***************************************************************************
                          definition.cpp  -  description
                             -------------------
    begin                : Mit Nov 20 2002
    copyright            : (C) 2002 by Dominik Seichter
    email                : domseichter@web.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "definition.h"
#include "sqltables.h"
#include "measurements.h"

// Qt includes
#include <qtextstream.h>
#include <qsqlquery.h>
#include <qregexp.h>

// KDE includes
#include <kapplication.h>
#include <kfiledialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>

// a simple helper function
// that copies a file
bool filecopy( const char* src, const char* dest )
{
    FILE* s;
    FILE* d;
    int c;

    d = fopen(dest, "w");
    if( d == NULL )
        return false;

    s = fopen(src, "r");
    if( s == NULL ) {
        fclose( d );
        remove( dest );
        return false;
    }

    while(( c = getc( s )) != EOF )
        putc( c, d );

    fclose( s );
    fclose( d );
    return true;
}

class PrivateParser {
    public:
        PrivateParser( QString line, bool all = true );
        ~PrivateParser();

        QString getId() const { return label_def_id; }
        QString getProducer() const { return producer; }
        QString getType() const { return type; }
        Measurements* getMeasurements() const { return m; };

    private:
        QString removeQuote( const QString & q );

        QString label_def_id;
        QString producer;
        QString type;

        Measurements* m;
};

PrivateParser::PrivateParser( QString line, bool all )
{
    line = line.stripWhiteSpace();
    int pos = line.find("(");
    line = line.mid( pos + 1, line.length() - pos - 1 );

    m = new Measurements();

    label_def_id = line.section( ",", 0, 0 ).stripWhiteSpace();
    producer = removeQuote( line.section( ",", 1, 1 ) );
    type = removeQuote( line.section( ",", 2, 2 ) );
    if( all ) {
        m->setGapTopMM( line.section( ",", 4, 4 ).toDouble() );
        m->setGapLeftMM( line.section( ",", 5, 5 ).toDouble() );
        m->setHeightMM( line.section( ",", 6, 6 ).toDouble() );
        m->setWidthMM( line.section( ",", 7, 7 ).toDouble() );
        m->setGapVMM( line.section( ",", 8, 8 ).toDouble() );
        m->setGapHMM( line.section( ",", 9, 9 ).toDouble() );
        m->setNumH( line.section( ",", 10, 10 ).toInt() );
        m->setNumV( line.section( ",", 11, 11 ).toInt() );

        // fix broken label definitions
        // with numh and numv = 0
        if( !m->numH() )
            m->setNumH( 1 );

        if( !m->numV() )
            m->setNumV( 1 );
    }
}

PrivateParser::~PrivateParser()
{ }

QString PrivateParser::removeQuote( const QString & q )
{
    QString quote = q.stripWhiteSpace();

    if( quote.startsWith("'") )
        quote = quote.mid( 1, quote.length() - 1 );

    if( quote.endsWith("'") )
        quote = quote.left( quote.length() - 1 );

    return quote;
}


/***************************************************************************/

Definition::Definition()
{
    id = -1;
    m = new Measurements();
}

Definition::Definition( int label_def_id )
{
    m = new Measurements();
    init( QString("%1").arg( label_def_id ) );
}

Definition::Definition( const QString & label_def_id )
{
    m = new Measurements();
    init( label_def_id );
}

Definition::Definition( const QString & producer, const QString & type )
{
    m = new Measurements();

    if( SqlTables::isConnected() ) {
        QSqlQuery query(
            "select label_no from " TABLE_LABEL_DEF " WHERE manufacture='" + producer + "' AND type='" + type + "'");
        while( query.next() )
            init( query.value( 0 ).toString() );
    } else {
        if(!openFile())
            return;

        QString s;
        while( file->readLine( s, 1000 ) != -1 ) {
            if( s.isEmpty() || s.left( 1 ) == "#" )
                continue;

            PrivateParser p( s );
            if( p.getProducer() ==producer && p.getType() == type ) {
                init( p.getId() );
                break;
            }
        }
    }

}

Definition::~Definition()
{
    delete m;
}

QFile* Definition::file = 0;
QByteArray* Definition::array = 0;
QStringList* Definition::listProducers = 0;
QMap<QString,QStringList> Definition::mapTypes;

void Definition::setId( const QString & label_def_id )
{
    init( label_def_id );
}

void Definition::setId( int label_def_id )
{
    init( QString("%1").arg( label_def_id ) );
}

void Definition::init( const QString & label_def_id )
{
    if( SqlTables::isConnected() ) {
        QSqlQuery* query = new QSqlQuery(
            "select number_h, number_v, gap_left, gap_top, gap_v, gap_h, width, height, manufacture, type from " TABLE_LABEL_DEF
            " WHERE label_no = " + label_def_id );

        while( query->next() ) {
            m->setNumH( query->value( 0 ).toInt() );
            m->setNumV( query->value( 1 ).toInt() );
            m->setGapLeftMM( query->value( 2 ).toDouble() );
            m->setGapTopMM( query->value( 3 ).toDouble() );
            m->setGapVMM( query->value( 4 ).toDouble() );
            m->setGapHMM( query->value( 5 ).toDouble() );
            m->setWidthMM( query->value( 6 ).toDouble() );
            m->setHeightMM( query->value( 7 ).toDouble() );
            producer = query->value( 8 ).toString();
            type = query->value( 9 ).toString();
        }
    } else {
        getFileMeasurements( label_def_id );
    }

    id = label_def_id.toInt();

}

Measurements* Definition::getMeasurements() const
{
    return m;
}

void Definition::getFileMeasurements( const QString & label_def_id )
{
    if(!openFile()) {
        m = new Measurements();
        return;
    }

    QTextStream stream(*array, IO_ReadOnly );
    while( !stream.atEnd() ) {
        QString s = stream.readLine();
        if( s.isEmpty() || s.startsWith( "#" ) )
            continue;

        PrivateParser p( s );
        if( p.getId() != label_def_id )
            continue;

        producer = p.getProducer();
        type = p.getType();
        m = p.getMeasurements();
        break;
    }
}

bool Definition::openFile()
{
    if( file ) {
        file->at( 0 );
        return true;        
    }

    QString f = locateLocal( "data", "kbarcode/labeldefinitions.sql" );
    if( !QFile::exists( f ) ) {
        KConfig* config = kapp->config();
        config->setGroup( "Definitions" );

        // copy file to new location
        QString fname = config->readEntry( "defpath", locate( "data", "kbarcode/labeldefinitions.sql" ) );
        if( !QFile::exists( fname ) || fname.isEmpty() ) 
            return ( showFileError() ? openFile() : false );

        if(!filecopy( (const char*)fname, (const char*)f ))
            return ( showFileError() ? openFile() : false );
    }

    file = new QFile( f );
    if( !file->open( IO_ReadOnly ) ) {
        delete file;
        file = 0;
        return ( showFileError() ? openFile() : false );
    }

    // keeping this array around
    // increases speed quite a lot
    // but does also cost lot's of memory
    array = new QByteArray();
    *array = file->readAll();
    file->at( 0 );

    return true;
}

const QStringList Definition::getProducers()
{
    if( listProducers )
        return *listProducers;

    listProducers = new QStringList();

    if( SqlTables::isConnected() ) {
        QSqlQuery query("SELECT manufacture FROM " TABLE_LABEL_DEF " GROUP by manufacture;");
        while( query.next() )
            listProducers->append( query.value( 0 ).toString() );
    } else {
        if(!openFile() )
            return *listProducers;

        QTextStream stream(*array, IO_ReadOnly );
        while( !stream.atEnd() ) {
            QString s = stream.readLine();
            if( s.isEmpty() || s.startsWith( "#" ) )
                continue;

            PrivateParser p( s, false );
            if( !listProducers->contains( p.getProducer() ) )
                listProducers->append( p.getProducer() );
        }
    }

    return *listProducers;
}

const QStringList Definition::getTypes( QString producer )
{
    if( mapTypes.contains( producer ) ) {
        return mapTypes[producer];
    }

    QStringList list;

    if( SqlTables::isConnected() ) {
        QSqlQuery query("SELECT type FROM " TABLE_LABEL_DEF " WHERE manufacture='" + producer + "'" );
        while( query.next() )
            if( !list.contains( query.value( 0 ).toString() ) )
                    list.append( query.value( 0 ).toString() );
    } else {
        if(!openFile())
            return list;

        QTextStream stream(*array, IO_ReadOnly );
        while( !stream.atEnd() ) {
            QString s = stream.readLine();
            if( s.isEmpty() || s.startsWith( "#" ) )
                continue;

            PrivateParser p( s, false );
            if( p.getProducer() == producer )
                if( !list.contains( p.getType() ) )
                    list.append( p.getType() );
        }
    }

    mapTypes.insert( producer, list );

    return list;
}

00356 void Definition::updateProducer()
{
    // TODO: check wether this function is
    // correct! w/ SQL and without
    if( listProducers ) {
        delete listProducers;
        listProducers = 0;

        if( array ) {
            delete array;
            array = 0;
        }

        if( file ) {
            file->close();
            delete file;
            file = 0;
        }
        mapTypes.clear();
    }
}

int Definition::write( Measurements* c, QString type, QString producer )
{
    int r = -1;
    if( SqlTables::isConnected() )
        r = Definition::writeSQL( c, type, producer );
    else
        r = Definition::writeFile( c, type, producer ); 

    Definition::updateProducer();
    return r;
}

int Definition::writeFile( Measurements* c, QString type, QString producer )
{
    if( !openFile() )
        return -1;

    QStringList data;
    bool datawritten = false;
    int index = 0;
    QString entry = ", '" +
                  producer + "', '" + type + "', 'C',"+ I2S(c->gapTopMM()) +
                  ", " + I2S(c->gapLeftMM()) + ", " +
                  I2S(c->heightMM()) + ", " + I2S(c->widthMM()) + ", " +
                  I2S(c->gapVMM()) + ", " + I2S(c->gapHMM()) + ", " +
                  I2S(c->numH()) + ", " + I2S(c->numV()) + ", NULL, NULL )";
        
    QString s;
    while( file->readLine( s, 1000 ) != -1 ) {
        if( s.isEmpty() || s.left( 1 ) == "#" ) {
            data.append( s );
            continue;
        }
            
        PrivateParser p( s );
        if( p.getId().toInt() > index )
            index = p.getId().toInt();

        if( p.getType() == type && p.getProducer() == producer ) {
            // update an item already present in the list
            entry = entry.prepend( "INSERT INTO " TABLE_LABEL_DEF " VALUES (" + I2S(p.getId().toInt()) );
            data.append( entry );
            datawritten = true;
        } else
            data.append( s );
    }

    if( !datawritten ) {
        entry = entry.prepend( "INSERT INTO " TABLE_LABEL_DEF " VALUES (" + I2S(index+1) );
        data.append( entry );
    }
    
    file->close();
    if( !file->open( IO_WriteOnly ) ) {
        file->open( IO_ReadOnly );
        return -1;
    }

    QTextStream t( file );
    for( unsigned int i = 0; i < data.count(); i++ )
        t << data[i].replace( QRegExp("\\n"), "" ) << "\n";

    // get the file back to the normal stage
    file->close();
    file->open( IO_ReadOnly );

    return index + 1;
}

int Definition::writeSQL( Measurements* c, QString type, QString producer )
{
    bool newitem = true;
    QSqlQuery q( "SELECT manufacture, type FROM " TABLE_LABEL_DEF );
    // TODO: use a more inteligent query using where=
    while( q.next() )
        if( q.value( 0 ) == producer &&
            q.value( 1 ) == type )
                newitem = false;

    if( newitem ) {
        QSqlQuery query(
              "INSERT INTO " TABLE_LABEL_DEF " (manufacture, type, gap_top, gap_left, "
              "width, height, gap_v, gap_h, number_h, number_v) VALUES ('" +
              producer + "', '" + type + "', '"+ I2S( c->gapTopMM() ) +
              "', '" + I2S( c->gapLeftMM() ) + "', '" +
              I2S( c->widthMM() ) + "', '" + I2S( c->heightMM() ) + "', '" +
              I2S( c->gapVMM() ) + "', '" + I2S( c->gapHMM() ) + "', '" +
              I2S( c->numH() ) + "', '" + I2S( c->numV() ) + "')"
              );

        if(!query.isValid())
            qDebug("Query to insert values not valid!");
    } else {
        QSqlQuery query( "UPDATE " TABLE_LABEL_DEF " SET "
            "gap_top = " + I2S( c->gapTopMM() ) + " ,gap_left = " + I2S( c->gapLeftMM() ) +
            " ,width = " + I2S( c->widthMM() ) + " ,height = " + I2S( c->heightMM() ) +
            " ,gap_v = " + I2S( c->gapVMM() ) + " ,gap_h = " + I2S( c->gapHMM() ) +
            " ,number_h = " + I2S( c->numH() ) + " ,number_v = " + I2S( c->numV() ) +
            " WHERE manufacture = '" + producer + "' AND"
            " type = '" + type + "'" );

        if(!query.isValid())
            qDebug("Query to update values not valid!\n" + query.lastQuery() );
    }

    QSqlQuery qi("SELECT label_no FROM " TABLE_LABEL_DEF " WHERE manufacture='" + producer + "' AND type='" + type + "'" );
    while( qi.next() )
        return qi.value( 0 ).toInt();

    return -1;
}


bool Definition::nodefmsg = true;
bool Definition::showFileError()
{
    if( nodefmsg ) {
        KMessageBox::information( 0,
            i18n("KBarcode is unable to find its label definitions."
                 "Please make sure that the file $KDEDIR/share/apps/kbarcode/labeldefinitions.sql "
                 "does exist. This file is part of the KBarcode distribution. "
                 "You will be prompted now to select the file containing the labeldefinitions."),
                 "", "NoDefinitionsFound" );

        QString f = KFileDialog::getOpenFileName( QString::null, QString::null, 0 );
        if( !f.isEmpty() && QFile::exists( f ) ) {
            KConfig* config = kapp->config();
            config->setGroup( "Definitions" );
            config->writeEntry( "defpath", f );
            config->sync();
        }
        nodefmsg = false;
        return openFile();
    } else
        qDebug("No label definitions found. Please install them.");

    return false;
}

int Definition::getClosest( const QString & producer, const QString & type )
{
    QStringList t = Definition::getTypes(producer); 
    for( unsigned int z = 0; z < t.count(); z++ )  {
        if( t[z] == type ) {
            Definition d( producer, type );
            return d.getId();
        }
    }

    return -1;
}

Generated by  Doxygen 1.6.0   Back to index