diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /filters/kspread/csv | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'filters/kspread/csv')
-rw-r--r-- | filters/kspread/csv/DESIGN | 37 | ||||
-rw-r--r-- | filters/kspread/csv/Makefile.am | 22 | ||||
-rw-r--r-- | filters/kspread/csv/README | 10 | ||||
-rw-r--r-- | filters/kspread/csv/TODO | 5 | ||||
-rw-r--r-- | filters/kspread/csv/csvdialog.cpp | 635 | ||||
-rw-r--r-- | filters/kspread/csv/csvdialog.h | 89 | ||||
-rw-r--r-- | filters/kspread/csv/csvexport.cc | 382 | ||||
-rw-r--r-- | filters/kspread/csv/csvexport.h | 49 | ||||
-rw-r--r-- | filters/kspread/csv/csvexportdialog.cpp | 332 | ||||
-rw-r--r-- | filters/kspread/csv/csvexportdialog.h | 72 | ||||
-rw-r--r-- | filters/kspread/csv/csvimport.cc | 264 | ||||
-rw-r--r-- | filters/kspread/csv/csvimport.h | 35 | ||||
-rw-r--r-- | filters/kspread/csv/dialogui.ui | 554 | ||||
-rw-r--r-- | filters/kspread/csv/exportdialogui.ui | 510 | ||||
-rw-r--r-- | filters/kspread/csv/kspread_csv_export.desktop | 73 | ||||
-rw-r--r-- | filters/kspread/csv/kspread_csv_import.desktop | 72 | ||||
-rw-r--r-- | filters/kspread/csv/status.html | 202 | ||||
-rw-r--r-- | filters/kspread/csv/xmltree.cc | 154 | ||||
-rw-r--r-- | filters/kspread/csv/xmltree.h | 53 |
19 files changed, 3550 insertions, 0 deletions
diff --git a/filters/kspread/csv/DESIGN b/filters/kspread/csv/DESIGN new file mode 100644 index 00000000..9c6c4c90 --- /dev/null +++ b/filters/kspread/csv/DESIGN @@ -0,0 +1,37 @@ +The CSV import filter uses a hand-made state machine to parse the CSV file. +This allows to handle quoted fields (such as those containing the CSV delimiter), +as well as the double-quote character itself (which then appears twice, and +always in a quoted field). +Just to make sure about the vocabulary, I call a quoted field a field +starting with " and finishing with ". + +Let's try to draw the graph of the state machine using ascii-art. + + + DEL or EOL + /--\ + | | + | v " + /--[START]-------->[QUOTED_FIELD] (**) + other| ^ ^ | ^ + (*) | | | DEL or | " | " (*) + | | | EOL v | + | | \----[MAYBE_END_OF_QUOTED_FIELD] + | | | + | | DEL or | + | | EOL | other + | | | + v | /------<-------| + [NORMAL_FIELD] (**) + +DEL : CSV delimiter (depends on locale !). Often comma, sometimes semicolon. +EOL : End Of Line. +(*) : added to the current field +(**) : implicit loop on itself, labeled "other (*)" + + +Ugly isn't it ? :) One can't be good in drawings AND in hacking :) + +That's all. For the rest, see csvfilter.cc + +David Faure <[email protected]>, 1999 diff --git a/filters/kspread/csv/Makefile.am b/filters/kspread/csv/Makefile.am new file mode 100644 index 00000000..32c8408a --- /dev/null +++ b/filters/kspread/csv/Makefile.am @@ -0,0 +1,22 @@ +####### General stuff + +INCLUDES= -I$(srcdir) -I$(top_srcdir)/kspread $(KOFFICE_INCLUDES) \ + $(KOTEXT_INCLUDES) $(all_includes) + +####### Files + +kde_module_LTLIBRARIES = libcsvimport.la libcsvexport.la + +libcsvimport_la_SOURCES = csvimport.cc xmltree.cc csvdialog.cpp dialogui.ui +libcsvimport_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +libcsvimport_la_LIBADD = $(KOFFICE_LIBS) ../../../kspread/libkspreadcommon.la + +libcsvexport_la_SOURCES = csvexport.cc csvexportdialog.cpp exportdialogui.ui +libcsvexport_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +libcsvexport_la_LIBADD = $(KOFFICE_LIBS) ../../../kspread/libkspreadcommon.la + +METASOURCES = AUTO + +service_DATA = kspread_csv_import.desktop kspread_csv_export.desktop + +servicedir = $(kde_servicesdir) diff --git a/filters/kspread/csv/README b/filters/kspread/csv/README new file mode 100644 index 00000000..77921a28 --- /dev/null +++ b/filters/kspread/csv/README @@ -0,0 +1,10 @@ +This is a CSV filter for kspread. + +At first it was only an input filter, hence the files named "csvfilter*". +Then I added an export filter and named it csvexport* + +Read DESIGN for the gory details, TODO for how to help, the source for why +it screwed up your data. + +David Faure <[email protected]> ( CSV import and export ) +Werner Trobin <[email protected]> ( CSV filter dialogs ) diff --git a/filters/kspread/csv/TODO b/filters/kspread/csv/TODO new file mode 100644 index 00000000..4e61c3eb --- /dev/null +++ b/filters/kspread/csv/TODO @@ -0,0 +1,5 @@ +* Automatically adjust the columns width to their contents. + Will be difficult, as we don't know the font used... + Solution ? Set a default font _in_ the filter, and use it to compute + the width... + diff --git a/filters/kspread/csv/csvdialog.cpp b/filters/kspread/csv/csvdialog.cpp new file mode 100644 index 00000000..2757e72b --- /dev/null +++ b/filters/kspread/csv/csvdialog.cpp @@ -0,0 +1,635 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <[email protected]> + Copyright (C) 2004 Nicolas GOUTTE <[email protected]> + + 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 <dialogui.h> +#include <csvdialog.h> + +#include <qtable.h> +#include <qcheckbox.h> +#include <qcursor.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qspinbox.h> +#include <qtextstream.h> +#include <qbuttongroup.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qtextcodec.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> +#include <kcombobox.h> +#include <kmessagebox.h> +#include <kcharsets.h> + +CSVDialog::CSVDialog(QWidget* parent, QByteArray& fileArray, const QString /*seperator*/) + : KDialogBase(parent, 0, true, QString::null, Ok|Cancel, No, true), + m_adjustRows(false), + m_adjustCols(false), + m_startRow(0), + m_startCol(0), + m_endRow(-1), + m_endCol(-1), + m_textquote('"'), + m_delimiter(","), + m_ignoreDups(false), + m_fileArray(fileArray), + m_dialog(new DialogUI(this)), + m_codec( QTextCodec::codecForName( "UTF-8" ) ) +{ + setCaption( i18n( "Import" ) ); + kapp->restoreOverrideCursor(); + + QStringList encodings; + encodings << i18n( "Descriptive encoding name", "Recommended ( %1 )" ).arg( "UTF-8" ); + encodings << i18n( "Descriptive encoding name", "Locale ( %1 )" ).arg( QTextCodec::codecForLocale()->name() ); + encodings += KGlobal::charsets()->descriptiveEncodingNames(); + // Add a few non-standard encodings, which might be useful for text files + const QString description(i18n("Descriptive encoding name","Other ( %1 )")); + encodings << description.arg("Apple Roman"); // Apple + encodings << description.arg("IBM 850") << description.arg("IBM 866"); // MS DOS + encodings << description.arg("CP 1258"); // Windows + m_dialog->comboBoxEncoding->insertStringList(encodings); + + m_formatList << i18n( "Text" ); + m_formatList << i18n( "Number" ); + m_formatList << i18n( "Currency" ); + m_formatList << i18n( "Date" ); + m_formatList << i18n( "Decimal Comma Number" ); + m_formatList << i18n( "Decimal Point Number" ); + m_dialog->m_formatComboBox->insertStringList( m_formatList ); + + m_dialog->m_sheet->setReadOnly( true ); + + loadSettings(); + + fillTable(); + + //resize(sizeHint()); + resize( 600, 400 ); // Try to show as much as possible of the table view + setMainWidget(m_dialog); + + m_dialog->m_sheet->setSelectionMode( QTable::Multi ); + + connect(m_dialog->m_formatComboBox, SIGNAL(activated( const QString& )), + this, SLOT(formatChanged( const QString& ))); + connect(m_dialog->m_delimiterBox, SIGNAL(clicked(int)), + this, SLOT(delimiterClicked(int))); + connect(m_dialog->m_delimiterEdit, SIGNAL(returnPressed()), + this, SLOT(returnPressed())); + connect(m_dialog->m_delimiterEdit, SIGNAL(textChanged ( const QString & )), + this, SLOT(formatChanged ( const QString & ) )); + connect(m_dialog->m_comboQuote, SIGNAL(activated(const QString &)), + this, SLOT(textquoteSelected(const QString &))); + connect(m_dialog->m_sheet, SIGNAL(currentChanged(int, int)), + this, SLOT(currentCellChanged(int, int))); + connect(m_dialog->m_ignoreDuplicates, SIGNAL(stateChanged(int)), + this, SLOT(ignoreDuplicatesChanged(int))); + connect(m_dialog->m_updateButton, SIGNAL(clicked()), + this, SLOT(updateClicked())); + connect(m_dialog->comboBoxEncoding, SIGNAL(textChanged ( const QString & )), + this, SLOT(encodingChanged ( const QString & ) )); +} + +CSVDialog::~CSVDialog() +{ + saveSettings(); + kapp->setOverrideCursor(Qt::waitCursor); +} + +void CSVDialog::loadSettings() +{ + KConfig *config = kapp->config(); + config->setGroup("CSVDialog Settings"); + m_textquote = config->readEntry("textquote", "\"")[0]; + m_delimiter = config->readEntry("delimiter", ","); + m_ignoreDups = config->readBoolEntry("ignoreDups", false); + const QString codecText = config->readEntry("codec", ""); + + // update widgets + if (!codecText.isEmpty()) { + m_dialog->comboBoxEncoding->setCurrentText(codecText); + m_codec = getCodec(); + } + if (m_delimiter == ",") m_dialog->m_radioComma->setChecked(true); + else if (m_delimiter == "\t") m_dialog->m_radioTab->setChecked(true); + else if (m_delimiter == " ") m_dialog->m_radioSpace->setChecked(true); + else if (m_delimiter == ";") m_dialog->m_radioSemicolon->setChecked(true); + else { + m_dialog->m_radioOther->setChecked(true); + m_dialog->m_delimiterEdit->setText(m_delimiter); + } + m_dialog->m_ignoreDuplicates->setChecked(m_ignoreDups); + m_dialog->m_comboQuote->setCurrentItem(m_textquote == '\'' ? 1 + : m_textquote == '"' ? 0 : 2); +} + +void CSVDialog::saveSettings() +{ + KConfig *config = kapp->config(); + config->setGroup("CSVDialog Settings"); + QString q = m_textquote; + config->writeEntry("textquote", q); + config->writeEntry("delimiter", m_delimiter); + config->writeEntry("ignoreDups", m_ignoreDups); + config->writeEntry("codec", m_dialog->comboBoxEncoding->currentText()); + config->sync(); +} + +void CSVDialog::fillTable( ) +{ + int row, column; + bool lastCharDelimiter = false; + enum { S_START, S_QUOTED_FIELD, S_MAYBE_END_OF_QUOTED_FIELD, S_END_OF_QUOTED_FIELD, + S_MAYBE_NORMAL_FIELD, S_NORMAL_FIELD } state = S_START; + + QChar x; + QString field; + + kapp->setOverrideCursor(Qt::waitCursor); + + for (row = 0; row < m_dialog->m_sheet->numRows(); ++row) + for (column = 0; column < m_dialog->m_sheet->numCols(); ++column) + m_dialog->m_sheet->clearCell(row, column); + + int maxColumn = 1; + row = column = 1; + QTextStream inputStream(m_fileArray, IO_ReadOnly); + kdDebug(30501) << "Encoding: " << m_codec->name() << endl; + inputStream.setCodec( m_codec ); + + bool lastCharWasCr = false; // Last character was a Carriage Return + while (!inputStream.atEnd()) + { + inputStream >> x; // read one char + + // ### TODO: we should perhaps skip all other control characters + if ( x == '\r' ) + { + // We have a Carriage Return, assume that its role is the one of a LineFeed + lastCharWasCr = true; + x = '\n'; // Replace by Line Feed + } + else if ( x == '\n' && lastCharWasCr ) + { + // The end of line was already handled by the Carriage Return, so do nothing for this character + lastCharWasCr = false; + continue; + } + else if ( x == QChar( 0xc ) ) + { + // We have a FormFeed, skip it + lastCharWasCr = false; + continue; + } + else + { + lastCharWasCr = false; + } + + if ( column > maxColumn ) + maxColumn = column; + + switch (state) + { + case S_START : + if (x == m_textquote) + { + state = S_QUOTED_FIELD; + } + else if (x == m_delimiter) + { + if ((m_ignoreDups == false) || (lastCharDelimiter == false)) + ++column; + lastCharDelimiter = true; + } + else if (x == '\n') + { + ++row; + column = 1; + if ( row > ( m_endRow - m_startRow ) && m_endRow >= 0 ) + break; + } + else + { + field += x; + state = S_MAYBE_NORMAL_FIELD; + } + break; + case S_QUOTED_FIELD : + if (x == m_textquote) + { + state = S_MAYBE_END_OF_QUOTED_FIELD; + } + else + { + field += x; + } + break; + case S_MAYBE_END_OF_QUOTED_FIELD : + if (x == m_textquote) + { + field += x; + state = S_QUOTED_FIELD; + } + else if (x == m_delimiter || x == '\n') + { + setText(row - m_startRow, column - m_startCol, field); + field = QString::null; + if (x == '\n') + { + ++row; + column = 1; + if ( row > ( m_endRow - m_startRow ) && m_endRow >= 0 ) + break; + } + else + { + if ((m_ignoreDups == false) || (lastCharDelimiter == false)) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } + else + { + state = S_END_OF_QUOTED_FIELD; + } + break; + case S_END_OF_QUOTED_FIELD : + if (x == m_delimiter || x == '\n') + { + setText(row - m_startRow, column - m_startCol, field); + field = QString::null; + if (x == '\n') + { + ++row; + column = 1; + if ( row > ( m_endRow - m_startRow ) && m_endRow >= 0 ) + break; + } + else + { + if ((m_ignoreDups == false) || (lastCharDelimiter == false)) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } + break; + case S_MAYBE_NORMAL_FIELD : + if (x == m_textquote) + { + field = QString::null; + state = S_QUOTED_FIELD; + break; + } + case S_NORMAL_FIELD : + if (x == m_delimiter || x == '\n') + { + setText(row - m_startRow, column - m_startCol, field); + field = QString::null; + if (x == '\n') + { + ++row; + column = 1; + if ( row > ( m_endRow - m_startRow ) && m_endRow >= 0 ) + break; + } + else + { + if ((m_ignoreDups == false) || (lastCharDelimiter == false)) + ++column; + lastCharDelimiter = true; + } + state = S_START; + } + else + { + field += x; + } + } + if (x != m_delimiter) + lastCharDelimiter = false; + } + + if ( !field.isEmpty() ) + { + // the last line of the file had not any line end + setText(row - m_startRow, column - m_startCol, field); + ++row; + field = QString::null; + } + + m_adjustCols = true; + adjustRows( row - m_startRow ); + adjustCols( maxColumn - m_startCol ); + m_dialog->m_colEnd->setMaxValue( maxColumn ); + if ( m_endCol == -1 ) + m_dialog->m_colEnd->setValue( maxColumn ); + + + for (column = 0; column < m_dialog->m_sheet->numCols(); ++column) + { + const QString header = m_dialog->m_sheet->horizontalHeader()->label(column); + if ( m_formatList.find( header ) == m_formatList.end() ) + m_dialog->m_sheet->horizontalHeader()->setLabel(column, i18n("Text")); + + m_dialog->m_sheet->adjustColumn(column); + } + fillComboBox(); + + kapp->restoreOverrideCursor(); +} + +void CSVDialog::fillComboBox() +{ + if ( m_endRow == -1 ) + m_dialog->m_rowEnd->setValue( m_dialog->m_sheet->numRows() ); + else + m_dialog->m_rowEnd->setValue( m_endRow ); + + if ( m_endCol == -1 ) + m_dialog->m_colEnd->setValue( m_dialog->m_sheet->numCols() ); + else + m_dialog->m_colEnd->setValue( m_endCol ); + + m_dialog->m_rowEnd->setMinValue( 1 ); + m_dialog->m_colEnd->setMinValue( 1 ); + m_dialog->m_rowEnd->setMaxValue( m_dialog->m_sheet->numRows() ); + m_dialog->m_colEnd->setMaxValue( m_dialog->m_sheet->numCols() ); + + m_dialog->m_rowStart->setMinValue( 1 ); + m_dialog->m_colStart->setMinValue( 1 ); + m_dialog->m_rowStart->setMaxValue( m_dialog->m_sheet->numRows() ); + m_dialog->m_colStart->setMaxValue( m_dialog->m_sheet->numCols() ); +} + +int CSVDialog::getRows() +{ + int rows = m_dialog->m_sheet->numRows(); + if ( m_endRow >= 0 ) + { + if ( rows > ( m_startRow + m_endRow ) ) + rows = m_startRow + m_endRow; + } + + return rows; +} + +int CSVDialog::getCols() +{ + int cols = m_dialog->m_sheet->numCols(); + if ( m_endCol >= 0 ) + { + if ( cols > ( m_startCol + m_endCol ) ) + cols = m_startCol + m_endCol; + } + + return cols; +} + +int CSVDialog::getHeader(int col) +{ + QString header = m_dialog->m_sheet->horizontalHeader()->label(col); + + if (header == i18n("Text")) + return TEXT; + else if (header == i18n("Number")) + return NUMBER; + else if (header == i18n("Currency")) + return CURRENCY; + else if ( header == i18n( "Date" ) ) + return DATE; + else if ( header == i18n( "Decimal Comma Number" ) ) + return COMMANUMBER; + else if ( header == i18n( "Decimal Point Number" ) ) + return POINTNUMBER; + else + return TEXT; // Should not happen +} + +QString CSVDialog::getText(int row, int col) +{ + return m_dialog->m_sheet->text( row, col ); +} + +void CSVDialog::setText(int row, int col, const QString& text) +{ + if ( row < 1 || col < 1 ) // skipped by the user + return; + + if ( ( row > ( m_endRow - m_startRow ) && m_endRow > 0 ) || ( col > ( m_endCol - m_startCol ) && m_endCol > 0 ) ) + return; + + if ( m_dialog->m_sheet->numRows() < row ) + { + m_dialog->m_sheet->setNumRows( row + 5000 ); /* We add 5000 at a time to limit recalculations */ + m_adjustRows = true; + } + + if ( m_dialog->m_sheet->numCols() < col ) + { + m_dialog->m_sheet->setNumCols( col ); + m_adjustCols = true; + } + + m_dialog->m_sheet->setText( row - 1, col - 1, text ); +} + +/* + * Called after the first fillTable() when number of rows are unknown. + */ +void CSVDialog::adjustRows(int iRows) +{ + if (m_adjustRows) + { + m_dialog->m_sheet->setNumRows( iRows ); + m_adjustRows = false; + } +} + +void CSVDialog::adjustCols(int iCols) +{ + if (m_adjustCols) + { + m_dialog->m_sheet->setNumCols( iCols ); + m_adjustCols = false; + + if ( m_endCol == -1 ) + { + if ( iCols > ( m_endCol - m_startCol ) ) + iCols = m_endCol - m_startCol; + + m_dialog->m_sheet->setNumCols( iCols ); + } + } +} + +void CSVDialog::returnPressed() +{ + if (m_dialog->m_delimiterBox->id(m_dialog->m_delimiterBox->selected()) != 4) + return; + + m_delimiter = m_dialog->m_delimiterEdit->text(); + fillTable(); +} + +void CSVDialog::textChanged ( const QString & ) +{ + m_dialog->m_radioOther->setChecked ( true ); + delimiterClicked(4); // other +} + +void CSVDialog::formatChanged( const QString& newValue ) +{ + //kdDebug(30501) << "CSVDialog::formatChanged:" << newValue << endl; + for ( int i = 0; i < m_dialog->m_sheet->numSelections(); ++i ) + { + QTableSelection select ( m_dialog->m_sheet->selection( i ) ); + for ( int j = select.leftCol(); j <= select.rightCol() ; ++j ) + { + m_dialog->m_sheet->horizontalHeader()->setLabel( j, newValue ); + + } + } +} + +void CSVDialog::delimiterClicked(int id) +{ + switch (id) + { + case 0: // comma + m_delimiter = ","; + break; + case 4: // other + m_delimiter = m_dialog->m_delimiterEdit->text(); + break; + case 2: // tab + m_delimiter = "\t"; + break; + case 3: // space + m_delimiter = " "; + break; + case 1: // semicolon + m_delimiter = ";"; + break; + } + + fillTable(); +} + +void CSVDialog::textquoteSelected(const QString& mark) +{ + if (mark == i18n("None")) + m_textquote = 0; + else + m_textquote = mark[0]; + + fillTable(); +} + +void CSVDialog::updateClicked() +{ + if ( !checkUpdateRange() ) + return; + + m_startRow = m_dialog->m_rowStart->value() - 1; + m_endRow = m_dialog->m_rowEnd->value(); + + m_startCol = m_dialog->m_colStart->value() - 1; + m_endCol = m_dialog->m_colEnd->value(); + + fillTable(); +} + +bool CSVDialog::checkUpdateRange() +{ + if ( ( m_dialog->m_rowStart->value() > m_dialog->m_rowEnd->value() ) + || ( m_dialog->m_colStart->value() > m_dialog->m_colEnd->value() ) ) + { + KMessageBox::error( this, i18n( "Please check the ranges you specified. The start value must be lower than the end value." ) ); + return false; + } + + return true; +} + +void CSVDialog::currentCellChanged(int, int col) +{ + const QString header = m_dialog->m_sheet->horizontalHeader()->label(col); + m_dialog->m_formatComboBox->setCurrentText( header ); +} + +void CSVDialog::ignoreDuplicatesChanged(int) +{ + if (m_dialog->m_ignoreDuplicates->isChecked()) + m_ignoreDups = true; + else + m_ignoreDups = false; + fillTable(); +} + +QTextCodec* CSVDialog::getCodec(void) const +{ + const QString strCodec( KGlobal::charsets()->encodingForName( m_dialog->comboBoxEncoding->currentText() ) ); + kdDebug(30502) << "Encoding: " << strCodec << endl; + + bool ok = false; + QTextCodec* codec = QTextCodec::codecForName( strCodec.utf8() ); + + // If QTextCodec has not found a valid encoding, so try with KCharsets. + if ( codec ) + { + ok = true; + } + else + { + codec = KGlobal::charsets()->codecForName( strCodec, ok ); + } + + // Still nothing? + if ( !codec || !ok ) + { + // Default: UTF-8 + kdWarning(30502) << "Cannot find encoding:" << strCodec << endl; + // ### TODO: what parent to use? + KMessageBox::error( 0, i18n("Cannot find encoding: %1").arg( strCodec ) ); + return 0; + } + + return codec; +} + +void CSVDialog::encodingChanged ( const QString & ) +{ + QTextCodec* codec = getCodec(); + + if ( codec ) + { + m_codec = codec; + fillTable(); + } +} + + +#include <csvdialog.moc> diff --git a/filters/kspread/csv/csvdialog.h b/filters/kspread/csv/csvdialog.h new file mode 100644 index 00000000..e73976e6 --- /dev/null +++ b/filters/kspread/csv/csvdialog.h @@ -0,0 +1,89 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <[email protected]> + Copyright (C) 2004 Nicolas GOUTTE <[email protected]> + + 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. +*/ + +#ifndef CSVDIALOG_H +#define CSVDIALOG_H + +#include <qstringlist.h> + +#include <kdialogbase.h> + +class DialogUI; + +class CSVDialog : public KDialogBase +{ + Q_OBJECT +public: + enum Header + { + TEXT, ///< Normal text + NUMBER, ///< Number (either like locale or like C) + DATE, ///< Date \todo What type exactly? + CURRENCY, ///< Currency + COMMANUMBER,///< Number, which decimal symbol is a comma + POINTNUMBER ///< Number, which decimal symbol is a point/dot + }; + + CSVDialog(QWidget* parent, QByteArray& fileArray, const QString seperator); + ~CSVDialog(); + + int getRows(); + int getCols(); + int getHeader(int col); + QString getText(int row, int col); + +private: + void loadSettings(); + void saveSettings(); + void fillTable(); + void fillComboBox(); + void setText(int row, int col, const QString& text); + void adjustRows(int iRows); + void adjustCols(int iCols); + bool checkUpdateRange(); + QTextCodec* getCodec(void) const; + + bool m_adjustRows; + bool m_adjustCols; + int m_startRow; + int m_startCol; + int m_endRow; + int m_endCol; + QChar m_textquote; + QString m_delimiter; + bool m_ignoreDups; + QByteArray m_fileArray; + DialogUI * m_dialog; + QTextCodec* m_codec; + QStringList m_formatList; ///< List of the column formats + +private slots: + void returnPressed(); + void formatChanged( const QString& ); + void delimiterClicked(int id); + void textquoteSelected(const QString& mark); + void currentCellChanged(int, int col); + void textChanged ( const QString & ); + void ignoreDuplicatesChanged( int ); + void updateClicked(); + void encodingChanged ( const QString & ); +}; + +#endif diff --git a/filters/kspread/csv/csvexport.cc b/filters/kspread/csv/csvexport.cc new file mode 100644 index 00000000..c2b99c2b --- /dev/null +++ b/filters/kspread/csv/csvexport.cc @@ -0,0 +1,382 @@ +/* This file is part of the KDE project + Copyright (C) 2000 David Faure <[email protected]> + Copyright (C) 2004 Nicolas GOUTTE <[email protected]> + + 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 <csvexport.h> + +#include <qfile.h> +#include <qtextcodec.h> + +#include <kdebug.h> +#include <kmessagebox.h> +#include <kgenericfactory.h> +#include <KoFilterChain.h> +#include <KoFilterManager.h> + +#include <kspread_map.h> +#include <kspread_sheet.h> +#include <kspread_doc.h> +#include <kspread_view.h> +#include <selection.h> + +#include <csvexportdialog.h> + +using namespace KSpread; + +typedef KGenericFactory<CSVExport, KoFilter> CSVExportFactory; +K_EXPORT_COMPONENT_FACTORY( libcsvexport, CSVExportFactory( "kofficefilters" ) ) + +class Cell +{ + public: + int row, col; + QString text; + + bool operator < ( const Cell & c ) const + { + return row < c.row || ( row == c.row && col < c.col ); + } + bool operator == ( const Cell & c ) const + { + return row == c.row && col == c.col; + } +}; + + +CSVExport::CSVExport( KoFilter *, const char *, const QStringList & ) + : KoFilter(), m_eol("\n") +{ +} + +QString CSVExport::exportCSVCell( Sheet const * const sheet, int col, int row, QChar const & textQuote, QChar csvDelimiter ) +{ + // This function, given a cell, returns a string corresponding to its export in CSV format + // It proceeds by: + // - getting the value of the cell, if any + // - protecting quote characters within cells, if any + // - enclosing the cell in quotes if the cell is non empty + + KSpread::Cell const * const cell = sheet->cellAt( col, row ); + QString text; + + if ( !cell->isDefault() && !cell->isEmpty() ) + { + if ( cell->isFormula() ) + text = cell->strOutText(); + else if ( !cell->link().isEmpty() ) + text = cell->text(); // untested + else if( cell->isTime() ) + text = cell->value().asTime().toString("hh:mm:ss"); + else if( cell->isDate() ) + text = cell->value().asDate().toString("yyyy-MM-dd"); + else + text = cell->strOutText(); + } + + // quote only when needed (try to mimic excel) + bool quote = false; + if ( !text.isEmpty() ) + { + if ( text.find( textQuote ) != -1 ) + { + QString doubleTextQuote(textQuote); + doubleTextQuote.append(textQuote); + text.replace(textQuote, doubleTextQuote); + quote = true; + + } else if ( text[0].isSpace() || text[text.length()-1].isSpace() ) + quote = true; + else if ( text.find( csvDelimiter ) != -1 ) + quote = true; + else if ( text.find( "\n" ) != -1 || text.find( "\r" ) != -1 ) + quote = true; + } + + if ( quote ) { + text.prepend(textQuote); + text.append(textQuote); + } + + return text; +} + +// The reason why we use the KoDocument* approach and not the QDomDocument +// approach is because we don't want to export formulas but values ! +KoFilter::ConversionStatus CSVExport::convert( const QCString & from, const QCString & to ) +{ + kdDebug(30501) << "CSVExport::convert" << endl; + KoDocument* document = m_chain->inputDocument(); + + if ( !document ) + return KoFilter::StupidError; + + if ( !::qt_cast<const KSpread::Doc *>( document ) ) + { + kdWarning(30501) << "document isn't a KSpread::Doc but a " << document->className() << endl; + return KoFilter::NotImplemented; + } + if ( ( to != "text/x-csv" && to != "text/plain" ) || from != "application/x-kspread" ) + { + kdWarning(30501) << "Invalid mimetypes " << to << " " << from << endl; + return KoFilter::NotImplemented; + } + + Doc const * const ksdoc = static_cast<const Doc *>(document); + + if ( ksdoc->mimeType() != "application/x-kspread" ) + { + kdWarning(30501) << "Invalid document mimetype " << ksdoc->mimeType() << endl; + return KoFilter::NotImplemented; + } + + CSVExportDialog *expDialog = 0; + if (!m_chain->manager()->getBatchMode()) + { + expDialog= new CSVExportDialog( 0 ); + + if (!expDialog) + { + kdError(30501) << "Dialog has not been created! Aborting!" << endl; + return KoFilter::StupidError; + } + expDialog->fillSheet( ksdoc->map() ); + + if ( !expDialog->exec() ) + { + delete expDialog; + return KoFilter::UserCancelled; + } + } + + QTextCodec* codec = 0; + QChar csvDelimiter; + if (expDialog) + { + codec = expDialog->getCodec(); + if ( !codec ) + { + delete expDialog; + return KoFilter::StupidError; + } + csvDelimiter = expDialog->getDelimiter(); + m_eol = expDialog->getEndOfLine(); + } + else + { + codec = QTextCodec::codecForName("UTF-8"); + csvDelimiter = ','; + } + + + // Now get hold of the sheet to export + // (Hey, this could be part of the dialog too, choosing which sheet to export.... + // It's great to have parametrable filters... IIRC even MSOffice doesn't have that) + // Ok, for now we'll use the first sheet - my document has only one sheet anyway ;-))) + + bool first = true; + QString str; + QChar textQuote; + if (expDialog) + textQuote = expDialog->getTextQuote(); + else + textQuote = '"'; + + if ( expDialog && expDialog->exportSelectionOnly() ) + { + kdDebug(30501) << "Export as selection mode" << endl; + View const * const view = static_cast<View*>(ksdoc->views().getFirst()); + + if ( !view ) // no view if embedded document + { + delete expDialog; + return KoFilter::StupidError; + } + + Sheet const * const sheet = view->activeSheet(); + + QRect selection = view->selectionInfo()->lastRange(); + // Compute the highest row and column indexes (within the selection) + // containing non-empty cells, respectively called CSVMaxRow CSVMaxCol. + // The CSV will have CSVMaxRow rows, all with CSVMaxCol columns + int right = selection.right(); + int bottom = selection.bottom(); + int CSVMaxRow = 0; + int CSVMaxCol = 0; + + for ( int idxRow = 1, row = selection.top(); row <= bottom; ++row, ++idxRow ) + { + for ( int idxCol = 1, col = selection.left(); col <= right; ++col, ++idxCol ) + { + if( ! sheet->cellAt( col, row )->isEmpty() ) + { + if ( idxRow > CSVMaxRow ) + CSVMaxRow = idxRow; + + if ( idxCol > CSVMaxCol ) + CSVMaxCol = idxCol; + } + } + } + + for ( int idxRow = 1, row = selection.top(); + row <= bottom && idxRow <= CSVMaxRow; ++row, ++idxRow ) + { + int idxCol = 1; + for ( int col = selection.left(); + col <= right && idxCol <= CSVMaxCol; ++col, ++idxCol ) + { + str += exportCSVCell( sheet, col, row, textQuote, csvDelimiter ); + + if ( idxCol < CSVMaxCol ) + str += csvDelimiter; + } + + // This is to deal with the case of non-rectangular selections + for ( ; idxCol < CSVMaxCol; ++idxCol ) + str += csvDelimiter; + + str += m_eol; + } + } + else + { + kdDebug(30501) << "Export as full mode" << endl; + QPtrListIterator<Sheet> it( ksdoc->map()->sheetList() ); + for( ; it.current(); ++it ) + { + Sheet const * const sheet = it.current(); + + if (expDialog && !expDialog->exportSheet( sheet->sheetName() ) ) + { + continue; + } + + // Compute the highest row and column indexes containing non-empty cells, + // respectively called CSVMaxRow CSVMaxCol. + // The CSV will have CSVMaxRow rows, all with CSVMaxCol columns + int sheetMaxRow = sheet->maxRow(); + int sheetMaxCol = sheet->maxColumn(); + int CSVMaxRow = 0; + int CSVMaxCol = 0; + + for ( int row = 1 ; row <= sheetMaxRow ; ++row) + { + for ( int col = 1 ; col <= sheetMaxCol ; col++ ) + { + if( ! sheet->cellAt( col, row )->isEmpty() ) + { + if ( row > CSVMaxRow ) + CSVMaxRow = row; + + if ( col > CSVMaxCol ) + CSVMaxCol = col; + } + } + } + + // Skip the sheet altogether if it is empty + if ( CSVMaxRow + CSVMaxCol == 0) + continue; + + kdDebug(30501) << "Max row x column: " << CSVMaxRow << " x " << CSVMaxCol << endl; + + // Print sheet separators, except for the first sheet + if ( !first || ( expDialog && expDialog->printAlwaysSheetDelimiter() ) ) + { + if ( !first) + str += m_eol; + + QString name; + if (expDialog) + name = expDialog->getSheetDelimiter(); + else + name = "********<SHEETNAME>********"; + const QString tname( i18n("<SHEETNAME>") ); + int pos = name.find( tname ); + if ( pos != -1 ) + { + name.replace( pos, tname.length(), sheet->sheetName() ); + } + str += name; + str += m_eol; + str += m_eol; + } + + first = false; + + + // this is just a bad approximation which fails for documents with less than 50 rows, but + // we don't need any progress stuff there anyway :) (Werner) + int value = 0; + int step = CSVMaxRow > 50 ? CSVMaxRow/50 : 1; + + // Print the CSV for the sheet data + for ( int row = 1, i = 1 ; row <= CSVMaxRow ; ++row, ++i ) + { + if ( i > step ) + { + value += 2; + emit sigProgress(value); + i = 0; + } + + QString collect; // buffer delimiters while reading empty cells + + for ( int col = 1 ; col <= CSVMaxCol ; col++ ) + { + const QString txt = exportCSVCell( sheet, col, row, textQuote, csvDelimiter ); + + // if we encounter a non-empty cell, commit the buffered delimiters + if (!txt.isEmpty()) { + str += collect + txt; + collect = QString(); + } + + collect += csvDelimiter; + } + // Here, throw away buffered delimiters. They're trailing and therefore + // superfluous. + + str += m_eol; + } + } + } + + emit sigProgress(100); + + QFile out(m_chain->outputFile()); + if ( !out.open( IO_WriteOnly ) ) + { + kdError(30501) << "Unable to open output file!" << endl; + out.close(); + delete expDialog; + return KoFilter::StupidError; + } + + QTextStream outStream( &out ); + outStream.setCodec( codec ); + + outStream << str; + + out.close(); + delete expDialog; + return KoFilter::OK; +} + +#include <csvexport.moc> diff --git a/filters/kspread/csv/csvexport.h b/filters/kspread/csv/csvexport.h new file mode 100644 index 00000000..05ce65a0 --- /dev/null +++ b/filters/kspread/csv/csvexport.h @@ -0,0 +1,49 @@ +/* This file is part of the KDE project + Copyright (C) 2000 David Faure <[email protected]> + Copyright (C) 2004 Nicolas GOUTTE <[email protected]> + + 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. +*/ + +#ifndef CSVEXPORT_H +#define CSVEXPORT_H + +#include <qstring.h> +#include <KoFilter.h> + +namespace KSpread +{ +class Sheet; +} + +class CSVExport : public KoFilter +{ + Q_OBJECT + + public: + CSVExport(KoFilter * parent, const char * name, const QStringList &); + virtual ~CSVExport() {} + + virtual KoFilter::ConversionStatus convert( const QCString & from, const QCString & to ); + + private: + QString exportCSVCell( KSpread::Sheet const * const sheet, int col, int row, QChar const & textQuote, QChar delimiter ); + + private: + QString m_eol; ///< End of line (LF, CR or CRLF) +}; + +#endif // CSVEXPORT_H diff --git a/filters/kspread/csv/csvexportdialog.cpp b/filters/kspread/csv/csvexportdialog.cpp new file mode 100644 index 00000000..d095a9af --- /dev/null +++ b/filters/kspread/csv/csvexportdialog.cpp @@ -0,0 +1,332 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <[email protected]> + Copyright (C) 2004 Nicolas GOUTTE <[email protected]> + + 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 <csvexportdialog.h> +#include <exportdialogui.h> + +#include <kspread_map.h> +#include <kspread_sheet.h> + +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qcursor.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qlistview.h> +#include <qptrlist.h> +#include <qradiobutton.h> +#include <qtextstream.h> +#include <qtabwidget.h> +#include <qtextcodec.h> +#include <qvalidator.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <klocale.h> +#include <kdebug.h> +#include <kcombobox.h> +#include <kmessagebox.h> +#include <kcharsets.h> + +using namespace KSpread; + +CSVExportDialog::CSVExportDialog( QWidget * parent ) + : KDialogBase( parent, 0, true, QString::null, Ok | Cancel, No, true ), + m_dialog( new ExportDialogUI( this ) ), + m_delimiter( "," ), + m_textquote('"') +{ + kapp->restoreOverrideCursor(); + + QStringList encodings; + encodings << i18n( "Descriptive encoding name", "Recommended ( %1 )" ).arg( "UTF-8" ); + encodings << i18n( "Descriptive encoding name", "Locale ( %1 )" ).arg( QTextCodec::codecForLocale()->name() ); + encodings += KGlobal::charsets()->descriptiveEncodingNames(); + // Add a few non-standard encodings, which might be useful for text files + const QString description(i18n("Descriptive encoding name","Other ( %1 )")); + encodings << description.arg("Apple Roman"); // Apple + encodings << description.arg("IBM 850") << description.arg("IBM 866"); // MS DOS + encodings << description.arg("CP 1258"); // Windows + + m_dialog->comboBoxEncoding->insertStringList(encodings); + + setButtonBoxOrientation ( Vertical ); + + setMainWidget(m_dialog); + + // Invalid 'Other' delimiters + // - Quotes + // - CR,LF,Vetical-tab,Formfeed,ASCII bel + QRegExp rx( "^[^\"'\r\n\v\f\a]{0,1}$" ); + m_delimiterValidator = new QRegExpValidator( rx, m_dialog->m_delimiterBox ); + m_dialog->m_delimiterEdit->setValidator( m_delimiterValidator ); + + connect( m_dialog->m_delimiterBox, SIGNAL( clicked(int) ), + this, SLOT( delimiterClicked( int ) ) ); + connect( m_dialog->m_delimiterEdit, SIGNAL( returnPressed() ), + this, SLOT( returnPressed() ) ); + connect( m_dialog->m_delimiterEdit, SIGNAL( textChanged ( const QString & ) ), + this, SLOT(textChanged ( const QString & ) ) ); + connect( m_dialog->m_comboQuote, SIGNAL( activated( const QString & ) ), + this, SLOT( textquoteSelected( const QString & ) ) ); + connect( m_dialog->m_selectionOnly, SIGNAL( toggled( bool ) ), + this, SLOT( selectionOnlyChanged( bool ) ) ); + + loadSettings(); +} + +CSVExportDialog::~CSVExportDialog() +{ + saveSettings(); + kapp->setOverrideCursor(Qt::waitCursor); + delete m_delimiterValidator; +} + +void CSVExportDialog::loadSettings() +{ + KConfig *config = kapp->config(); + config->setGroup("CSVDialog Settings"); + m_textquote = config->readEntry("textquote", "\"")[0]; + m_delimiter = config->readEntry("delimiter", ","); + const QString codecText = config->readEntry("codec", ""); + bool selectionOnly = config->readBoolEntry("selectionOnly", false); + const QString sheetDelim = config->readEntry("sheetDelimiter", m_dialog->m_sheetDelimiter->text()); + bool delimAbove = config->readBoolEntry("sheetDelimiterAbove", false); + const QString eol = config->readEntry("eol", "\r\n"); + + // update widgets + if (!codecText.isEmpty()) { + m_dialog->comboBoxEncoding->setCurrentText(codecText); + } + if (m_delimiter == ",") m_dialog->m_radioComma->setChecked(true); + else if (m_delimiter == "\t") m_dialog->m_radioTab->setChecked(true); + else if (m_delimiter == " ") m_dialog->m_radioSpace->setChecked(true); + else if (m_delimiter == ";") m_dialog->m_radioSemicolon->setChecked(true); + else { + m_dialog->m_radioOther->setChecked(true); + m_dialog->m_delimiterEdit->setText(m_delimiter); + } + m_dialog->m_comboQuote->setCurrentItem(m_textquote == '\'' ? 1 + : m_textquote == '"' ? 0 : 2); + m_dialog->m_selectionOnly->setChecked(selectionOnly); + m_dialog->m_sheetDelimiter->setText(sheetDelim); + m_dialog->m_delimiterAboveAll->setChecked(delimAbove); + if (eol == "\r\n") m_dialog->radioEndOfLineCRLF->setChecked(true); + else if (eol == "\r") m_dialog->radioEndOfLineCR->setChecked(true); + else m_dialog->radioEndOfLineLF->setChecked(true); +} + +void CSVExportDialog::saveSettings() +{ + KConfig *config = kapp->config(); + config->setGroup("CSVDialog Settings"); + QString q = m_textquote; + config->writeEntry("textquote", q); + config->writeEntry("delimiter", m_delimiter); + config->writeEntry("codec", m_dialog->comboBoxEncoding->currentText()); + config->writeEntry("selectionOnly", exportSelectionOnly()); + config->writeEntry("sheetDelimiter", getSheetDelimiter()); + config->writeEntry("sheetDelimiterAbove", printAlwaysSheetDelimiter()); + config->writeEntry("eol", getEndOfLine()); + config->sync(); +} + +void CSVExportDialog::fillSheet( Map * map ) +{ + m_dialog->m_sheetList->clear(); + QCheckListItem * item; + + QPtrListIterator<Sheet> it( map->sheetList() ); + for( ; it.current(); ++it ) + { + item = new QCheckListItem( m_dialog->m_sheetList, + it.current()->sheetName(), + QCheckListItem::CheckBox ); + item->setOn(true); + m_dialog->m_sheetList->insertItem( item ); + } + + m_dialog->m_sheetList->setSorting(0, true); + m_dialog->m_sheetList->sort(); + m_dialog->m_sheetList->setSorting( -1 ); +} + +QChar CSVExportDialog::getDelimiter() const +{ + return m_delimiter[0]; +} + +QChar CSVExportDialog::getTextQuote() const +{ + return m_textquote; +} + +bool CSVExportDialog::printAlwaysSheetDelimiter() const +{ + return m_dialog->m_delimiterAboveAll->isChecked(); +} + +QString CSVExportDialog::getSheetDelimiter() const +{ + return m_dialog->m_sheetDelimiter->text(); +} + +bool CSVExportDialog::exportSheet(QString const & sheetName) const +{ + for (QListViewItem * item = m_dialog->m_sheetList->firstChild(); item; item = item->nextSibling()) + { + if (((QCheckListItem * ) item)->isOn()) + { + if ( ((QCheckListItem * ) item)->text() == sheetName ) + return true; + } + } + return false; +} + +void CSVExportDialog::slotOk() +{ + accept(); +} + +void CSVExportDialog::slotCancel() +{ + reject(); +} + +void CSVExportDialog::returnPressed() +{ + if ( m_dialog->m_delimiterBox->id( m_dialog->m_delimiterBox->selected() ) != 4 ) + return; + + m_delimiter = m_dialog->m_delimiterEdit->text(); +} + +void CSVExportDialog::textChanged ( const QString & ) +{ + + if ( m_dialog->m_delimiterEdit->text().isEmpty() ) + { + enableButtonOK( ! m_dialog->m_radioOther->isChecked() ); + return; + } + + m_dialog->m_radioOther->setChecked ( true ); + delimiterClicked(4); +} + +void CSVExportDialog::delimiterClicked( int id ) +{ + enableButtonOK( true ); + + //Erase "Other Delimiter" text box if the user has selected one of + //the standard options instead (comma, semicolon, tab or space) + if (id != 4) + m_dialog->m_delimiterEdit->setText(""); + + switch (id) + { + case 0: // comma + m_delimiter = ","; + break; + case 1: // semicolon + m_delimiter = ";"; + break; + case 2: // tab + m_delimiter = "\t"; + break; + case 3: // space + m_delimiter = " "; + break; + case 4: // other + enableButtonOK( ! m_dialog->m_delimiterEdit->text().isEmpty() ); + m_delimiter = m_dialog->m_delimiterEdit->text(); + break; + } +} + +void CSVExportDialog::textquoteSelected( const QString & mark ) +{ + m_textquote = mark[0]; +} + +void CSVExportDialog::selectionOnlyChanged( bool on ) +{ + m_dialog->m_sheetList->setEnabled( !on ); + m_dialog->m_delimiterLineBox->setEnabled( !on ); + + if ( on ) + m_dialog->m_tabWidget->setCurrentPage( 1 ); +} + +bool CSVExportDialog::exportSelectionOnly() const +{ + return m_dialog->m_selectionOnly->isChecked(); +} + +QTextCodec* CSVExportDialog::getCodec(void) const +{ + const QString strCodec( KGlobal::charsets()->encodingForName( m_dialog->comboBoxEncoding->currentText() ) ); + kdDebug(30502) << "Encoding: " << strCodec << endl; + + bool ok = false; + QTextCodec* codec = QTextCodec::codecForName( strCodec.utf8() ); + + // If QTextCodec has not found a valid encoding, so try with KCharsets. + if ( codec ) + { + ok = true; + } + else + { + codec = KGlobal::charsets()->codecForName( strCodec, ok ); + } + + // Still nothing? + if ( !codec || !ok ) + { + // Default: UTF-8 + kdWarning(30502) << "Cannot find encoding:" << strCodec << endl; + // ### TODO: what parent to use? + KMessageBox::error( 0, i18n("Cannot find encoding: %1").arg( strCodec ) ); + return 0; + } + + return codec; +} + +QString CSVExportDialog::getEndOfLine(void) const +{ + QString strReturn; + if (m_dialog->radioEndOfLineLF==m_dialog->buttonGroupEndOfLine->selected()) + strReturn="\n"; + else if (m_dialog->radioEndOfLineCRLF==m_dialog->buttonGroupEndOfLine->selected()) + strReturn="\r\n"; + else if (m_dialog->radioEndOfLineCR==m_dialog->buttonGroupEndOfLine->selected()) + strReturn="\r"; + else + strReturn="\n"; + + return strReturn; +} + +#include "csvexportdialog.moc" + diff --git a/filters/kspread/csv/csvexportdialog.h b/filters/kspread/csv/csvexportdialog.h new file mode 100644 index 00000000..0ca1f5ba --- /dev/null +++ b/filters/kspread/csv/csvexportdialog.h @@ -0,0 +1,72 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <[email protected]> + Copyright (C) 2004 Nicolas GOUTTE <[email protected]> + + 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. +*/ + +#ifndef CSVEXPORTDIALOG_H +#define CSVEXPORTDIALOG_H + +#include <kdialogbase.h> + +class ExportDialogUI; +class QValidator; + +namespace KSpread +{ +class Map; +} + +class CSVExportDialog : public KDialogBase +{ + Q_OBJECT + public: + CSVExportDialog(QWidget * parent); + ~CSVExportDialog(); + + QChar getDelimiter() const; + QChar getTextQuote() const; + bool exportSheet( QString const & sheetName ) const; + bool printAlwaysSheetDelimiter() const; + QString getSheetDelimiter() const; + bool exportSelectionOnly() const; + + void fillSheet( KSpread::Map * map ); + QString getEndOfLine(void) const; + QTextCodec* getCodec(void) const; + + private: + void loadSettings(); + void saveSettings(); + ExportDialogUI * m_dialog; + + QValidator* m_delimiterValidator; + QString m_delimiter; + QChar m_textquote; + + private slots: + void slotOk(); + void slotCancel(); + + void returnPressed(); + void delimiterClicked( int id ); + void textChanged ( const QString & ); + void textquoteSelected( const QString & mark ); + void selectionOnlyChanged( bool ); +}; + +#endif diff --git a/filters/kspread/csv/csvimport.cc b/filters/kspread/csv/csvimport.cc new file mode 100644 index 00000000..49792406 --- /dev/null +++ b/filters/kspread/csv/csvimport.cc @@ -0,0 +1,264 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <[email protected]> + Copyright (C) 2004 Nicolas GOUTTE <[email protected]> + + 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 <qfile.h> +#include <qregexp.h> + +#include <kapplication.h> +#include <kmessagebox.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 QStringList&) : + KoFilter() { +} + +KoFilter::ConversionStatus CSVFilter::convert( const QCString& from, const QCString& to ) +{ + QString file( m_chain->inputFile() ); + KoDocument* document = m_chain->outputDocument(); + + if ( !document ) + return KoFilter::StupidError; + + kdDebug(30501) << "here we go... " << document->className() << endl; + + if ( !::qt_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; + } + + QFile in(file); + if(!in.open(IO_ReadOnly)) { + KMessageBox::sorry( 0L, i18n("CSV filter cannot open input file - please report.") ); + in.close(); + return KoFilter::FileNotFound; + } + + QString csv_delimiter; + // ###### FIXME: disabled for now + //if (!config.isNull()) + // csv_delimiter = config[0]; + + QByteArray 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); + QApplication::setOverrideCursor(Qt::waitCursor); + + int i; + double init = sheet->nonDefaultColumnFormat( 1 )->dblWidth(); + QMemArray<double> widths( numCols ); + for ( i = 0; i < numCols; ++i ) + widths[i] = init; + + Cell* c = sheet->nonDefaultCell( 1, 1 ); + QFontMetrics 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 QString 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; + QString tmp ( text ); + tmp.remove ( QRegExp( "[^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; + QString tmp ( text ); + tmp.remove ( QRegExp( "[^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 ); + QApplication::restoreOverrideCursor(); + delete dialog; + + return KoFilter::OK; +} + +#include <csvimport.moc> diff --git a/filters/kspread/csv/csvimport.h b/filters/kspread/csv/csvimport.h new file mode 100644 index 00000000..f89f16e6 --- /dev/null +++ b/filters/kspread/csv/csvimport.h @@ -0,0 +1,35 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <[email protected]> + + 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. +*/ + +#ifndef CSVFILTER_H +#define CSVFILTER_H + +#include <KoFilter.h> + +class CSVFilter : public KoFilter { + + Q_OBJECT + +public: + CSVFilter(KoFilter *parent, const char *name, const QStringList&); + virtual ~CSVFilter() {} + + virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to ); +}; +#endif // CSVFILTER_H diff --git a/filters/kspread/csv/dialogui.ui b/filters/kspread/csv/dialogui.ui new file mode 100644 index 00000000..9381676c --- /dev/null +++ b/filters/kspread/csv/dialogui.ui @@ -0,0 +1,554 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>DialogUI</class> +<widget class="QWidget"> + <property name="name"> + <cstring>DialogUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>577</width> + <height>410</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QTable" row="1" column="0"> + <property name="name"> + <cstring>m_sheet</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="numRows"> + <number>0</number> + </property> + <property name="numCols"> + <number>0</number> + </property> + </widget> + <widget class="QTabWidget" row="0" column="0"> + <property name="name"> + <cstring>tabWidget2</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>TabPage</cstring> + </property> + <attribute name="title"> + <string>Encoding</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>E&ncoding:</string> + </property> + <property name="textFormat"> + <enum>PlainText</enum> + </property> + <property name="buddy" stdset="0"> + <cstring>comboBoxEncoding</cstring> + </property> + </widget> + <widget class="KComboBox"> + <property name="name"> + <cstring>comboBoxEncoding</cstring> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>106</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>60</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Common</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QButtonGroup" row="0" column="0" rowspan="2" colspan="1"> + <property name="name"> + <cstring>m_delimiterBox</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Delimiter</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QRadioButton" row="0" column="0"> + <property name="name"> + <cstring>m_radioComma</cstring> + </property> + <property name="text"> + <string>Comma</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton" row="0" column="1"> + <property name="name"> + <cstring>m_radioSemicolon</cstring> + </property> + <property name="text"> + <string>Semicolon</string> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>m_radioTab</cstring> + </property> + <property name="text"> + <string>Tabulator</string> + </property> + </widget> + <widget class="QRadioButton" row="1" column="1"> + <property name="name"> + <cstring>m_radioSpace</cstring> + </property> + <property name="text"> + <string>Space</string> + </property> + </widget> + <widget class="QRadioButton" row="0" column="2"> + <property name="name"> + <cstring>m_radioOther</cstring> + </property> + <property name="text"> + <string>Other</string> + </property> + </widget> + <widget class="QLineEdit" row="1" column="2"> + <property name="name"> + <cstring>m_delimiterEdit</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>30</width> + <height>32767</height> + </size> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>m_ignoreDuplicates</cstring> + </property> + <property name="text"> + <string>Ignore duplicate delimiters</string> + </property> + </widget> + <widget class="QLabel" row="1" column="1"> + <property name="name"> + <cstring>TextLabel2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Text&quote:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_comboQuote</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="text"> + <string>&Format:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_formatComboBox</cstring> + </property> + </widget> + <widget class="KComboBox" row="0" column="2"> + <property name="name"> + <cstring>m_formatComboBox</cstring> + </property> + </widget> + <widget class="QComboBox" row="1" column="2"> + <item> + <property name="text"> + <string>"</string> + </property> + </item> + <item> + <property name="text"> + <string>'</string> + </property> + </item> + <item> + <property name="text"> + <string>None</string> + </property> + </item> + <property name="name"> + <cstring>m_comboQuote</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <spacer row="0" column="3"> + <property name="name"> + <cstring>spacer19</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>51</width> + <height>21</height> + </size> + </property> + </spacer> + <spacer row="1" column="3"> + <property name="name"> + <cstring>spacer20</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>51</width> + <height>21</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Ranges</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QFrame" row="0" column="0"> + <property name="name"> + <cstring>frame3</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QSpinBox" row="0" column="3"> + <property name="name"> + <cstring>m_rowEnd</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>to</string> + </property> + <property name="textFormat"> + <enum>AutoText</enum> + </property> + <property name="alignment"> + <set>WordBreak|AlignCenter</set> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>TextLabel3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="text"> + <string>Import lines:</string> + </property> + </widget> + <widget class="QSpinBox" row="1" column="3"> + <property name="name"> + <cstring>m_colEnd</cstring> + </property> + </widget> + <widget class="QSpinBox" row="1" column="1"> + <property name="name"> + <cstring>m_colStart</cstring> + </property> + <property name="value"> + <number>1</number> + </property> + </widget> + <widget class="QLabel" row="1" column="2"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>to</string> + </property> + <property name="textFormat"> + <enum>AutoText</enum> + </property> + <property name="alignment"> + <set>WordBreak|AlignCenter</set> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>m_rowStart</cstring> + </property> + <property name="value"> + <number>1</number> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>TextLabel3_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="text"> + <string>Import columns:</string> + </property> + </widget> + <spacer row="1" column="4" rowspan="1" colspan="3"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>468</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer row="0" column="4" rowspan="1" colspan="3"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>468</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer row="2" column="0" rowspan="1" colspan="5"> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>611</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer row="2" column="5"> + <property name="name"> + <cstring>spacer8</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>71</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton" row="2" column="6"> + <property name="name"> + <cstring>m_updateButton</cstring> + </property> + <property name="text"> + <string>Update</string> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcombobox.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kcombobox.h</includehint> +</includehints> +</UI> diff --git a/filters/kspread/csv/exportdialogui.ui b/filters/kspread/csv/exportdialogui.ui new file mode 100644 index 00000000..5bb78dea --- /dev/null +++ b/filters/kspread/csv/exportdialogui.ui @@ -0,0 +1,510 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>ExportDialogUI</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ExportDialogUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>520</width> + <height>496</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QTabWidget" row="1" column="0"> + <property name="name"> + <cstring>m_tabWidget</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>encodingPage</cstring> + </property> + <attribute name="title"> + <string>Encoding</string> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>E&ncoding:</string> + </property> + <property name="textFormat"> + <enum>PlainText</enum> + </property> + <property name="buddy" stdset="0"> + <cstring>comboBoxEncoding</cstring> + </property> + </widget> + <widget class="KComboBox"> + <property name="name"> + <cstring>comboBoxEncoding</cstring> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>106</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>buttonGroupEndOfLine</cstring> + </property> + <property name="title"> + <string>End of Line</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioEndOfLineLF</cstring> + </property> + <property name="text"> + <string>&UNIX style (recommended; line feed only)</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioEndOfLineCRLF</cstring> + </property> + <property name="text"> + <string>&Windows style (carriage return and line feed)</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioEndOfLineCR</cstring> + </property> + <property name="text"> + <string>&MacOS style (carriage return only)</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>96</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Sheets</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QListView" row="2" column="0"> + <column> + <property name="text"> + <string>Available Sheets</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_sheetList</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>TextLabel4</cstring> + </property> + <property name="text"> + <string>Select sheets to export:</string> + </property> + </widget> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>m_delimiterLineBox</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Delimiter Line</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLineEdit" row="0" column="0"> + <property name="name"> + <cstring>m_sheetDelimiter</cstring> + </property> + <property name="text"> + <string>********<SHEETNAME>********</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>TextLabel6</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><SHEETNAME> gets replaced by the name of the next sheet.</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>m_delimiterAboveAll</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Print delimiter line above every sheet</string> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab2</cstring> + </property> + <attribute name="title"> + <string>Cells</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QButtonGroup" row="0" column="0"> + <property name="name"> + <cstring>m_delimiterBox</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Delimiter</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QRadioButton" row="0" column="0"> + <property name="name"> + <cstring>m_radioComma</cstring> + </property> + <property name="text"> + <string>Comma</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton" row="0" column="1"> + <property name="name"> + <cstring>m_radioSemicolon</cstring> + </property> + <property name="text"> + <string>Semicolon</string> + </property> + </widget> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>m_radioTab</cstring> + </property> + <property name="text"> + <string>Tabulator</string> + </property> + </widget> + <widget class="QRadioButton" row="1" column="1"> + <property name="name"> + <cstring>m_radioSpace</cstring> + </property> + <property name="text"> + <string>Space</string> + </property> + </widget> + <widget class="QRadioButton" row="0" column="2"> + <property name="name"> + <cstring>m_radioOther</cstring> + </property> + <property name="text"> + <string>Other:</string> + </property> + </widget> + <widget class="QLineEdit" row="1" column="2"> + <property name="name"> + <cstring>m_delimiterEdit</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>30</width> + <height>32767</height> + </size> + </property> + <property name="maxLength"> + <number>1</number> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>GroupBox1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Cells</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>m_quotesLabel</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Quotes:</string> + </property> + </widget> + <widget class="QComboBox" row="1" column="1"> + <item> + <property name="text"> + <string>"</string> + </property> + </item> + <item> + <property name="text"> + <string>'</string> + </property> + </item> + <property name="name"> + <cstring>m_comboQuote</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </grid> + </widget> + <spacer row="2" column="0"> + <property name="name"> + <cstring>Spacer5</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>0</width> + <height>81</height> + </size> + </property> + </spacer> + </grid> + </widget> + </widget> + <widget class="QButtonGroup" row="0" column="0"> + <property name="name"> + <cstring>buttonGroup2</cstring> + </property> + <property name="title"> + <string></string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>m_selectionOnly</cstring> + </property> + <property name="text"> + <string>Export selection only</string> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcombobox.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/filters/kspread/csv/kspread_csv_export.desktop b/filters/kspread/csv/kspread_csv_export.desktop new file mode 100644 index 00000000..c4158234 --- /dev/null +++ b/filters/kspread/csv/kspread_csv_export.desktop @@ -0,0 +1,73 @@ +[Desktop Entry] +Type=Service +Name=CSV Export Filter for KSpread +Name[af]=Cvs Voer uit Filter vir Kspread +Name[az]=KSpread üçün CSV Vermə Süzgəci +Name[bg]=Филтър за експортиране от KSpread в CSV +Name[br]=Sil ezporzh CSV evit KSpread +Name[bs]=CSV Export Filter za KSpread +Name[ca]=Filtre d'exportació CSV per a KSpread +Name[cs]=CSV exportní filtr pro KSpread +Name[cy]=Hidlen Allforio CSV i Kontour +Name[da]=CSV-eksportfilter for KSpread +Name[de]=KSpread CSV-Exportfilter +Name[el]=Φίλτρο εξαγωγής CSV για το KSpread +Name[eo]=CSV-Eksportfiltrilo por KSpread +Name[es]=Filtro de exportación CSV para KSpread +Name[et]=KSpreadi CSV ekspordifilter +Name[eu]=KSpread-en CSV esportaziorako iragazkia +Name[fa]=پالایۀ صادرات CSV برای KSpread +Name[fi]=CSV-vientisuodin KSpeadiin +Name[fo]=CSV-útflyting til KRokni +Name[fr]=Filtre d'exportation CSV de KSpread +Name[fy]=CSV-Eksportfilter foar KSpread +Name[gl]=Filtro de Exportación de CSV para KSpread +Name[he]=מסנן ייצוא מ־KSpread ל־CSV +Name[hi]=के-स्प्रेड के लिए सीएसवी निर्यात छननी +Name[hr]=CSV filtar izvoza za KSpread +Name[hu]=CSV exportszűrő a KSpreadhez +Name[id]=Filter Ekspor CSV untuk K Spread +Name[is]=CSV útflutningssía fyrir KSpread +Name[it]=Filtro di esportazione CSV per KSpread +Name[ja]=KSpread CSV エクスポートフィルタ +Name[km]=តម្រងនាំចេញ CSV សម្រាប់ KSpread +Name[lo]= ຕົວຕອງການສົ່ງອອກ CSV ຂອງກະດາດຄຳນວນ K +Name[lt]=KSpread eksporto filtras CSV +Name[lv]=CSV eksporta filtrs priekš KSpread +Name[mk]=CSV извозен филтер за KSpread +Name[ms]=Penapis Eksport CSV bagi KSpread +Name[mt]=Filtru għall-esportazzjoni ta' files CSV minn ġo KSpread +Name[nb]=CSV-eksportfilter for KSpread +Name[nds]=CSV-Exportfilter för KSpread +Name[ne]=केडीई स्प्रिेडका लागि CSV निर्यात फिल्टर +Name[nl]=CSV-Exportfilter voor KSpread +Name[nn]=CSV-eksportfilter for KSpread +Name[pl]=Filtr eksportu do formatu CSV dla KSpread +Name[pt]=Filtro de Exportação de CSV para o KSpread +Name[pt_BR]=Filtro de exportação CSV para o KSpread +Name[ro]=Filtru de exportare KSpread pentru CSV +Name[ru]=Фильтр экспорта таблиц KSpread в CSV +Name[se]=KSpread:a CSV-olggosfievrridansilli +Name[sk]=CSV filter pre export z KSpread +Name[sl]=Izvozni filter CSV za KSpread +Name[sr]=KSpread-ов филтер за извоз у CSV +Name[sr@Latn]=KSpread-ov filter za izvoz u CSV +Name[sv]=CSV-exportfilter för Kspread +Name[ta]=KSpread க்கான CSV ஏற்றுமதி வடிகட்டி +Name[tg]=CSV Филтри Содирот барои KSpread +Name[th]=ตัวกรองการส่งออก CSV ของกระดาษคำนวณ K +Name[tr]=KSpread CSV Aktarma Filtresi +Name[uk]=Фільтр експорту CSV для KSpread +Name[uz]=KSpread uchun CSV eksport filteri +Name[uz@cyrillic]=KSpread учун CSV экспорт филтери +Name[ven]=Filithara yau bvisela nnda ya CSV yau phadaladza ha K +Name[wa]=Passete CSV di rexhowe po KSpread +Name[xh]=CSV Yesihluzi Sokurhweba ngaphandle se KSpread +Name[zh_CN]=KSpread 的 CSV 导出过滤器 +Name[zh_TW]=KSpread 的 CSV 匯出過濾程式 +Name[zu]=CSV ICSV Export Filter for KSpread +X-KDE-Export=text/x-csv,text/plain +X-KDE-Import=application/x-kspread +X-KDE-Weight=50 +X-KDE-Library=libcsvexport +ServiceTypes=KOfficeFilter diff --git a/filters/kspread/csv/kspread_csv_import.desktop b/filters/kspread/csv/kspread_csv_import.desktop new file mode 100644 index 00000000..0b87e54a --- /dev/null +++ b/filters/kspread/csv/kspread_csv_import.desktop @@ -0,0 +1,72 @@ +[Desktop Entry] +Type=Service +Name=CSV Import Filter for KSpread +Name[af]=Cvs In voer Filter vir Kspread +Name[az]=KSpread üçün CSV Alma Süzgəci +Name[bg]=Филтър за импортиране от CSV в KSpread +Name[br]=Sil enporzh CSV evit KSpread +Name[bs]=CSV Import Filter za KSpread +Name[ca]=Filtre d'importació CSV per a KSpread +Name[cs]=CSV importní filtr pro KSpread +Name[cy]=Hidlen Fewnforio CSV i Kontour +Name[da]=CSV-importfilter for KSpread +Name[de]=KSpread CSV-Importfilter +Name[el]=Φίλτρο εισαγωγής CSV για το KSpread +Name[eo]=CSV-importfiltrilo por KSpread +Name[es]=Filtro de importación CSV para KSpread +Name[et]=KSpreadi CSV impordifilter +Name[eu]=KSpread-en CSV inportaziorako iragazkia +Name[fa]=پالایۀ واردات CSV برای KSpread +Name[fi]=CSV-tuontisuodin KSpeadiin +Name[fr]=Filtre d'importation CSV de KSpread +Name[fy]=CSV-Ymportfilter foar KSpread +Name[ga]=Scagaire Iompórtála CSV le haghaidh KSpread +Name[gl]=Filtro de Importación de CSV para KSpread +Name[he]=מסנן ייבוא מ־CSV ל־KSpread +Name[hi]=के-स्प्रेड के लिए सीएसवी आयात छननी +Name[hr]=CSV filtar uvoza za KSpread +Name[hu]=CSV importszűrő a KSpreadhez +Name[id]=Filter Impor CSV untuk KSpread +Name[is]=CSV innflutningssía fyrir KSpread +Name[it]=Filtro di importazione CSV per KSpread +Name[ja]=KSpread CSV インポートフィルタ +Name[km]=តម្រងនាំចូល CSV សម្រាប់ KSpread +Name[lo]= ຕົວຕອງການນຳເຂົ້າ CSV ຂອງກະດາດຄຳນວນ K +Name[lt]=CSV importo filtras skirtas KSpread +Name[lv]=CSV importa filtrs priekš KSpread +Name[mk]=CSV увозен филтер за KSpread +Name[ms]=Penapis Import CSV bagi KSpread +Name[mt]=Filtru għall-importazzjoni ta' CSV ġo KSpread +Name[nb]=CSV-importfilter for KSpread +Name[nds]=CSV-Importfilter för KSpread +Name[ne]=केडीई स्प्रिेडका लागि CSV आयात फिल्टर +Name[nl]=CSV-Importfilter voor KSpread +Name[nn]=CSV-importfilter for KSpread +Name[pl]=Filtr importu formatu CSV dla KSpread +Name[pt]=Filtro de Importação de CSV para o KSpread +Name[pt_BR]=Filtro de importação CSV para o KSpread +Name[ro]=Filtru de importare KSpread pentru CSV +Name[ru]=Фильтр импорта файлов CSV в KSpread +Name[se]=KSpread:a CSV-sisafievrridansilli +Name[sk]=Filter pre import CVS pre KSpread +Name[sl]=Uvozni filter CSV za KSpread +Name[sr]=KSpread-ов филтер за увоз из CSV-а +Name[sr@Latn]=KSpread-ov filter za uvoz iz CSV-a +Name[sv]=CSV-importfilter för Kspread +Name[ta]=KSpread க்கான CSV இறக்குமதி வடிகட்டி +Name[tg]=CSV Филтри Воридот барои KSpread +Name[th]=ตัวกรองการนำเข้า CSV ของกระดาษคำนวณ K +Name[tr]=KSpread CSV Alma Filtresi +Name[uk]=Фільтр імпорту CSV для KSpread +Name[uz]=KSpread uchun CSV import filteri +Name[uz@cyrillic]=KSpread учун CSV импорт филтери +Name[ven]=Filithara yau u dzhenisa nga ngomu ya CSV ya u phadaladzhwa ha K +Name[wa]=Passete CSV d' intrêye po KSpread +Name[xh]=CSV Yesihluzi Sokurhweba se KSpread +Name[zh_CN]=KSpread 的 CSV 导入过滤器 +Name[zh_TW]=KSpread 的 CSV 匯入過濾程式 +X-KDE-Export=application/x-kspread +X-KDE-Import=text/x-csv,text/plain +X-KDE-Weight=50 +X-KDE-Library=libcsvimport +ServiceTypes=KOfficeFilter diff --git a/filters/kspread/csv/status.html b/filters/kspread/csv/status.html new file mode 100644 index 00000000..c4379ade --- /dev/null +++ b/filters/kspread/csv/status.html @@ -0,0 +1,202 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <title>KOffice filters status: CSV FILTER</title> +</head> +<body text="#000000" bgcolor="#FFFFFF" link="#000099" vlink="#666666" alink="#666666"> +<A NAME="START"> </A> + +<BR> +<center> + <h1> + KOffice filters status: <i>CSV - Comma Separated Values</i> + </h1> +</center> + +<hr NOSHADE SIZE=2 WIDTH="70%"> + +<font size="-1"><b> + <A HREF="#import">Import</A> | + <A HREF="#export">Export</A> +</b></font> + +<BR><BR><BR> +<center><a NAME="import"></a></center> + +<A HREF="#START"><font size="-1"><b>Up</b></font></A> +<center> +<table BORDER=0 CELLSPACING=0 BGCOLOR="#000000" WIDTH="100%"> + <tr> + <td> + <table BORDER=0 CELLPADDING=2 BGCOLOR="#FFFFFF" WIDTH="100%"> + + <tr BGCOLOR="#DDFFDD"> + <td COLSPAN="2"> + <center><b><i><font size="+1"> + <BR> + Import CSV for KSpread<BR> + <BR> + </font></i></b></center> + </td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP WIDTH="1%" NOWRAP><b><font size="+1">Last update</font></b></td> + <td>9 jan 2001</td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">Features</font></b></td> + <td>- Can import CVS documents</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Todo</font></b></td> + <td> + - Automatically adjust the columns width to their contents.<BR> + Will be difficult, as we don't know the font used...<BR> + Solution ? Set a default font _in_ the filter, and use it to <BR> + compute the width... + </td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">History</font></b></td> + <td>-</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Authors</font></b></td> + <td> + <A HREF="mailto:[email protected]">David Faure</A> + <A HREF="mailto:[email protected]">Werner Trobin</A> + </td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">Links</font></b></td> + <td>-</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Progress report </font></b></td> + <td> + <H2>Design</H2> +<PRE> +The CSV import filter uses a hand-made state machine to parse the CSV file. +This allows to handle quoted fields (such as those containing the CSV delimiter), +as well as the double-quote character itself (which then appears twice, and +always in a quoted field). +Just to make sure about the vocabulary, I call a quoted field a field +starting with " and finishing with ". + +Let's try to draw the graph of the state machine using ascii-art. + + + DEL or EOL + /--\ + | | + | v " + /--[START]-------->[QUOTED_FIELD] (**) + other| ^ ^ | ^ + (*) | | | DEL or | " | " (*) + | | | EOL v | other + | | \----[MAYBE_END_OF_QUOTED_FIELD]--------> Error + | | + | | DEL or + | | EOL + v | + [NORMAL_FIELD] (**) + +DEL : CSV delimiter (depends on locale !). Often comma, sometimes semicolon. +EOL : End Of Line. +(*) : added to the current field +(**) : implicit loop on itself, labeled "other (*)" + + +Ugly isn't it ? :) One can't be good in drawings AND in hacking :) + +That's all. For the rest, see csvfilter.cc + +David Faure <[email protected]>, 1999 +</PRE> + </td> + </tr> + </table> + </td> + </tr> +</table> +</center> +<A HREF="#START"><font size="-1"><b>Up</b></font></A> + +<br><br><br> + +<hr NOSHADE SIZE=1> +<br><br><br> + + +<center> + <a NAME="export"></a> +</center> + +<A HREF="#START"><font size="-1"><b>Up</b></font></A> +<center> +<table BORDER=0 CELLSPACING=0 BGCOLOR="#000000" WIDTH="100%"> + <tr> + <td> + <table BORDER=0 CELLPADDING=2 BGCOLOR="#FFFFFF" WIDTH="100%"> + <tr BGCOLOR="#FFDDDD"> + <td COLSPAN="2"> + <center><b><i><font size="+1"> + <BR>Export KSpread to CSV<BR><BR> + </font></i></b></center> + </td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP WIDTH="1%" NOWRAP><b><font size="+1">Last update</font></b></td> + <td>?</td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">Features</font></b></td> + <td>?</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Todo</font></b></td> + <td>?</td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">History</font></b></td> + <td>-</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Authors</font></b></td> + <td> + <A HREF="mailto:[email protected]">David Faure</A> + <A HREF="mailto:[email protected]">Werner Trobin</A> + </td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">Links</font></b></td> + <td>-</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Progress report </font></b></td> + <td>---</td> + </tr> + </table> + </td> + </tr> +</table> +</center> +<A HREF="#START"><font size="-1"><b>Up</b></font></A> + +</body> +</html> diff --git a/filters/kspread/csv/xmltree.cc b/filters/kspread/csv/xmltree.cc new file mode 100644 index 00000000..e6fdf124 --- /dev/null +++ b/filters/kspread/csv/xmltree.cc @@ -0,0 +1,154 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <[email protected]> + + 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 <xmltree.h> + +#include <qdatetime.h> +#include <kdebug.h> + + +XMLTree::XMLTree(QDomDocument &qdoc) : root(qdoc) +{ + root=QDomDocument("spreadsheet"); + root.appendChild( root.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) ); + doc = root.createElement( "spreadsheet" ); + + doc.setAttribute("editor", "KSpread CSV Filter"); + doc.setAttribute("mime", "application/x-kspread"); + root.appendChild(doc); + + QDomElement paper = root.createElement("paper"); + paper.setAttribute("format", "A4"); + paper.setAttribute("orientation", "Portrait"); + QDomElement borders = root.createElement( "borders" ); + borders.setAttribute( "left", 20 ); + borders.setAttribute( "top", 20 ); + borders.setAttribute( "right", 20 ); + borders.setAttribute( "bottom", 20 ); + paper.appendChild( borders ); + doc.appendChild(paper); + + map = root.createElement("map"); + doc.appendChild(map); + + sheet = root.createElement("table"); + + sheet.setAttribute("name", "foobar"); + map.appendChild(sheet); + + row = 1; + column = 1; +} + +XMLTree::~XMLTree() +{ + //if(root) // We're using fancy references, now! (Werner) + //delete root; +} + +// Not needed anymore (Werner) +//const QString XMLTree::part() +//{ +// QString s; +// QTextStream t(s, IO_WriteOnly); + +// QTime tmr; +// tmr.start(); +// kdDebug(30501) << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" << endl; + +// root.save(t); // Why does this take sooooo long (approx. 8s on my Athlon 500 with a + // quite small file :( ) + +// David: gdb says that QString::replace calls itself recursively an enormous amount of time +// This is called by QStringBuffer::writeBlock (), called by QTextStream::writeBlock () +// called by QTextStream::operator<< () in QDOM_AttrPrivate::save (). +// +// And this looks related to the UTF 8 encoding ... + +// kdDebug(30501) << (const char*)QString::number((int)tmr.elapsed()) << endl; +// kdDebug(30501) << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" << endl; + +// t << '\0'; + +// return s; +//} + +bool XMLTree::cell( const QString & contents ) +{ + QDomElement e = root.createElement("cell"); + //e.appendChild(getFormat(xf)); + //e.appendChild(getFont(xf)); + + e.setAttribute("row", row); + e.setAttribute("column", column++); + + QDomElement format=root.createElement("format"); + format.setAttribute("float", "3"); + format.setAttribute("alignY", "2"); + format.setAttribute("floatcolor", "2"); + format.setAttribute("faktor", "1"); + format.setAttribute("precision", "-1"); + format.setAttribute("align", "4"); + + QDomElement pen=root.createElement("pen"); + pen.setAttribute("width", "1"); + pen.setAttribute("style", "0"); + pen.setAttribute("color", "#000000"); + + QDomElement lborder=root.createElement("left-border"); + lborder.appendChild(pen); + format.appendChild(lborder); + + pen=root.createElement("pen"); + pen.setAttribute("width", "1"); + pen.setAttribute("style", "0"); + pen.setAttribute("color", "#000000"); + + QDomElement tborder=root.createElement("top-border"); + tborder.appendChild(pen); + format.appendChild(tborder); + + pen=root.createElement("pen"); + pen.setAttribute("width", "1"); + pen.setAttribute("style", "0"); + pen.setAttribute("color", "#000000"); + + QDomElement fdia=root.createElement("fall-diagonal"); + fdia.appendChild(pen); + format.appendChild(fdia); + + pen=root.createElement("pen"); + pen.setAttribute("width", "1"); + pen.setAttribute("style", "0"); + pen.setAttribute("color", "#000000"); + + QDomElement udia=root.createElement("up-diagonal"); + udia.appendChild(pen); + format.appendChild(udia); + + e.appendChild(format); + + QDomElement text=root.createElement("text"); + text.appendChild(root.createTextNode(contents)); + e.appendChild(text); + + sheet.appendChild(e); + + return true; +} diff --git a/filters/kspread/csv/xmltree.h b/filters/kspread/csv/xmltree.h new file mode 100644 index 00000000..919acc8f --- /dev/null +++ b/filters/kspread/csv/xmltree.h @@ -0,0 +1,53 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <[email protected]> + + 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. +*/ + +#ifndef XMLTREE_H +#define XMLTREE_H + +#include <qdom.h> +#include <qmemarray.h> +#include <qtextstream.h> + +class XMLTree +{ + +public: + // Create a tree. + // inputFileName is only used in order to name the sheet + XMLTree(QDomDocument &qdoc); + ~XMLTree(); + + // Return the whole XML as QString + //const QString part(); + + // Create a new cell + bool cell( const QString & contents ); + + // Tell about an empty cell (doesn't create it, just skips) + void emptycell() { column ++; } // easy heh ? ;) + + // Go to new line + void newline() { row ++; column = 1; } + +private: + int row, column; + QDomDocument &root; + QDomElement doc, map, sheet; +}; +#endif // XMLTREE_H |