<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.kde.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.6"
          urlbase="https://bugs.kde.org/"
          
          maintainer="sysadmin@kde.org"
>

    <bug>
          <bug_id>132462</bug_id>
          
          <creation_ts>2006-08-15 22:07:46 +0000</creation_ts>
          <short_desc>usability: kspread csv export dialog does not remember encoding</short_desc>
          <delta_ts>2007-01-14 20:19:37 +0000</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>2</classification_id>
          <classification>Applications</classification>
          <product>calligrasheets</product>
          <component>general</component>
          <version>1.5</version>
          <rep_platform>Compiled Sources</rep_platform>
          <op_sys>Linux</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>NOR</priority>
          <bug_severity>normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Leo Savernik">l.savernik</reporter>
          <assigned_to name="Calligra Sheets (KSpread) Bugs">calligra-sheets-bugs-null</assigned_to>
          
          
          <cf_commitlink></cf_commitlink>
          <cf_versionfixedin></cf_versionfixedin>
          <cf_sentryurl></cf_sentryurl>
          <votes>0</votes>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>460682</commentid>
    <comment_count>0</comment_count>
    <who name="Leo Savernik">l.savernik</who>
    <bug_when>2006-08-15 22:07:46 +0000</bug_when>
    <thetext>Version:           1.5 (using KDE KDE 3.5.4)
Installed from:    Compiled From Sources

Not only can&apos;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 &quot;UTF-8&quot; 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&apos;t force to to change settings all time.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>501563</commentid>
    <comment_count>1</comment_count>
    <who name="Leo Savernik">l.savernik</who>
    <bug_when>2007-01-14 20:19:35 +0000</bug_when>
    <thetext>SVN commit 623416 by savernik:

Fix nasty bugs and usability issues of csv-converter:
- Remember settings.
- Don&apos;t convert already converted document to utf8.
- Don&apos;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 &lt;qtextcodec.h&gt;
 
 #include &lt;kapplication.h&gt;
+#include &lt;kconfig.h&gt;
 #include &lt;kdebug.h&gt;
 #include &lt;klocale.h&gt;
 #include &lt;kcombobox.h&gt;
@@ -57,7 +58,7 @@
 {
     setCaption( i18n( &quot;Import&quot; ) );
     kapp-&gt;restoreOverrideCursor();
-
+    
     QStringList encodings;
     encodings &lt;&lt; i18n( &quot;Descriptive encoding name&quot;, &quot;Recommended ( %1 )&quot; ).arg( &quot;UTF-8&quot; );
     encodings &lt;&lt; i18n( &quot;Descriptive encoding name&quot;, &quot;Locale ( %1 )&quot; ).arg( QTextCodec::codecForLocale()-&gt;name() );
@@ -79,6 +80,8 @@
 
     m_dialog-&gt;m_sheet-&gt;setReadOnly( true );
 
+    loadSettings();
+
     fillTable();
 
     //resize(sizeHint());
@@ -109,9 +112,49 @@
 
 CSVDialog::~CSVDialog()
 {
+    saveSettings();
     kapp-&gt;setOverrideCursor(Qt::waitCursor);
 }
 
+void CSVDialog::loadSettings()
+{
+    KConfig *config = kapp-&gt;config();
+    config-&gt;setGroup(&quot;CSVDialog Settings&quot;);
+    m_textquote = config-&gt;readEntry(&quot;textquote&quot;, &quot;\&quot;&quot;)[0];
+    m_delimiter = config-&gt;readEntry(&quot;delimiter&quot;, &quot;,&quot;);
+    m_ignoreDups = config-&gt;readBoolEntry(&quot;ignoreDups&quot;, false);
+    const QString codecText = config-&gt;readEntry(&quot;codec&quot;, &quot;&quot;);
+
+    // update widgets
+    if (!codecText.isEmpty()) {
+      m_dialog-&gt;comboBoxEncoding-&gt;setCurrentText(codecText);
+      m_codec = getCodec();
+    }
+    if (m_delimiter == &quot;,&quot;) m_dialog-&gt;m_radioComma-&gt;setChecked(true);
+    else if (m_delimiter == &quot;\t&quot;) m_dialog-&gt;m_radioTab-&gt;setChecked(true);
+    else if (m_delimiter == &quot; &quot;) m_dialog-&gt;m_radioSpace-&gt;setChecked(true);
+    else if (m_delimiter == &quot;;&quot;) m_dialog-&gt;m_radioSemicolon-&gt;setChecked(true);
+    else {
+        m_dialog-&gt;m_radioOther-&gt;setChecked(true);
+        m_dialog-&gt;m_delimiterEdit-&gt;setText(m_delimiter);
+    }
+    m_dialog-&gt;m_ignoreDuplicates-&gt;setChecked(m_ignoreDups);
+    m_dialog-&gt;m_comboQuote-&gt;setCurrentItem(m_textquote == &apos;\&apos;&apos; ? 1
+        : m_textquote == &apos;&quot;&apos; ? 0 : 2);
+}
+
+void CSVDialog::saveSettings()
+{
+    KConfig *config = kapp-&gt;config();
+    config-&gt;setGroup(&quot;CSVDialog Settings&quot;);
+    QString q = m_textquote;
+    config-&gt;writeEntry(&quot;textquote&quot;, q);
+    config-&gt;writeEntry(&quot;delimiter&quot;, m_delimiter);
+    config-&gt;writeEntry(&quot;ignoreDups&quot;, m_ignoreDups);
+    config-&gt;writeEntry(&quot;codec&quot;, m_dialog-&gt;comboBoxEncoding-&gt;currentText());
+    config-&gt;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&amp; 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 &amp; textQuote )
+QString CSVExport::exportCSVCell( Sheet const * const sheet, int col, int row, QChar const &amp; 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-&gt;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( &quot;\n&quot; ) != -1 || text.find( &quot;\r&quot; ) != -1 )
+      quote = true;
+  }
+
+  if ( quote ) {
     text.prepend(textQuote);
     text.append(textQuote);
   }
@@ -164,6 +175,7 @@
       return KoFilter::StupidError;
     }
     csvDelimiter = expDialog-&gt;getDelimiter();
+    m_eol = expDialog-&gt;getEndOfLine();
   }
   else
   {
@@ -229,7 +241,7 @@
       for ( int col = selection.left();
             col &lt;= right &amp;&amp; idxCol &lt;= CSVMaxCol; ++col, ++idxCol )
       {
-        str += exportCSVCell( sheet, col, row, textQuote );
+        str += exportCSVCell( sheet, col, row, textQuote, csvDelimiter );
 
         if ( idxCol &lt; CSVMaxCol )
           str += csvDelimiter;
@@ -324,13 +336,22 @@
           i = 0;
         }
 
+        QString collect;  // buffer delimiters while reading empty cells
+
         for ( int col = 1 ; col &lt;= CSVMaxCol ; col++ )
         {
-          str += exportCSVCell( sheet, col, row, textQuote );
+          const QString txt = exportCSVCell( sheet, col, row, textQuote, csvDelimiter );
 
-          if ( col &lt; 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&apos;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 &amp; from, const QCString &amp; to );
 
   private:
-  QString exportCSVCell( KSpread::Sheet const * const sheet, int col, int row, QChar const &amp; textQuote );
+  QString exportCSVCell( KSpread::Sheet const * const sheet, int col, int row, QChar const &amp; textQuote, QChar delimiter );
 
   private:
   QString m_eol; ///&lt; End of line (LF, CR or CRLF)  
--- branches/koffice/1.6/koffice/filters/kspread/csv/csvexportdialog.cpp #623415:623416
@@ -39,6 +39,7 @@
 #include &lt;qvalidator.h&gt;
 
 #include &lt;kapplication.h&gt;
+#include &lt;kconfig.h&gt;
 #include &lt;klocale.h&gt;
 #include &lt;kdebug.h&gt;
 #include &lt;kcombobox.h&gt;
@@ -88,14 +89,66 @@
            this, SLOT( textquoteSelected( const QString &amp; ) ) );
   connect( m_dialog-&gt;m_selectionOnly, SIGNAL( toggled( bool ) ),
            this, SLOT( selectionOnlyChanged( bool ) ) );
+
+  loadSettings();
 }
 
 CSVExportDialog::~CSVExportDialog()
 {
+  saveSettings();
   kapp-&gt;setOverrideCursor(Qt::waitCursor);
   delete m_delimiterValidator;
 }
 
+void CSVExportDialog::loadSettings()
+{
+    KConfig *config = kapp-&gt;config();
+    config-&gt;setGroup(&quot;CSVDialog Settings&quot;);
+    m_textquote = config-&gt;readEntry(&quot;textquote&quot;, &quot;\&quot;&quot;)[0];
+    m_delimiter = config-&gt;readEntry(&quot;delimiter&quot;, &quot;,&quot;);
+    const QString codecText = config-&gt;readEntry(&quot;codec&quot;, &quot;&quot;);
+    bool selectionOnly = config-&gt;readBoolEntry(&quot;selectionOnly&quot;, false);
+    const QString sheetDelim = config-&gt;readEntry(&quot;sheetDelimiter&quot;, m_dialog-&gt;m_sheetDelimiter-&gt;text());
+    bool delimAbove = config-&gt;readBoolEntry(&quot;sheetDelimiterAbove&quot;, false);
+    const QString eol = config-&gt;readEntry(&quot;eol&quot;, &quot;\r\n&quot;);
+
+    // update widgets
+    if (!codecText.isEmpty()) {
+      m_dialog-&gt;comboBoxEncoding-&gt;setCurrentText(codecText);
+    }
+    if (m_delimiter == &quot;,&quot;) m_dialog-&gt;m_radioComma-&gt;setChecked(true);
+    else if (m_delimiter == &quot;\t&quot;) m_dialog-&gt;m_radioTab-&gt;setChecked(true);
+    else if (m_delimiter == &quot; &quot;) m_dialog-&gt;m_radioSpace-&gt;setChecked(true);
+    else if (m_delimiter == &quot;;&quot;) m_dialog-&gt;m_radioSemicolon-&gt;setChecked(true);
+    else {
+        m_dialog-&gt;m_radioOther-&gt;setChecked(true);
+        m_dialog-&gt;m_delimiterEdit-&gt;setText(m_delimiter);
+    }
+    m_dialog-&gt;m_comboQuote-&gt;setCurrentItem(m_textquote == &apos;\&apos;&apos; ? 1
+        : m_textquote == &apos;&quot;&apos; ? 0 : 2);
+    m_dialog-&gt;m_selectionOnly-&gt;setChecked(selectionOnly);
+    m_dialog-&gt;m_sheetDelimiter-&gt;setText(sheetDelim);
+    m_dialog-&gt;m_delimiterAboveAll-&gt;setChecked(delimAbove);
+    if (eol == &quot;\r\n&quot;) m_dialog-&gt;radioEndOfLineCRLF-&gt;setChecked(true);
+    else if (eol == &quot;\r&quot;) m_dialog-&gt;radioEndOfLineCR-&gt;setChecked(true);
+    else m_dialog-&gt;radioEndOfLineLF-&gt;setChecked(true);
+}
+
+void CSVExportDialog::saveSettings()
+{
+    KConfig *config = kapp-&gt;config();
+    config-&gt;setGroup(&quot;CSVDialog Settings&quot;);
+    QString q = m_textquote;
+    config-&gt;writeEntry(&quot;textquote&quot;, q);
+    config-&gt;writeEntry(&quot;delimiter&quot;, m_delimiter);
+    config-&gt;writeEntry(&quot;codec&quot;, m_dialog-&gt;comboBoxEncoding-&gt;currentText());
+    config-&gt;writeEntry(&quot;selectionOnly&quot;, exportSelectionOnly());
+    config-&gt;writeEntry(&quot;sheetDelimiter&quot;, getSheetDelimiter());
+    config-&gt;writeEntry(&quot;sheetDelimiterAbove&quot;, printAlwaysSheetDelimiter());
+    config-&gt;writeEntry(&quot;eol&quot;, getEndOfLine());
+    config-&gt;sync();
+}
+
 void CSVExportDialog::fillSheet( Map * map )
 {
   m_dialog-&gt;m_sheetList-&gt;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-&gt;getText( row, col ).utf8() );
+            const QString text( dialog-&gt;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 );
</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>