|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2002-2003 Norbert Andres <nandres@web.de>
|
|
|
|
(C) 2002-2003 Ariya Hidayat <ariya@kde.org>
|
|
|
|
(C) 2002 Laurent Montel <montel@kde.org>
|
|
|
|
(C) 1999 David Faure <faure@kde.org>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <tqbuttongroup.h>
|
|
|
|
#include <tqcheckbox.h>
|
|
|
|
#include <tqclipboard.h>
|
|
|
|
#include <tqcombobox.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqlineedit.h>
|
|
|
|
#include <tqmime.h>
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
#include <tqradiobutton.h>
|
|
|
|
#include <tqtable.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kdialogbase.h>
|
|
|
|
#include <kfiledialog.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
|
|
|
|
#include <kspread_cell.h>
|
|
|
|
#include <kspread_doc.h>
|
|
|
|
#include <kspread_sheet.h>
|
|
|
|
#include <kspread_undo.h>
|
|
|
|
#include <kspread_view.h>
|
|
|
|
|
|
|
|
#include "kspread_dlg_csv.h"
|
|
|
|
|
|
|
|
using namespace KSpread;
|
|
|
|
|
|
|
|
CSVDialog::CSVDialog( View * tqparent, const char * name, TQRect const & rect, Mode mode)
|
|
|
|
: KDialogBase( tqparent, name, true, TQString(), Ok|Cancel ),
|
|
|
|
m_pView( tqparent ),
|
|
|
|
m_cancelled( false ),
|
|
|
|
m_adjustRows( 0 ),
|
|
|
|
m_startline( 0 ),
|
|
|
|
m_textquote( '"' ),
|
|
|
|
m_delimiter( "," ),
|
|
|
|
m_targetRect( rect ),
|
|
|
|
m_mode( mode )
|
|
|
|
{
|
|
|
|
if ( !name )
|
|
|
|
setName( "CSV" );
|
|
|
|
|
|
|
|
setSizeGripEnabled( TRUE );
|
|
|
|
|
|
|
|
TQWidget* page = new TQWidget( this );
|
|
|
|
setMainWidget( page );
|
|
|
|
// MyDialogLayout = new TQGridLayout( page, 4, 4, marginHint(), spacingHint(), "MyDialogLayout");
|
|
|
|
MyDialogLayout = new TQGridLayout( page, 1, 1, 11, 6, "MyDialogLayout");
|
|
|
|
|
|
|
|
// Limit the range
|
|
|
|
int column = m_targetRect.left();
|
|
|
|
Cell* lastCell = m_pView->activeSheet()->getLastCellColumn( column );
|
|
|
|
if( lastCell )
|
|
|
|
if( m_targetRect.bottom() > lastCell->row() )
|
|
|
|
m_targetRect.setBottom( lastCell->row() );
|
|
|
|
|
|
|
|
m_sheet = new TQTable( page, "m_table" );
|
|
|
|
//m_sheet->tqsetSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)5, (TQSizePolicy::SizeType)7, 0, 0, m_sheet->sizePolicy().hasHeightForWidth() ) );
|
|
|
|
m_sheet->setNumRows( 0 );
|
|
|
|
m_sheet->setNumCols( 0 );
|
|
|
|
|
|
|
|
MyDialogLayout->addMultiCellWidget( m_sheet, 3, 3, 0, 3 );
|
|
|
|
|
|
|
|
// Delimiter: comma, semicolon, tab, space, other
|
|
|
|
m_delimiterBox = new TQButtonGroup( page, "m_delimiterBox" );
|
|
|
|
m_delimiterBox->tqsetSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)1, 0, 0, m_delimiterBox->sizePolicy().hasHeightForWidth() ) );
|
|
|
|
m_delimiterBox->setTitle( i18n( "Delimiter" ) );
|
|
|
|
m_delimiterBox->setColumnLayout(0, Qt::Vertical );
|
|
|
|
m_delimiterBox->tqlayout()->setSpacing( KDialog::spacingHint() );
|
|
|
|
m_delimiterBox->tqlayout()->setMargin( KDialog::marginHint() );
|
|
|
|
m_delimiterBoxLayout = new TQGridLayout( m_delimiterBox->tqlayout() );
|
|
|
|
m_delimiterBoxLayout->tqsetAlignment( TQt::AlignTop );
|
|
|
|
MyDialogLayout->addMultiCellWidget( m_delimiterBox, 0, 2, 0, 0 );
|
|
|
|
|
|
|
|
m_ignoreDuplicates = new TQCheckBox( page, "m_ignoreDuplicates" );
|
|
|
|
m_ignoreDuplicates->setText( i18n( "Ignore duplicate delimiters" ) );
|
|
|
|
|
|
|
|
MyDialogLayout->addMultiCellWidget( m_ignoreDuplicates, 2, 2, 2, 3 );
|
|
|
|
|
|
|
|
m_radioComma = new TQRadioButton( m_delimiterBox, "m_radioComma" );
|
|
|
|
m_radioComma->setText( i18n( "Comma" ) );
|
|
|
|
m_radioComma->setChecked( TRUE );
|
|
|
|
m_delimiterBoxLayout->addWidget( m_radioComma, 0, 0 );
|
|
|
|
|
|
|
|
m_radioSemicolon = new TQRadioButton( m_delimiterBox, "m_radioSemicolon" );
|
|
|
|
m_radioSemicolon->setText( i18n( "Semicolon" ) );
|
|
|
|
m_delimiterBoxLayout->addWidget( m_radioSemicolon, 0, 1 );
|
|
|
|
|
|
|
|
m_radioTab = new TQRadioButton( m_delimiterBox, "m_radioTab" );
|
|
|
|
m_radioTab->setText( i18n( "Tabulator" ) );
|
|
|
|
m_delimiterBoxLayout->addWidget( m_radioTab, 1, 0 );
|
|
|
|
|
|
|
|
m_radioSpace = new TQRadioButton( m_delimiterBox, "m_radioSpace" );
|
|
|
|
m_radioSpace->setText( i18n( "Space" ) );
|
|
|
|
m_delimiterBoxLayout->addWidget( m_radioSpace, 1, 1 );
|
|
|
|
|
|
|
|
m_radioOther = new TQRadioButton( m_delimiterBox, "m_radioOther" );
|
|
|
|
m_radioOther->setText( i18n( "Other" ) );
|
|
|
|
m_delimiterBoxLayout->addWidget( m_radioOther, 0, 2 );
|
|
|
|
|
|
|
|
m_delimiterEdit = new TQLineEdit( m_delimiterBox, "m_delimiterEdit" );
|
|
|
|
m_delimiterEdit->tqsetSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0, 0, 0, m_delimiterEdit->sizePolicy().hasHeightForWidth() ) );
|
|
|
|
m_delimiterEdit->setMaximumSize( TQSize( 30, 32767 ) );
|
|
|
|
m_delimiterBoxLayout->addWidget( m_delimiterEdit, 1, 2 );
|
|
|
|
|
|
|
|
|
|
|
|
// Format: number, text, currency,
|
|
|
|
m_formatBox = new TQButtonGroup( page, "m_formatBox" );
|
|
|
|
m_formatBox->tqsetSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)1, 0, 0, m_formatBox->sizePolicy().hasHeightForWidth() ) );
|
|
|
|
m_formatBox->setTitle( i18n( "Format" ) );
|
|
|
|
m_formatBox->setColumnLayout(0, Qt::Vertical );
|
|
|
|
m_formatBox->tqlayout()->setSpacing( KDialog::spacingHint() );
|
|
|
|
m_formatBox->tqlayout()->setMargin( KDialog::marginHint() );
|
|
|
|
m_formatBoxLayout = new TQGridLayout( m_formatBox->tqlayout() );
|
|
|
|
m_formatBoxLayout->tqsetAlignment( TQt::AlignTop );
|
|
|
|
MyDialogLayout->addMultiCellWidget( m_formatBox, 0, 2, 1, 1 );
|
|
|
|
|
|
|
|
m_radioNumber = new TQRadioButton( m_formatBox, "m_radioNumber" );
|
|
|
|
m_radioNumber->setText( i18n( "Number" ) );
|
|
|
|
m_formatBoxLayout->addMultiCellWidget( m_radioNumber, 1, 1, 0, 1 );
|
|
|
|
|
|
|
|
m_radioText = new TQRadioButton( m_formatBox, "m_radioText" );
|
|
|
|
m_radioText->setText( i18n( "Text" ) );
|
|
|
|
m_radioText->setChecked( TRUE );
|
|
|
|
m_formatBoxLayout->addWidget( m_radioText, 0, 0 );
|
|
|
|
|
|
|
|
m_radioCurrency = new TQRadioButton( m_formatBox, "m_radioCurrency" );
|
|
|
|
m_radioCurrency->setText( i18n( "Currency" ) );
|
|
|
|
m_formatBoxLayout->addMultiCellWidget( m_radioCurrency, 0, 0, 1, 2 );
|
|
|
|
|
|
|
|
m_radioDate = new TQRadioButton( m_formatBox, "m_radioDate" );
|
|
|
|
m_radioDate->setText( i18n( "Date" ) );
|
|
|
|
m_formatBoxLayout->addWidget( m_radioDate, 1, 2 );
|
|
|
|
|
|
|
|
m_comboLine = new TQComboBox( FALSE, page, "m_comboLine" );
|
|
|
|
m_comboLine->insertItem( i18n( "1" ) );
|
|
|
|
m_comboLine->tqsetSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, m_comboLine->sizePolicy().hasHeightForWidth() ) );
|
|
|
|
|
|
|
|
MyDialogLayout->addWidget( m_comboLine, 1, 3 );
|
|
|
|
|
|
|
|
m_comboQuote = new TQComboBox( FALSE, page, "m_comboQuote" );
|
|
|
|
m_comboQuote->insertItem( i18n( "\"" ) );
|
|
|
|
m_comboQuote->insertItem( i18n( "'" ) );
|
|
|
|
m_comboQuote->insertItem( i18n( "None" ) );
|
|
|
|
m_comboQuote->tqsetSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, m_comboQuote->sizePolicy().hasHeightForWidth() ) );
|
|
|
|
|
|
|
|
MyDialogLayout->addWidget( m_comboQuote, 1, 2 );
|
|
|
|
TQSpacerItem* spacer_2 = new TQSpacerItem( 0, 0, TQSizePolicy::Minimum, TQSizePolicy::Preferred );
|
|
|
|
MyDialogLayout->addItem( spacer_2, 2, 3 );
|
|
|
|
|
|
|
|
TextLabel3 = new TQLabel( page, "TextLabel3" );
|
|
|
|
TextLabel3->tqsetSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, TextLabel3->sizePolicy().hasHeightForWidth() ) );
|
|
|
|
TextLabel3->setText( i18n( "Start at line:" ) );
|
|
|
|
|
|
|
|
MyDialogLayout->addWidget( TextLabel3, 0, 3 );
|
|
|
|
|
|
|
|
TextLabel2 = new TQLabel( page, "TextLabel2" );
|
|
|
|
TextLabel2->tqsetSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)1, (TQSizePolicy::SizeType)0, 0, 0, TextLabel2->sizePolicy().hasHeightForWidth() ) );
|
|
|
|
TextLabel2->setText( i18n( "Textquote:" ) );
|
|
|
|
|
|
|
|
MyDialogLayout->addWidget( TextLabel2, 0, 2 );
|
|
|
|
|
|
|
|
if ( m_mode == Clipboard )
|
|
|
|
{
|
|
|
|
setCaption( i18n( "Inserting From Clipboard" ) );
|
|
|
|
TQMimeSource * mime = TQApplication::tqclipboard()->data();
|
|
|
|
if ( !mime )
|
|
|
|
{
|
|
|
|
KMessageBox::information( this, i18n("There is no data in the clipboard.") );
|
|
|
|
m_cancelled = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !mime->provides( "text/plain" ) )
|
|
|
|
{
|
|
|
|
KMessageBox::information( this, i18n("There is no usable data in the clipboard.") );
|
|
|
|
m_cancelled = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_fileArray = TQByteArray(mime->tqencodedData( "text/plain" ) );
|
|
|
|
}
|
|
|
|
else if ( mode == File )
|
|
|
|
{
|
|
|
|
setCaption( i18n( "Inserting Text File" ) );
|
|
|
|
TQString file = KFileDialog::getOpenFileName(":",
|
|
|
|
"text/plain",
|
|
|
|
this);
|
|
|
|
//cancel action !
|
|
|
|
if ( file.isEmpty() )
|
|
|
|
{
|
|
|
|
actionButton( Ok )->setEnabled( false );
|
|
|
|
m_cancelled = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
TQFile in(file);
|
|
|
|
if (!in.open(IO_ReadOnly))
|
|
|
|
{
|
|
|
|
KMessageBox::sorry( this, i18n("Cannot open input file.") );
|
|
|
|
in.close();
|
|
|
|
actionButton( Ok )->setEnabled( false );
|
|
|
|
m_cancelled = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_fileArray = TQByteArray(in.size());
|
|
|
|
in.readBlock(m_fileArray.data(), in.size());
|
|
|
|
in.close();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setCaption( i18n( "Text to Columns" ) );
|
|
|
|
m_data = "";
|
|
|
|
Cell * cell;
|
|
|
|
Sheet * sheet = m_pView->activeSheet();
|
|
|
|
int col = m_targetRect.left();
|
|
|
|
for (int i = m_targetRect.top(); i <= m_targetRect.bottom(); ++i)
|
|
|
|
{
|
|
|
|
cell = sheet->cellAt( col, i );
|
|
|
|
if ( !cell->isEmpty() && !cell->isDefault() )
|
|
|
|
{
|
|
|
|
m_data += cell->strOutText();
|
|
|
|
}
|
|
|
|
m_data += "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fillSheet();
|
|
|
|
fillComboBox();
|
|
|
|
|
|
|
|
resize(tqsizeHint());
|
|
|
|
|
|
|
|
m_sheet->setSelectionMode(TQTable::NoSelection);
|
|
|
|
|
|
|
|
connect(m_formatBox, TQT_SIGNAL(clicked(int)),
|
|
|
|
this, TQT_SLOT(formatClicked(int)));
|
|
|
|
connect(m_delimiterBox, TQT_SIGNAL(clicked(int)),
|
|
|
|
this, TQT_SLOT(delimiterClicked(int)));
|
|
|
|
connect(m_delimiterEdit, TQT_SIGNAL(returnPressed()),
|
|
|
|
this, TQT_SLOT(returnPressed()));
|
|
|
|
connect(m_delimiterEdit, TQT_SIGNAL(textChanged ( const TQString & )),
|
|
|
|
this, TQT_SLOT(textChanged ( const TQString & ) ));
|
|
|
|
connect(m_comboLine, TQT_SIGNAL(activated(const TQString&)),
|
|
|
|
this, TQT_SLOT(lineSelected(const TQString&)));
|
|
|
|
connect(m_comboQuote, TQT_SIGNAL(activated(const TQString&)),
|
|
|
|
this, TQT_SLOT(textquoteSelected(const TQString&)));
|
|
|
|
connect(m_sheet, TQT_SIGNAL(currentChanged(int, int)),
|
|
|
|
this, TQT_SLOT(currentCellChanged(int, int)));
|
|
|
|
connect(m_ignoreDuplicates, TQT_SIGNAL(stateChanged(int)),
|
|
|
|
this, TQT_SLOT(ignoreDuplicatesChanged(int)));
|
|
|
|
}
|
|
|
|
|
|
|
|
CSVDialog::~CSVDialog()
|
|
|
|
{
|
|
|
|
// no need to delete child widgets, TQt does it all for us
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CSVDialog::cancelled()
|
|
|
|
{
|
|
|
|
return m_cancelled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::fillSheet()
|
|
|
|
{
|
|
|
|
int row, column;
|
|
|
|
bool lastCharDelimiter = false;
|
|
|
|
bool ignoreDups = m_ignoreDuplicates->isChecked();
|
|
|
|
enum { S_START, S_TQUOTED_FIELD, S_MAYBE_END_OF_TQUOTED_FIELD, S_END_OF_TQUOTED_FIELD,
|
|
|
|
S_MAYBE_NORMAL_FIELD, S_NORMAL_FIELD } state = S_START;
|
|
|
|
|
|
|
|
TQChar x;
|
|
|
|
TQString field = "";
|
|
|
|
|
|
|
|
for (row = 0; row < m_sheet->numRows(); ++row)
|
|
|
|
for (column = 0; column < m_sheet->numCols(); ++column)
|
|
|
|
m_sheet->clearCell(row, column);
|
|
|
|
|
|
|
|
row = column = 1;
|
|
|
|
if (m_mode != Column)
|
|
|
|
{
|
|
|
|
m_mode = Column;
|
|
|
|
m_data = TQString(m_fileArray);
|
|
|
|
m_fileArray.resize(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQTextStream inputStream(m_data, IO_ReadOnly);
|
|
|
|
inputStream.setEncoding(TQTextStream::Locale);
|
|
|
|
|
|
|
|
while (!inputStream.atEnd())
|
|
|
|
{
|
|
|
|
inputStream >> x; // read one char
|
|
|
|
|
|
|
|
if (x == '\r') inputStream >> x; // eat '\r', to handle DOS/LOSEDOWS files correctly
|
|
|
|
|
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case S_START :
|
|
|
|
if (x == m_textquote)
|
|
|
|
{
|
|
|
|
state = S_TQUOTED_FIELD;
|
|
|
|
}
|
|
|
|
else if (x == m_delimiter)
|
|
|
|
{
|
|
|
|
if ((ignoreDups == false) || (lastCharDelimiter == false))
|
|
|
|
++column;
|
|
|
|
lastCharDelimiter = true;
|
|
|
|
}
|
|
|
|
else if (x == '\n')
|
|
|
|
{
|
|
|
|
++row;
|
|
|
|
column = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
field += x;
|
|
|
|
state = S_MAYBE_NORMAL_FIELD;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case S_TQUOTED_FIELD :
|
|
|
|
if (x == m_textquote)
|
|
|
|
{
|
|
|
|
state = S_MAYBE_END_OF_TQUOTED_FIELD;
|
|
|
|
}
|
|
|
|
else if (x == '\n')
|
|
|
|
{
|
|
|
|
setText(row - m_startline, column, field);
|
|
|
|
field = "";
|
|
|
|
if (x == '\n')
|
|
|
|
{
|
|
|
|
++row;
|
|
|
|
column = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((ignoreDups == false) || (lastCharDelimiter == false))
|
|
|
|
++column;
|
|
|
|
lastCharDelimiter = true;
|
|
|
|
}
|
|
|
|
state = S_START;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
field += x;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case S_MAYBE_END_OF_TQUOTED_FIELD :
|
|
|
|
if (x == m_textquote)
|
|
|
|
{
|
|
|
|
field += x;
|
|
|
|
state = S_TQUOTED_FIELD;
|
|
|
|
}
|
|
|
|
else if (x == m_delimiter || x == '\n')
|
|
|
|
{
|
|
|
|
setText(row - m_startline, column, field);
|
|
|
|
field = "";
|
|
|
|
if (x == '\n')
|
|
|
|
{
|
|
|
|
++row;
|
|
|
|
column = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((ignoreDups == false) || (lastCharDelimiter == false))
|
|
|
|
++column;
|
|
|
|
lastCharDelimiter = true;
|
|
|
|
}
|
|
|
|
state = S_START;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
state = S_END_OF_TQUOTED_FIELD;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case S_END_OF_TQUOTED_FIELD :
|
|
|
|
if (x == m_delimiter || x == '\n')
|
|
|
|
{
|
|
|
|
setText(row - m_startline, column, field);
|
|
|
|
field = "";
|
|
|
|
if (x == '\n')
|
|
|
|
{
|
|
|
|
++row;
|
|
|
|
column = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((ignoreDups == false) || (lastCharDelimiter == false))
|
|
|
|
++column;
|
|
|
|
lastCharDelimiter = true;
|
|
|
|
}
|
|
|
|
state = S_START;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
state = S_END_OF_TQUOTED_FIELD;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case S_MAYBE_NORMAL_FIELD :
|
|
|
|
if (x == m_textquote)
|
|
|
|
{
|
|
|
|
field = "";
|
|
|
|
state = S_TQUOTED_FIELD;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case S_NORMAL_FIELD :
|
|
|
|
if (x == m_delimiter || x == '\n')
|
|
|
|
{
|
|
|
|
setText(row - m_startline, column, field);
|
|
|
|
field = "";
|
|
|
|
if (x == '\n')
|
|
|
|
{
|
|
|
|
++row;
|
|
|
|
column = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((ignoreDups == false) || (lastCharDelimiter == false))
|
|
|
|
++column;
|
|
|
|
lastCharDelimiter = true;
|
|
|
|
}
|
|
|
|
state = S_START;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
field += x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (x != m_delimiter)
|
|
|
|
lastCharDelimiter = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// file with only one line without '\n'
|
|
|
|
if (field.length() > 0)
|
|
|
|
{
|
|
|
|
setText(row - m_startline, column, field);
|
|
|
|
++row;
|
|
|
|
field = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
adjustRows( row - m_startline );
|
|
|
|
|
|
|
|
for (column = 0; column < m_sheet->numCols(); ++column)
|
|
|
|
{
|
|
|
|
TQString header = m_sheet->horizontalHeader()->label(column);
|
|
|
|
if (header != i18n("Text") && header != i18n("Number") &&
|
|
|
|
header != i18n("Date") && header != i18n("Currency"))
|
|
|
|
m_sheet->horizontalHeader()->setLabel(column, i18n("Text"));
|
|
|
|
|
|
|
|
m_sheet->adjustColumn(column);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::fillComboBox()
|
|
|
|
{
|
|
|
|
m_comboLine->clear();
|
|
|
|
for (int row = 0; row < m_sheet->numRows(); ++row)
|
|
|
|
m_comboLine->insertItem(TQString::number(row + 1), row);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::setText(int row, int col, const TQString& text)
|
|
|
|
{
|
|
|
|
if (row < 1) // skipped by the user
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (m_sheet->numRows() < row) {
|
|
|
|
m_sheet->setNumRows(row+5000); /* We add 5000 at a time to limit recalculations */
|
|
|
|
m_adjustRows=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_sheet->numCols() < col)
|
|
|
|
m_sheet->setNumCols(col);
|
|
|
|
|
|
|
|
m_sheet->setText(row - 1, col - 1, text);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called after the first fillSheet() when number of rows are unknown.
|
|
|
|
*/
|
|
|
|
void CSVDialog::adjustRows(int iRows)
|
|
|
|
{
|
|
|
|
if (m_adjustRows)
|
|
|
|
{
|
|
|
|
m_sheet->setNumRows( iRows );
|
|
|
|
m_adjustRows=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::returnPressed()
|
|
|
|
{
|
|
|
|
if (m_delimiterBox->id(m_delimiterBox->selected()) != 4)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_delimiter = m_delimiterEdit->text();
|
|
|
|
fillSheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::textChanged ( const TQString & )
|
|
|
|
{
|
|
|
|
m_radioOther->setChecked ( true );
|
|
|
|
delimiterClicked(4); // other
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::formatClicked(int id)
|
|
|
|
{
|
|
|
|
TQString header;
|
|
|
|
|
|
|
|
switch (id)
|
|
|
|
{
|
|
|
|
case 1: // text
|
|
|
|
header = i18n("Text");
|
|
|
|
break;
|
|
|
|
case 0: // number
|
|
|
|
header = i18n("Number");
|
|
|
|
break;
|
|
|
|
case 3: // date
|
|
|
|
header = i18n("Date");
|
|
|
|
break;
|
|
|
|
case 2: // currency
|
|
|
|
header = i18n("Currency");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_sheet->horizontalHeader()->setLabel(m_sheet->currentColumn(), header);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::delimiterClicked(int id)
|
|
|
|
{
|
|
|
|
switch (id)
|
|
|
|
{
|
|
|
|
case 0: // comma
|
|
|
|
m_delimiter = ",";
|
|
|
|
break;
|
|
|
|
case 4: // other
|
|
|
|
m_delimiter = m_delimiterEdit->text();
|
|
|
|
break;
|
|
|
|
case 2: // tab
|
|
|
|
m_delimiter = "\t";
|
|
|
|
break;
|
|
|
|
case 3: // space
|
|
|
|
m_delimiter = " ";
|
|
|
|
break;
|
|
|
|
case 1: // semicolon
|
|
|
|
m_delimiter = ";";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fillSheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::textquoteSelected(const TQString& mark)
|
|
|
|
{
|
|
|
|
if (mark == i18n("none"))
|
|
|
|
m_textquote = 0;
|
|
|
|
else
|
|
|
|
m_textquote = mark[0];
|
|
|
|
|
|
|
|
fillSheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::lineSelected(const TQString& line)
|
|
|
|
{
|
|
|
|
m_startline = line.toInt() - 1;
|
|
|
|
fillSheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::currentCellChanged(int, int col)
|
|
|
|
{
|
|
|
|
int id;
|
|
|
|
TQString header = m_sheet->horizontalHeader()->label(col);
|
|
|
|
|
|
|
|
if (header == i18n("Text"))
|
|
|
|
id = 1;
|
|
|
|
else if (header == i18n("Number"))
|
|
|
|
id = 0;
|
|
|
|
else if (header == i18n("Date"))
|
|
|
|
id = 3;
|
|
|
|
else
|
|
|
|
id = 2;
|
|
|
|
|
|
|
|
m_formatBox->setButton(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::accept()
|
|
|
|
{
|
|
|
|
Sheet * sheet = m_pView->activeSheet();
|
|
|
|
TQString csv_delimiter = TQString();
|
|
|
|
Cell * cell;
|
|
|
|
|
|
|
|
int numRows = m_sheet->numRows();
|
|
|
|
int numCols = m_sheet->numCols();
|
|
|
|
|
|
|
|
if (numRows == 0)
|
|
|
|
++numRows;
|
|
|
|
|
|
|
|
if ( (numCols > m_targetRect.width()) && (m_targetRect.width() > 1) )
|
|
|
|
{
|
|
|
|
numCols = m_targetRect.width();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_targetRect.setRight( m_targetRect.left() + numCols );
|
|
|
|
|
|
|
|
if ( (numRows > m_targetRect.height()) && (m_targetRect.height() > 1) )
|
|
|
|
numRows = m_targetRect.height();
|
|
|
|
else
|
|
|
|
m_targetRect.setBottom( m_targetRect.top() + numRows );
|
|
|
|
|
|
|
|
if ( numRows == 1 && numCols == 1)
|
|
|
|
{
|
|
|
|
Doc * doc = m_pView->doc();
|
|
|
|
cell = sheet->nonDefaultCell( m_targetRect.left(), m_targetRect.top() );
|
|
|
|
if ( !doc->undoLocked() )
|
|
|
|
{
|
|
|
|
UndoSetText * undo = new UndoSetText( doc, sheet , cell->text(), m_targetRect.left(),
|
|
|
|
m_targetRect.top(), cell->formatType() );
|
|
|
|
doc->addCommand( undo );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UndoChangeAreaTextCell * undo = new UndoChangeAreaTextCell( m_pView->doc(), sheet , m_targetRect );
|
|
|
|
m_pView->doc()->addCommand( undo );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pView->doc()->emitBeginOperation();
|
|
|
|
|
|
|
|
int i;
|
|
|
|
int left = m_targetRect.left();
|
|
|
|
int top = m_targetRect.top();
|
|
|
|
|
|
|
|
TQMemArray<double> widths( numCols );
|
|
|
|
for ( i = 0; i < numCols; ++i )
|
|
|
|
{
|
|
|
|
ColumnFormat * c = sheet->nonDefaultColumnFormat( left + i );
|
|
|
|
widths[i] = c->dblWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int row = 0; row < numRows; ++row)
|
|
|
|
{
|
|
|
|
for (int col = 0; col < numCols; ++col)
|
|
|
|
{
|
|
|
|
cell = sheet->nonDefaultCell( left + col, top + row );
|
|
|
|
cell->setCellText( getText( row, col ) );
|
|
|
|
|
|
|
|
TQFontMetrics fm = sheet->painter().fontMetrics();
|
|
|
|
double w = fm.width( cell->strOutText() );
|
|
|
|
if ( w == 0.0 )
|
|
|
|
{
|
|
|
|
TQFontMetrics fm( cell->format()->textFont( left + col, top + row ) );
|
|
|
|
w = fm.width('x') * (double) getText( row, col ).length();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( w > widths[col] )
|
|
|
|
widths[col] = w;
|
|
|
|
|
|
|
|
cell->format()->setFormatType(Generic_format);
|
|
|
|
/*
|
|
|
|
Disabling this code for now, everything will use Generic formatting,
|
|
|
|
hoping for the best (Tomas)
|
|
|
|
//### FIXME: long term solution is to allow to select Generic format ("autodetect") in the dialog and make it the default
|
|
|
|
|
|
|
|
switch (getHeader(col))
|
|
|
|
{
|
|
|
|
case TEXT:
|
|
|
|
break;
|
|
|
|
case NUMBER:
|
|
|
|
cell->format()->setFormatType(Number_format);
|
|
|
|
cell->setPrecision(2);
|
|
|
|
break;
|
|
|
|
case DATE:
|
|
|
|
cell->format()->setFormatType(ShortDate_format);
|
|
|
|
break;
|
|
|
|
case CURRENCY:
|
|
|
|
cell->format()->setFormatType(Money_format);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i = 0; i < numCols; ++i )
|
|
|
|
{
|
|
|
|
ColumnFormat * c = sheet->nonDefaultColumnFormat( left + i );
|
|
|
|
c->setDblWidth( widths[i] );
|
|
|
|
sheet->emit_updateColumn( c, left + i );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pView->slotUpdateView( sheet );
|
|
|
|
TQDialog::accept();
|
|
|
|
}
|
|
|
|
|
|
|
|
int CSVDialog::getHeader(int col)
|
|
|
|
{
|
|
|
|
TQString header = 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
|
|
|
|
return DATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString CSVDialog::getText(int row, int col)
|
|
|
|
{
|
|
|
|
return m_sheet->text(row, col);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSVDialog::ignoreDuplicatesChanged(int)
|
|
|
|
{
|
|
|
|
fillSheet();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kspread_dlg_csv.moc"
|