diff options
Diffstat (limited to 'filters/kspread/csv/csvimport.cpp')
-rw-r--r-- | filters/kspread/csv/csvimport.cpp | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/filters/kspread/csv/csvimport.cpp b/filters/kspread/csv/csvimport.cpp new file mode 100644 index 000000000..72cadfa2b --- /dev/null +++ b/filters/kspread/csv/csvimport.cpp @@ -0,0 +1,264 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <faure@kde.org> + Copyright (C) 2004 Nicolas GOUTTE <goutte@kde.org> + + 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 <csvimport.h> + +#include <tqfile.h> +#include <tqregexp.h> + +#include <tdeapplication.h> +#include <tdemessagebox.h> +#include <kdebug.h> +#include <kgenericfactory.h> + +#include <KoFilterChain.h> +#include <KoFilterManager.h> +#include <kspread_doc.h> +#include <kspread_global.h> +#include <kspread_map.h> +#include <kspread_sheet.h> +#include <kspread_style.h> +#include <kspread_style_manager.h> +#include <kspread_cell.h> + +#include <csvdialog.h> + +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<CSVFilter, KoFilter> 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<const KSpread::Doc *>( 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<Doc *>( 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<double> 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 <csvimport.moc> |