/* This file is part of the KDE project Copyright (C) 1999 David Faure Copyright (C) 2004 Nicolas GOUTTE This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KSpread; // hehe >:-> /* To generate a test CSV file: perl -e '$i=0;while($i<30000) { print rand().",".rand()."\n"; $i++ }' > file.csv */ typedef KGenericFactory CSVImportFactory; K_EXPORT_COMPONENT_FACTORY( libcsvimport, CSVImportFactory( "kofficefilters" ) ) CSVFilter::CSVFilter(KoFilter *, const char*, const TQStringList&) : KoFilter() { } KoFilter::ConversionStatus CSVFilter::convert( const TQCString& from, const TQCString& to ) { TQString file( m_chain->inputFile() ); KoDocument* document = m_chain->outputDocument(); if ( !document ) return KoFilter::StupidError; kdDebug(30501) << "here we go... " << document->className() << endl; if ( !::tqqt_cast( document ) ) { kdWarning(30501) << "document isn't a KSpread::Doc but a " << document->className() << endl; return KoFilter::NotImplemented; } if(from!="text/x-csv" && from!="text/plain" || to!="application/x-kspread") { kdWarning(30501) << "Invalid mimetypes " << from << " " << to << endl; return KoFilter::NotImplemented; } kdDebug(30501) << "...still here..." << endl; Doc *ksdoc = static_cast( document ); // type checked above if(ksdoc->mimeType()!="application/x-kspread") { kdWarning(30501) << "Invalid document mimetype " << ksdoc->mimeType() << endl; return KoFilter::NotImplemented; } TQFile in(file); if(!in.open(IO_ReadOnly)) { KMessageBox::sorry( 0L, i18n("CSV filter cannot open input file - please report.") ); in.close(); return KoFilter::FileNotFound; } TQString csv_delimiter; // ###### FIXME: disabled for now //if (!config.isNull()) // csv_delimiter = config[0]; TQByteArray inputFile( in.readAll() ); in.close(); CSVDialog *dialog = new CSVDialog(0L, inputFile, csv_delimiter ); if (!m_chain->manager()->getBatchMode() && !dialog->exec()) return KoFilter::UserCancelled; inputFile.resize( 0 ); // Release memory (input file content) ElapsedTime t( "Filling data into document" ); Cell*cell; Sheet *sheet=ksdoc->map()->addNewSheet(); int numRows = dialog->getRows(); int numCols = dialog->getCols(); if (numRows == 0) ++numRows; int step = 100 / numRows * numCols; int value = 0; emit sigProgress(value); TQApplication::setOverrideCursor(TQt::waitCursor); int i; double init = sheet->nonDefaultColumnFormat( 1 )->dblWidth(); TQMemArray widths( numCols ); for ( i = 0; i < numCols; ++i ) widths[i] = init; Cell* c = sheet->nonDefaultCell( 1, 1 ); TQFontMetrics fm( c->format()->textFont( 1, 1 ) ); Style * s = ksdoc->styleManager()->defaultStyle(); for ( int row = 0; row < numRows; ++row ) { for (int col = 0; col < numCols; ++col) { value += step; emit sigProgress(value); const TQString text( dialog->getText( row, col ) ); // ### FIXME: how to calculate the width of numbers (as they might not be in the right format) const double len = fm.width( text ); if ( len > widths[col] ) widths[col] = len; switch (dialog->getHeader(col)) { case CSVDialog::TEXT: //see CSVDialog::accept(), Tomas introduced the Generic format between KOffice 1.3 and 1.4 //the Insert->External Data-> ... dialog uses the generic format for everything (see mentioned method) //I will use this approach only for the TEXT format in the CSV import filter... (raphael) //### FIXME: long term solution is to allow to select Generic format ("autodetect") in the dialog and make it the default cell = sheet->nonDefaultCell( col + 1, row + 1, false, s ); cell->setCellText( text ); cell->format()->setFormatType (Generic_format); /* old code cell = sheet->nonDefaultCell( col + 1, row + 1, false, s ); cell->setCellText( text, true ); */ break; // ### TODO: put the code for the different numbers together (at least partially) case CSVDialog::NUMBER: { bool ok = false; double d = ksdoc->locale()->readNumber( text, &ok ); // If not, try with the '.' as decimal separator if ( !ok ) d = text.toDouble( &ok ); if ( !ok ) { cell = sheet->nonDefaultCell( col + 1, row + 1, false, s ); cell->setCellText( text, true ); } else { cell = sheet->nonDefaultCell( col + 1, row + 1, false, s ); cell->setNumber( d ); } cell->format()->setPrecision( 2 ); break; } case CSVDialog::COMMANUMBER: { bool ok = false; TQString tmp ( text ); tmp.remove ( TQRegExp( "[^0-9,Ee+-]" ) ); // Keep only 0 to 9, comma, E, e, plus, minus tmp.replace ( ',', '.' ); kdDebug(30501) << "Comma: " << text << " => " << tmp << endl; const double d = tmp.toDouble( &ok ); if ( !ok ) { cell = sheet->nonDefaultCell( col + 1, row + 1, false, s ); cell->setCellText( text, true ); } else { cell = sheet->nonDefaultCell( col + 1, row + 1, false, s ); cell->setNumber( d ); } cell->format()->setPrecision( 2 ); break; } case CSVDialog::POINTNUMBER: { bool ok = false; TQString tmp ( text ); tmp.remove ( TQRegExp( "[^0-9\\.EeD+-]" ) ); // Keep only 0 to 9, dot, E, e, D, plus, minus tmp.replace ( 'D', 'E' ); // double from FORTRAN use D instead of E kdDebug(30501) << "Point: " << text << " => " << tmp << endl; const double d = tmp.toDouble( &ok ); if ( !ok ) { cell = sheet->nonDefaultCell( col + 1, row + 1, false, s ); cell->setCellText( text, true ); } else { cell = sheet->nonDefaultCell( col + 1, row + 1, false, s ); cell->setNumber( d ); } cell->format()->setPrecision( 2 ); break; } case CSVDialog::DATE: cell = sheet->nonDefaultCell( col + 1, row + 1, false, s ); cell->setCellText( text ); cell->format()->setFormatType( ShortDate_format ); break; case CSVDialog::CURRENCY: cell = sheet->nonDefaultCell( col + 1, row + 1, false, s ); cell->setCellText( text, false ); cell->format()->setFormatType( Money_format ); cell->format()->setPrecision( 2 ); break; } } } emit sigProgress( 98 ); ElapsedTime t2( "Resizing columns" ); for ( i = 0; i < numCols; ++i ) { ColumnFormat * c = sheet->nonDefaultColumnFormat( i + 1 ); c->setDblWidth( widths[i] ); } emit sigProgress( 100 ); TQApplication::restoreOverrideCursor(); delete dialog; return KoFilter::OK; } #include