Bug 132462 - usability: kspread csv export dialog does not remember encoding
Summary: usability: kspread csv export dialog does not remember encoding
Status: RESOLVED FIXED
Alias: None
Product: calligrasheets
Classification: Applications
Component: general (show other bugs)
Version: 1.5
Platform: Compiled Sources Linux
: NOR normal
Target Milestone: ---
Assignee: Calligra Sheets (KSpread) Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-08-15 22:07 UTC by Leo Savernik
Modified: 2007-01-14 20:19 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Leo Savernik 2006-08-15 22:07:46 UTC
Version:           1.5 (using KDE KDE 3.5.4)
Installed from:    Compiled From Sources

Not only can't you simply save (Ctrl+S) a csv file with the same settings as it was opened with in the first place without getting the dialog, the dialog even does *not remember* the latest settings.

I. e. I load a csv file with latin1 encoding, change it and save it (Ctrl+S). Then I get the export dialog, having "UTF-8" preselected. I click onto the text (which is easier to reach than the tiny knob at the far side), only to have a *caret* placed into the combo box line instead of popping up the menu.

Then I click the knob, select latin1 and click OK.

I have to perform these steps *every single time* I want to save a csv-file. This is *even nastier* than excel which only bugs about potential loss of formatting, but doesn't force to to change settings all time.
Comment 1 Leo Savernik 2007-01-14 20:19:35 UTC
SVN commit 623416 by savernik:

Fix nasty bugs and usability issues of csv-converter:
- Remember settings.
- Don't convert already converted document to utf8.
- Don't ignore newline settings on export (and only export unix-nl).

BUG: 132462


 M  +44 -1     csvdialog.cpp  
 M  +2 -0      csvdialog.h  
 M  +27 -6     csvexport.cc  
 M  +1 -1      csvexport.h  
 M  +53 -0     csvexportdialog.cpp  
 M  +2 -0      csvexportdialog.h  
 M  +1 -1      csvimport.cc  


--- branches/koffice/1.6/koffice/filters/kspread/csv/csvdialog.cpp #623415:623416
@@ -34,6 +34,7 @@
 #include <qtextcodec.h>
 
 #include <kapplication.h>
+#include <kconfig.h>
 #include <kdebug.h>
 #include <klocale.h>
 #include <kcombobox.h>
@@ -57,7 +58,7 @@
 {
     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() );
@@ -79,6 +80,8 @@
 
     m_dialog->m_sheet->setReadOnly( true );
 
+    loadSettings();
+
     fillTable();
 
     //resize(sizeHint());
@@ -109,9 +112,49 @@
 
 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;
--- branches/koffice/1.6/koffice/filters/kspread/csv/csvdialog.h #623415:623416
@@ -50,6 +50,8 @@
     QString getText(int row, int col);
 
 private:
+    void loadSettings();
+    void saveSettings();
     void fillTable();
     void fillComboBox();
     void setText(int row, int col, const QString& text);
--- branches/koffice/1.6/koffice/filters/kspread/csv/csvexport.cc #623415:623416
@@ -64,7 +64,7 @@
 {
 }
 
-QString CSVExport::exportCSVCell( Sheet const * const sheet, int col, int row, QChar const & textQuote )
+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:
@@ -89,6 +89,8 @@
         text = cell->strOutText();
   }
 
+  // quote only when needed (try to mimic excel)
+  bool quote = false;
   if ( !text.isEmpty() )
   {
     if ( text.find( textQuote ) != -1 )
@@ -96,8 +98,17 @@
       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);
   }
@@ -164,6 +175,7 @@
       return KoFilter::StupidError;
     }
     csvDelimiter = expDialog->getDelimiter();
+    m_eol = expDialog->getEndOfLine();
   }
   else
   {
@@ -229,7 +241,7 @@
       for ( int col = selection.left();
             col <= right && idxCol <= CSVMaxCol; ++col, ++idxCol )
       {
-        str += exportCSVCell( sheet, col, row, textQuote );
+        str += exportCSVCell( sheet, col, row, textQuote, csvDelimiter );
 
         if ( idxCol < CSVMaxCol )
           str += csvDelimiter;
@@ -324,13 +336,22 @@
           i = 0;
         }
 
+        QString collect;  // buffer delimiters while reading empty cells
+
         for ( int col = 1 ; col <= CSVMaxCol ; col++ )
         {
-          str += exportCSVCell( sheet, col, row, textQuote );
+          const QString txt = exportCSVCell( sheet, col, row, textQuote, csvDelimiter );
 
-          if ( col < CSVMaxCol )
-            str += 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;
       }
--- branches/koffice/1.6/koffice/filters/kspread/csv/csvexport.h #623415:623416
@@ -40,7 +40,7 @@
   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 );
+  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)  
--- branches/koffice/1.6/koffice/filters/kspread/csv/csvexportdialog.cpp #623415:623416
@@ -39,6 +39,7 @@
 #include <qvalidator.h>
 
 #include <kapplication.h>
+#include <kconfig.h>
 #include <klocale.h>
 #include <kdebug.h>
 #include <kcombobox.h>
@@ -88,14 +89,66 @@
            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();
--- branches/koffice/1.6/koffice/filters/kspread/csv/csvexportdialog.h #623415:623416
@@ -50,6 +50,8 @@
   QTextCodec* getCodec(void) const;
 
  private:
+  void loadSettings();
+  void saveSettings();
   ExportDialogUI * m_dialog;
 
   QValidator* m_delimiterValidator;
--- branches/koffice/1.6/koffice/filters/kspread/csv/csvimport.cc #623415:623416
@@ -142,7 +142,7 @@
         {
             value += step;
             emit sigProgress(value);
-            const QString text( dialog->getText( row, col ).utf8() );
+            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 );