[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kmymoney/4.6] kmymoney/plugins/csvimport: Backporting a number of fixes from git, including
From:       Allan Anderson <agander93 () gmail ! com>
Date:       2012-06-30 19:16:48
Message-ID: 20120630191648.85E63A60A6 () git ! kde ! org
[Download RAW message or body]

Git commit 9645baffb96e73a810b91a46dd5342c269000867 by Allan Anderson.
Committed on 30/06/2012 at 19:18.
Pushed by allananderson into branch '4.6'.

Backporting a number of fixes from git, including
In CMakeLists.txt, add link with kmm_mymoney to avoid failure to link if strict \
linkage is used. Bug 302181
Bug 287786
Deal with case where a 'field seperator' is within quotes and the quotes don't \
include the whole of the field. Bug 295162
Bug 296550
Bug 296676
Bug 296977
Correct error message when checking decimal symbol.

M  +5    -3    kmymoney/plugins/csvimport/CMakeLists.txt
M  +123  -26   kmymoney/plugins/csvimport/csvimporterdlg.cpp
M  +2    -0    kmymoney/plugins/csvimport/csvimporterdlg.h
M  +52   -27   kmymoney/plugins/csvimport/csvprocessing.cpp
M  +3    -2    kmymoney/plugins/csvimport/csvprocessing.h
M  +4    -4    kmymoney/plugins/csvimport/csvutil.cpp
M  +43   -42   kmymoney/plugins/csvimport/investmentdlg.cpp
M  +98   -40   kmymoney/plugins/csvimport/investprocessing.cpp
M  +17   -4    kmymoney/plugins/csvimport/investprocessing.h
M  +28   -16   kmymoney/plugins/csvimport/redefinedlg.cpp
M  +4    -2    kmymoney/plugins/csvimport/redefinedlg.h

http://commits.kde.org/kmymoney/9645baffb96e73a810b91a46dd5342c269000867

diff --git a/kmymoney/plugins/csvimport/CMakeLists.txt \
b/kmymoney/plugins/csvimport/CMakeLists.txt index 1ca4590..bd18644 100644
--- a/kmymoney/plugins/csvimport/CMakeLists.txt
+++ b/kmymoney/plugins/csvimport/CMakeLists.txt
@@ -40,19 +40,19 @@ IF(KDE4_BUILD_TESTS)
   KDE4_ADD_UNIT_TEST(csvdatetest TESTNAME kmymoney-plugin-csvdatetest
     ${csvdatetest_SRCS})
   TARGET_LINK_LIBRARIES(csvdatetest ${QT_AND_KDECORE_LIBS}
-    ${QT_QTTEST_LIBRARY} ${KDE4_KDECORE_LIBS} )
+    ${QT_QTTEST_LIBRARY} ${KDE4_KDECORE_LIBS} kmm_mymoney)
 
   SET(parsedatatest_SRCS parsedatatest.cpp csvutil.cpp)
   KDE4_ADD_UNIT_TEST(parsedatatest TESTNAME kmymoney-plugin-parsedatatest
     ${parsedatatest_SRCS})
   TARGET_LINK_LIBRARIES(parsedatatest ${QT_AND_KDECORE_LIBS}
-    ${QT_QTTEST_LIBRARY} ${KDE4_KDECORE_LIBS} )
+    ${QT_QTTEST_LIBRARY} ${KDE4_KDECORE_LIBS} kmm_mymoney)
 
   SET(symboltest_SRCS symboltest.cpp csvutil.cpp)
   KDE4_ADD_UNIT_TEST(symboltest TESTNAME kmymoney-plugin-symboltest
     ${symboltest_SRCS})
   TARGET_LINK_LIBRARIES(symboltest ${QT_AND_KDECORE_LIBS}
-    ${QT_QTTEST_LIBRARY} ${KDE4_KDECORE_LIBS} )
+    ${QT_QTTEST_LIBRARY} ${KDE4_KDECORE_LIBS} kmm_mymoney)
 ENDIF(KDE4_BUILD_TESTS)
 
 ########### install files ###############
@@ -66,3 +66,5 @@ INSTALL(TARGETS kmm_csvimport
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/kmm_csvimport.desktop
         DESTINATION ${SERVICES_INSTALL_DIR})
 
+INSTALL(FILES csvimporterrc
+        DESTINATION ${CONFIG_INSTALL_DIR})
diff --git a/kmymoney/plugins/csvimport/csvimporterdlg.cpp \
b/kmymoney/plugins/csvimport/csvimporterdlg.cpp index 757622f..5315317 100644
--- a/kmymoney/plugins/csvimport/csvimporterdlg.cpp
+++ b/kmymoney/plugins/csvimport/csvimporterdlg.cpp
@@ -178,7 +178,8 @@ CsvImporterDlg::CsvImporterDlg(QWidget* parent) :
   connect(comboBoxInv_securityName, SIGNAL(activated(QString)), m_investProcessing, \
SLOT(securityNameSelected(QString)));  
   connect(spinBox_skip, SIGNAL(valueChanged(int)), this, \
                SLOT(startLineChanged(int)));
-  connect(spinBox_skip, SIGNAL(valueChanged(int)), m_csvprocessing, \
SLOT(startLineChanged())); +  connect(spinBox_skip, SIGNAL(valueChanged(int)), \
m_csvprocessing, SLOT(startLineChanged(int))); +  connect(spinBox_skip, \
SIGNAL(valueChanged(int)), m_investProcessing, SLOT(startLineChanged(int)));  \
connect(spinBox_skipToLast, SIGNAL(valueChanged(int)), this, \
SLOT(endLineChanged(int)));  connect(spinBox_skipToLast, SIGNAL(editingFinished()), \
m_csvprocessing, SLOT(endLineChanged()));  connect(spinBox_skipToLast, \
SIGNAL(editingFinished()), m_investProcessing, SLOT(endLineChanged())); @@ -230,17 \
+231,22 @@ void CsvImporterDlg::endLineChanged(int val)  
 void CsvImporterDlg::startLineChanged(int val)
 {
+  if (m_fileType != "Banking") {
+    return;
+  }
   m_startLine = val;
 }
 
 int CsvImporterDlg::validateColumn(const int& col, const QString& type)
 {
-  //  First check if selection is in range
+  if (m_csvprocessing->m_columnsNotSet) {  //       Don't check columns until \
they've been selected. +    return KMessageBox::Ok;
+  }
+  //  Now check if selection is in range
   if ((col < 0) || (col >= m_csvprocessing->endColumn())) {
     return KMessageBox::No;
   }//                                               selection was in range
 
-
   if ((!m_columnType[col].isEmpty())  && (m_columnType[col] != type)) {
     //                                              BUT column is already in use
 
@@ -249,7 +255,7 @@ int CsvImporterDlg::validateColumn(const int& col, const QString& \
type)  
     m_previousColumn = -1;
     resetComboBox(m_columnType[col], col);
-    resetComboBox(type, col);//                    reset this combobox
+    resetComboBox(type, col);//                     reset this combobox
     m_previousType.clear();
     m_columnType[col].clear();
     return KMessageBox::Cancel;
@@ -481,7 +487,7 @@ void CsvImporterDlg::saveSettings()
 
     KConfigGroup profileGroup(config, "Profile");
     profileGroup.writeEntry("CurrentUI", m_currentUI);
-    QString str = "$HOME/" + m_csvprocessing->csvPath().section('/', 3);
+    QString str = "~/" + m_csvprocessing->csvPath().section('/', 3);
     profileGroup.writeEntry("CsvDirectory", str);
     profileGroup.writeEntry("DateFormat", comboBox_dateFormat->currentIndex());
     profileGroup.writeEntry("FieldDelimiter", \
m_csvprocessing->fieldDelimiterIndex()); @@ -691,7 +697,9 @@ void \
CsvImporterDlg::tabSelected(int index)  }
       }
       if ((m_csvprocessing->inFileName().isEmpty()) || (m_currentUI == "Invest")) {
-        m_investmentDlg->saveSettings();//            leaving "Invest" so save \
settings +        if (m_investProcessing->m_columnsNotSet == false) {
+          m_investmentDlg->saveSettings();//            leaving "Invest" so save \
settings +        }
         m_csvprocessing->readSettings();//            ...and load "Banking"
         tableWidget->reset();
         tabWidget_Main->setTabText(0, i18n("Banking") + '*');
@@ -699,6 +707,7 @@ void CsvImporterDlg::tabSelected(int index)
       }
       m_fileType = "Banking";
       m_currentUI = "Banking";
+      m_csvprocessing->m_columnsNotSet = false;
       break;
     case 1 ://  "Invest" selected
       if ((!m_csvprocessing->inFileName().isEmpty())  && (m_currentUI == "Banking")) \
{ @@ -711,7 +720,9 @@ void CsvImporterDlg::tabSelected(int index)
         }
       }
       if ((m_investProcessing->inFileName().isEmpty()) || (m_currentUI == \
                "Banking")) {
-        saveSettings();//                             leaving "Banking" so save \
settings +        if (m_csvprocessing->m_columnsNotSet == false) {
+          saveSettings();//                             leaving "Banking" so save \
settings +        }
         m_investProcessing->readSettings();//         ...and load "Invest"
         tableWidget->reset();
         tabWidget_Main->setTabText(0, i18n("Banking"));
@@ -719,6 +730,7 @@ void CsvImporterDlg::tabSelected(int index)
       }
       m_fileType = "Invest";
       m_currentUI = "Invest";
+      m_investProcessing->m_columnsNotSet = false;
       break;
   }
 }
@@ -728,7 +740,16 @@ void CsvImporterDlg::updateDecimalSymbol(const QString& type, \
int col)  QString txt;
   bool symbolFound = false;
   bool invalidResult = false;
+  int startLine;
+  int endLine;
 
+  if (m_fileType == "Banking") {
+    startLine = m_csvprocessing->startLine();
+    endLine = m_endLine;
+  } else {
+    startLine = m_investProcessing->m_startLine;
+    endLine = m_investProcessing->m_endLine;
+  }
   //  Clear background
 
   for (int row = 0; row < m_endLine; row++) {
@@ -741,17 +762,17 @@ void CsvImporterDlg::updateDecimalSymbol(const QString& type, \
int col)  
     //  Set first and last rows
 
-    int first = m_startLine;
-    int last = m_endLine;
     m_parse->setSymbolFound(false);
 
     QString newTxt;
     int errorRow = 0;
     QTableWidgetItem* errorItem(0);
     //  Check if this col contains empty cells
-    int row = 0;
-    for (row = first - 1; row < last; row++) {
-      if (tableWidget->item(row, col) == 0) { //       empty cell
+    for (int row = startLine; row < tableWidget->rowCount(); row++) {
+      if (row > endLine - 1) {
+          break;
+        }
+      if (tableWidget->item(row, col) == 0) {  //       empty cell
         if (((m_fileType == "Banking") && (m_csvprocessing->importNow())) ||
             ((m_fileType == "Invest") && (m_investProcessing->importNow()))) {
           //                                     if importing, this is error
@@ -768,13 +789,10 @@ void CsvImporterDlg::updateDecimalSymbol(const QString& type, \
int col)  if (ret == KMessageBox::Continue) {
           continue;
         }
-        return;//                                     empty cell
+        return;//                                        empty cell
       } else {
-
         //  Check if this col contains decimal symbol
-
-        txt = tableWidget->item(row, col)->text();//  get data
-
+        txt = tableWidget->item(row, col)->text();//     get data
         newTxt = m_parse->possiblyReplaceSymbol(txt);//  update data
         tableWidget->item(row, col)->setText(newTxt);//  highlight selection
         tableWidget->item(row, col)->setBackground(m_colorBrush);
@@ -790,7 +808,7 @@ void CsvImporterDlg::updateDecimalSymbol(const QString& type, int \
col)  if (m_parse->symbolFound()) {
           symbolFound = true;
         }
-        if (newTxt == txt) { //                        no matching symbol found
+        if (newTxt == txt) { //                          no matching symbol found
           continue;
         }
       }
@@ -815,11 +833,7 @@ void CsvImporterDlg::updateDecimalSymbol(const QString& type, \
                int col)
       KMessageBox::sorry(0, i18n("<center>The selected decimal symbol/thousands \
                separator</center>"
                                  "<center>have produced invalid results in row %1, \
                and possibly more.</center>"
                                  "<center>Please try again.</center>", errorRow + \
                1), i18n("Invalid Conversion"));
-      if (m_fileType == "Banking") {
-        m_csvprocessing->readFile("", 0);
-      } else {
-        m_investProcessing->readFile("", 0);
-      }
+      return;
     }
   }
 }
@@ -832,7 +846,7 @@ void CsvImporterDlg::decimalSymbolSelected(int index)
     return;
   }
 
-  if (m_startLine > m_endLine) {
+  if (((m_fileType == "Banking") && (m_startLine > m_endLine)) || ((m_fileType == \
                "Invest") && (m_investProcessing->m_startLine > \
                m_investProcessing->m_endLine))) {
     KMessageBox::sorry(0, i18n("<center>The start line is greater than the end \
                line.\n</center>"
                                "<center>Please correct your settings.</center>"), \
i18n("CSV import"));  return;
@@ -840,12 +854,11 @@ void CsvImporterDlg::decimalSymbolSelected(int index)
 
   if (m_decimalSymbolChanged) {
     if (m_fileType == "Banking") {
-      m_csvprocessing->readFile("", 0);
+      m_csvprocessing->readFile("");
     } else {
       m_investProcessing->readFile("", 0);
     }
   }
-
   //  Save new decimal symbol and thousands separator
 
   m_decimalSymbolIndex = index;
@@ -906,3 +919,87 @@ void CsvImporterDlg::setCurrentUI(QString val)
 {
   m_currentUI = val;
 }
+
+bool CsvImporterDlg::validateAmounts()
+{
+  bool ok;
+  QString value;
+  QString pattern = "[" + KGlobal::locale()->currencySymbol() + "(), ]";
+  //
+  //  Ensure numeric columns do contain valid numeric values
+  //
+  if (m_fileType == "Banking") {
+    for (int row = m_csvprocessing->startLine(); row < tableWidget->rowCount(); \
row++) { +      for (int col = 0; col < tableWidget->columnCount(); col++) {
+        if ((columnType(col) == "amount") || (columnType(col) == "debit") || \
(columnType(col) == "credit")) { +          if (tableWidget->item(row, col) == 0) {  \
//  Does cell exist? +            continue;  //                              No
+          }
+          value = tableWidget->item(row, col)->text().remove(QRegExp(pattern));
+          if (value.isEmpty()) {  //                   An empty cell is OK, \
probably. +            continue;
+          }
+          value.toDouble(&ok); //                      Test validity.
+          if ((!ok) && (!m_acceptAllInvalid)) {
+            QString str = KGlobal::locale()->currencySymbol();
+            int rc = KMessageBox::questionYesNoCancel(this, i18n("<center>An invalid \
value has been detected in column %1 on row %2.</center>" +                           \
"Please check that you have selected the correct columns." +                          \
"<center>You may accept all similar items, or just this one, or cancel.</center>", +  \
col + 1, row + m_csvprocessing->startLine()), i18n("CSV import"), +                   \
KGuiItem(i18n("Accept All")), +                                                       \
KGuiItem(i18n("Accept This")), +                                                      \
KGuiItem(i18n("Cancel"))); +            switch (rc) {
+            case KMessageBox::Yes:  //  = "Accept All"
+              m_acceptAllInvalid = true;
+              continue;
+
+            case KMessageBox::No:  //   = "Accept This"
+              m_acceptAllInvalid = false;
+              continue;
+
+            case KMessageBox::Cancel:
+              return false;
+            }
+          }
+        }
+      }
+    }
+  } else {
+    for (int row = m_investProcessing->m_startLine; row < \
m_investProcessing->m_endLine; row++) { +      for (int col = 0; col < \
tableWidget->columnCount(); col++) { +        if \
((m_investProcessing->columnType(col) == "amount") || \
(m_investProcessing->columnType(col) == "quantity") || \
(m_investProcessing->columnType(col) == "price")) { +          if \
(tableWidget->item(row, col) == 0) {  //  Does cell exist... +            continue;  \
//                              No +          }
+          value = tableWidget->item(row, col)->text().remove(QRegExp(pattern));
+          if (value.isEmpty()) {  //                   An empty cell is OK, \
probably. +            continue;
+          }
+          value.toDouble(&ok); //                      Test validity.
+          if ((!ok) && (!m_acceptAllInvalid)) {
+            QString str = KGlobal::locale()->currencySymbol();
+            int rc = KMessageBox::questionYesNoCancel(this, i18n("<center>An invalid \
value has been detected in column %1 on row %2.</center>" +                           \
"Please check that you have selected the correct columns." +                          \
"<center>You may accept all similar items, or just this one, or cancel.</center>", +  \
col + 1, row + 1), i18n("CSV import"), +                                              \
KGuiItem(i18n("Accept All")), +                                                       \
KGuiItem(i18n("Accept This")), +                                                      \
KGuiItem(i18n("Cancel"))); +            switch (rc) {
+              case KMessageBox::Yes:  //  = "Accept All"
+                m_acceptAllInvalid = true;
+                continue;
+              case KMessageBox::No:  //   = "Accept This"
+                m_acceptAllInvalid = false;
+               continue;
+            case KMessageBox::Cancel:
+              return false;
+            }
+          }
+        }
+      }
+    }
+  }
+  return true;
+}
diff --git a/kmymoney/plugins/csvimport/csvimporterdlg.h \
b/kmymoney/plugins/csvimport/csvimporterdlg.h index 5773724..3faa6f6 100644
--- a/kmymoney/plugins/csvimport/csvimporterdlg.h
+++ b/kmymoney/plugins/csvimport/csvimporterdlg.h
@@ -66,6 +66,7 @@ public:
   Parse*              m_parse;
 
   bool             m_decimalSymbolChanged;
+  bool             m_acceptAllInvalid;
 
   void             saveSettings();
 
@@ -75,6 +76,7 @@ public:
   void             clearColumnType(int column);
   void             clearPreviousColumn();
   bool             amountSelected();
+  bool             validateAmounts();
   void             setAmountSelected(bool val);
   bool             creditSelected();
   void             setCreditSelected(bool val);
diff --git a/kmymoney/plugins/csvimport/csvprocessing.cpp \
b/kmymoney/plugins/csvimport/csvprocessing.cpp index 00f2815..4a93273 100644
--- a/kmymoney/plugins/csvimport/csvprocessing.cpp
+++ b/kmymoney/plugins/csvimport/csvprocessing.cpp
@@ -62,6 +62,7 @@ CsvProcessing::CsvProcessing()
 {
   m_importNow = false;
   m_showEmptyCheckBox = true;
+  m_columnsNotSet = true;
 
   m_dateFormatIndex = 0;
   m_endLine = 0;
@@ -114,6 +115,8 @@ void CsvProcessing::fileDialog()
 
   m_endLine = 0;
   m_flagCol = -1;
+  m_debitFlag = -1;
+  m_columnsNotSet = true;
   m_accept = false;
   m_csvDialog->m_decimalSymbolChanged = false;
   int posn;
@@ -121,8 +124,7 @@ void CsvProcessing::fileDialog()
     m_csvPath = "~/";
   }
 
-  QPointer<KFileDialog> dialog =
-    new KFileDialog(KUrl("kfiledialog:///kmymoney-csvbank"),
+  QPointer<KFileDialog> dialog = new KFileDialog(KUrl(m_csvPath),
                     i18n("*.csv *.PRN *.txt | CSV Files\n *|All files"),
                     0);
 //  Add encoding selection to FileDialog
@@ -155,6 +157,7 @@ void CsvProcessing::fileDialog()
     return;
   }
   m_importNow = false;//                       Avoid attempting date formatting on \
headers +  m_csvDialog->m_acceptAllInvalid = false;  //              Don't accept \
further invalid values.  clearComboBoxText();//                       to clear any \
'*' in memo combo text  
   for (int i = 0; i < MAXCOL; i++)
@@ -168,13 +171,13 @@ void CsvProcessing::fileDialog()
   rect.setHeight(9999);
   m_csvDialog->tableWidget->setGeometry(rect);
   m_parse->setSymbolFound(false);
+  readFile(m_inFileName);
 
-  readFile(m_inFileName, 0);
   m_csvPath = m_inFileName;
   posn = m_csvPath.lastIndexOf("/");
   m_csvPath.truncate(posn + 1);   //   keep last "/"
 
-  QString str = "$HOME/" + m_csvPath.section('/', 3);
+  QString str = "~/" + m_csvPath.section('/', 3);
   profileGroup.writeEntry("CsvDirectory", str);//          save selected path
   profileGroup.writeEntry("Encoding", m_encodeIndex);//    ..and encoding
   profileGroup.config()->sync();
@@ -183,6 +186,7 @@ void CsvProcessing::fileDialog()
   //The following two items do not *Require* an entry so old values must be cleared.
   m_trData.number.clear();// this needs to be cleared or gets added to next \
transaction  m_trData.memo.clear();//   this too, as neither might be overwritten by \
new data +  m_columnsNotSet = false;
 }
 
 void CsvProcessing::enableInputs()
@@ -268,7 +272,7 @@ void CsvProcessing::encodingChanged(int index)
 {
   m_encodeIndex = index;
   if (!m_inFileName.isEmpty())
-    readFile(m_inFileName, 0);
+    readFile(m_inFileName);
 }
 
 void CsvProcessing::findCodecs()
@@ -307,16 +311,16 @@ void CsvProcessing::delimiterChanged()
     return;
   }
   if (!m_inFileName.isEmpty())
-    readFile(m_inFileName, 0);
+    readFile(m_inFileName);
 }
 
-void CsvProcessing::readFile(const QString& fname, int skipLines)
+void CsvProcessing::readFile(const QString& fname)
 {
   MyMoneyStatement st = MyMoneyStatement();
   if (!fname.isEmpty()) {
     m_inFileName = fname;
   }
-  m_startLine = skipLines;
+
   m_csvDialog->tableWidget->clear();//         including vert headers
   m_inBuffer.clear();
   m_outBuffer.clear();
@@ -343,7 +347,7 @@ void CsvProcessing::readFile(const QString& fname, int skipLines)
 
   //  Parse the buffer
 
-  QStringList lineList = m_parse->parseFile(buf, m_startLine, m_endLine);
+  QStringList lineList = m_parse->parseFile(buf, 0, m_endLine);  //  Show whole of \
file  m_csvDialog->spinBox_skipToLast->setValue(m_parse->lastLine());
   m_csvDialog->tableWidget->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
  m_screenUpdated = false;
@@ -355,7 +359,7 @@ void CsvProcessing::readFile(const QString& fname, int skipLines)
 
     displayLine(m_inBuffer);
 
-    if (m_importNow) { //                        user now ready to continue
+    if ((m_importNow) && (i >= m_startLine) && (i <= \
m_csvDialog->spinBox_skipToLast->value() - 1)) { //   user now ready to continue  int \
ret = (processQifLine(m_inBuffer));// parse a line  if (ret == KMessageBox::Ok) {
         csvImportTransaction(st);
@@ -366,7 +370,7 @@ void CsvProcessing::readFile(const QString& fname, int skipLines)
 
   //  Adjust table size (drop header lines)
 
-  updateScreen();//
+  updateScreen();
   m_csvDialog->tableWidget->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
  m_csvDialog->labelSet_skip->setEnabled(true);
   m_csvDialog->spinBox_skip->setEnabled(true);
@@ -466,8 +470,8 @@ void CsvProcessing::csvImportTransaction(MyMoneyStatement& st)
         return ;
     }
   }
-  tr.m_amount = m_trData.amount;
-  tr.m_shares = m_trData.amount;
+  tr.m_amount = MyMoneyMoney(m_trData.amount);
+  tr.m_shares = MyMoneyMoney(m_trData.amount);
 
   tmp = m_trData.number;
   tr.m_strNumber = tmp;
@@ -491,6 +495,8 @@ void CsvProcessing::csvImportTransaction(MyMoneyStatement& st)
 int CsvProcessing::processQifLine(QString& iBuff)//   parse input line
 {
   QString newTxt;
+  bool firstField = true;
+  QString firstValue = QString();
 
   if (m_columnList.count() < m_endColumn) {
     if (!m_accept) {
@@ -516,7 +522,9 @@ int CsvProcessing::processQifLine(QString& iBuff)//   parse input \
line  iBuff = iBuff.remove(m_textDelimiterCharacter);
   memo.clear();//                                     memo & number may not have \
been used  m_trData.number.clear();//                          .. so need to clear \
                prior contents
-  for (int i = 0; i < m_endColumn; i++) {//            check each column
+
+  for (int i = 0; i < m_columnList.count(); i++) {  //        check each column
+    //  Use actual column count for this line instead of m_endColumn, (crash if last \
field missing).  if (m_csvDialog->columnType(i) == "number") {
       txt = m_columnList[i];
       m_trData.number = txt;
@@ -598,15 +606,28 @@ int CsvProcessing::processQifLine(QString& iBuff)//   parse \
                input line
     else if ((m_csvDialog->columnType(i) == "debit") || (m_csvDialog->columnType(i) \
== "credit")) { //  Credit or debit?  ++neededFieldsCount;
       txt = m_columnList[i];
-      if (!txt.isEmpty()) {
-        if (m_csvDialog->debitColumn() == i)
-          txt = '-' + txt;//                          Mark as -ve
-        if ((m_csvDialog->debitColumn() == i) || (m_csvDialog->creditColumn() == i)) \
                {
-          newTxt = m_parse->possiblyReplaceSymbol(txt);
-          m_trData.amount = newTxt;
-          m_qifBuffer = m_qifBuffer + 'T' + newTxt + '\n';
+      if ((!txt.isEmpty()) && ((i == m_csvDialog->debitColumn()))) {
+        txt = '-' + txt;//                                     Mark as -ve
+      }
+      //
+      //  Fix problem where both fields are empty (previous value was being re-used)
+      //
+      if (firstField) {  //                                    Debit or credit, \
whichever comes first. +        firstValue = txt;  //                                 \
Save field until second arrives. +      } else {  //                                  \
Second field. +        if (txt.isEmpty()) {  //                               If \
second field empty,... +          txt = firstValue;  //                               \
...use first (which could also be empty..)  }
       }
+      if (txt.isEmpty()) {
+        txt = '0';
+      }
+      if (!firstField) {  //                                   Process outcome.
+        newTxt = m_parse->possiblyReplaceSymbol(txt);
+        m_trData.amount = newTxt;
+        m_qifBuffer = m_qifBuffer + 'T' + newTxt + '\n';
+      }
+      firstField = !firstField;
     }
 
     else if (m_csvDialog->columnType(i) == "memo") { // could be more than one
@@ -649,14 +670,18 @@ void CsvProcessing::importClicked()
                                  "<center>Please correct your settings.</center>"), \
i18n("CSV import"));  return;
     }
+    if (!m_csvDialog->validateAmounts()) {
+      //  Invalid numeric field found
+      return;
+    }
 
     m_parse->setSymbolFound(false);
-    readFile(m_inFileName, skp);   //               skip all headers
+    readFile(m_inFileName);   //               skip all headers
 
     //--- create the (revised) vertical (row) headers ---
 
     QStringList vertHeaders;
-    for (int i = skp; i < m_csvDialog->tableWidget->rowCount() + skp; i++) {
+    for (int i = 0; i < m_csvDialog->tableWidget->rowCount() + skp; i++) {
       QString hdr = (QString::number(i + 1));
       vertHeaders += hdr;
     }
@@ -674,7 +699,7 @@ void CsvProcessing::readSettings()
 {
   int tmp;
   QString txt;
-  KSharedConfigPtr config = \
KSharedConfig::openConfig(KStandardDirs::locateLocal("config", "csvimporterrc")); +  \
KSharedConfigPtr config = KSharedConfig::openConfig(KStandardDirs::locate("config", \
"csvimporterrc"));  
   KConfigGroup profileGroup(config, "Profile");
   m_dateFormatIndex = profileGroup.readEntry("DateFormat", QString()).toInt();
@@ -696,7 +721,7 @@ void CsvProcessing::readSettings()
 
   m_csvPath = profileGroup.readEntry("CsvDirectory", QString());
 
-  m_debitFlag = profileGroup.readEntry("DebitFlag", QString().toInt());
+  m_debitFlag = profileGroup.readEntry("DebitFlag", -1);
 
   KConfigGroup columnsGroup(config, "Columns");
 
@@ -780,9 +805,9 @@ int CsvProcessing::startLine()
   return m_startLine;
 }
 
-void CsvProcessing::startLineChanged()
+void CsvProcessing::startLineChanged(int val)
 {
-  int val = m_csvDialog->spinBox_skip->value();
+  val = m_csvDialog->spinBox_skip->value();
   if (val < 1) {
     return;
   }
diff --git a/kmymoney/plugins/csvimport/csvprocessing.h \
b/kmymoney/plugins/csvimport/csvprocessing.h index 21c2720..e277d95 100644
--- a/kmymoney/plugins/csvimport/csvprocessing.h
+++ b/kmymoney/plugins/csvimport/csvprocessing.h
@@ -54,6 +54,7 @@ public:
   KComboBox*        m_comboBoxEncode;
 
   bool              m_screenUpdated;
+  bool              m_columnsNotSet;
 
   /**
   * This method is called after startup, to initialise some parameters.
@@ -124,7 +125,7 @@ public slots:
   * statement import. It will also be called to reposition the file after row
   * deletion, or to reread following encoding or delimiter change.
   */
-  void           readFile(const QString& fname, int skipLines);
+  void           readFile(const QString& fname);
 
   /**
   * This method is called when the user clicks 'Save as QIF'. A file selector
@@ -136,7 +137,7 @@ public slots:
   * This method is called when the user selects the start line.  The requested
   * start line  value is saved.
   */
-  void           startLineChanged();
+  void           startLineChanged(int);
 
   /**
   * This method is called when the user selects the end line.  The requested
diff --git a/kmymoney/plugins/csvimport/csvutil.cpp \
b/kmymoney/plugins/csvimport/csvutil.cpp index fc3d136..75fa3f3 100644
--- a/kmymoney/plugins/csvimport/csvutil.cpp
+++ b/kmymoney/plugins/csvimport/csvutil.cpp
@@ -45,12 +45,12 @@ QStringList Parse::parseLine(const QString& data)
   QString txt;
   QString txt1;
 
+  m_fieldDelimiterCharacter = m_fieldDelimiterCharList[m_fieldDelimiterIndex];
   m_inBuffer = data;
-  if (m_inBuffer.endsWith(',')) {
+  if (m_inBuffer.endsWith(m_fieldDelimiterCharacter)) {
     m_inBuffer.chop(1);
   }
 
-  m_fieldDelimiterCharacter = m_fieldDelimiterCharList[m_fieldDelimiterIndex];
   listIn = m_inBuffer.split(m_fieldDelimiterCharacter);// firstly, split on \
m_fieldDelimiterCharacter  
   QStringList::const_iterator constIterator;
@@ -60,8 +60,8 @@ QStringList Parse::parseLine(const QString& data)
     txt = (*constIterator);
     // detect where a "quoted" string has been erroneously split, because of a \
                comma,
     // or in a value, a 'thousand separator' being mistaken for a field delimitor.
-
-    while ((txt.startsWith(m_textDelimiterCharacter)) && \
(!txt.endsWith(m_textDelimiterCharacter)))  { +    // Also, where a 'field seperator' \
is within quotes and the quotes don't include the whole of the field. +    \
while((txt.startsWith(m_textDelimiterCharacter)) && \
(!txt.mid(1,-1).contains(m_textDelimiterCharacter))) {  if (++constIterator < \
                listIn.constEnd())  {
         txt1 = (*constIterator);//                       second part of the split \
                string
         txt += m_fieldDelimiterCharacter + txt1;//       rejoin the string
diff --git a/kmymoney/plugins/csvimport/investmentdlg.cpp \
b/kmymoney/plugins/csvimport/investmentdlg.cpp index 679370d..9a16475 100644
--- a/kmymoney/plugins/csvimport/investmentdlg.cpp
+++ b/kmymoney/plugins/csvimport/investmentdlg.cpp
@@ -111,48 +111,49 @@ void InvestmentDlg::slotClose()
 
 void InvestmentDlg::saveSettings()
 {
-  if (!m_investProcessing->inFileName().isEmpty()) { //          don't save column \
                numbers if no file loaded
-    KSharedConfigPtr config = \
                KSharedConfig::openConfig(KStandardDirs::locateLocal("config", \
                "csvimporterrc"));
-
-    KConfigGroup investmentGroup(config, "InvestmentSettings");
-
-    QString str = "$HOME/" + m_investProcessing->invPath().section('/', 3);
-    investmentGroup.writeEntry("InvDirectory", str);
-    investmentGroup.writeEntry("StartLine", m_csvDialog->spinBox_skip->value() - 1);
-    investmentGroup.config()->sync();
-
-    KConfigGroup profileGroup(config, "Profile");
-    profileGroup.writeEntry("DateFormat", \
                m_csvDialog->comboBox_dateFormat->currentIndex());
-    profileGroup.writeEntry("FieldDelimiter", \
                m_csvDialog->comboBox_fieldDelimiter->currentIndex());
-    profileGroup.config()->sync();
-
-    KConfigGroup invcolumnsGroup(config, "InvColumns");
-    invcolumnsGroup.writeEntry("DateCol", \
                m_csvDialog->comboBoxInv_dateCol->currentIndex());
-    invcolumnsGroup.writeEntry("PayeeCol", \
                m_csvDialog->comboBoxInv_typeCol->currentIndex());
-    invcolumnsGroup.writeEntry("MemoCol", \
                m_csvDialog->comboBoxInv_memoCol->currentIndex());
-    invcolumnsGroup.writeEntry("QuantityCol", \
                m_csvDialog->comboBoxInv_quantityCol->currentIndex());
-    invcolumnsGroup.writeEntry("AmountCol", \
                m_csvDialog->comboBoxInv_amountCol->currentIndex());
-    invcolumnsGroup.writeEntry("PriceCol", \
                m_csvDialog->comboBoxInv_priceCol->currentIndex());
-    invcolumnsGroup.writeEntry("FeeCol", \
                m_csvDialog->comboBoxInv_feeCol->currentIndex());
-    invcolumnsGroup.config()->sync();
-
-    KConfigGroup securitiesGroup(config, "Securities");
-    securitiesGroup.writeEntry("SecurityNameList", \
                m_investProcessing->securityList());
-    securitiesGroup.config()->sync();
-
-    /*    These settings do not get altered so need not be saved.
-
-    investmentGroup.writeEntry( "ShrsinParam", invcsv->shrsinList);
-    investmentGroup.writeEntry( "DivXParam", invcsv->divXList);
-    investmentGroup.writeEntry( "BrokerageParam", invcsv->brokerageList);
-    investmentGroup.writeEntry( "ReinvdivParam", invcsv->reinvdivList);
-    investmentGroup.writeEntry( "BuyParam", invcsv->buyList);
-    investmentGroup.writeEntry( "SellParam", invcsv->sellList);
-    investmentGroup.writeEntry( "RemoveParam", invcsv->removeList);
-    investmentGroup.config()->sync();*/
-
-    m_investProcessing->inFileName().clear();
+  if ((m_csvDialog->m_fileType != "Invest") || \
(m_investProcessing->inFileName().isEmpty())) {  // don't save if no file loaded +    \
return;  }
+  KSharedConfigPtr config = \
KSharedConfig::openConfig(KStandardDirs::locateLocal("config", "csvimporterrc")); +
+  KConfigGroup investmentGroup(config, "InvestmentSettings");
+
+  QString str = "~/" + m_investProcessing->invPath().section('/', 3);
+  investmentGroup.writeEntry("InvDirectory", str);
+  investmentGroup.writeEntry("StartLine", m_csvDialog->spinBox_skip->value() - 1);
+  investmentGroup.config()->sync();
+
+  KConfigGroup profileGroup(config, "Profile");
+  profileGroup.writeEntry("DateFormat", \
m_csvDialog->comboBox_dateFormat->currentIndex()); +  \
profileGroup.writeEntry("FieldDelimiter", \
m_csvDialog->comboBox_fieldDelimiter->currentIndex()); +  \
profileGroup.config()->sync(); +
+  KConfigGroup invcolumnsGroup(config, "InvColumns");
+  invcolumnsGroup.writeEntry("DateCol", \
m_csvDialog->comboBoxInv_dateCol->currentIndex()); +  \
invcolumnsGroup.writeEntry("PayeeCol", \
m_csvDialog->comboBoxInv_typeCol->currentIndex()); +  \
invcolumnsGroup.writeEntry("MemoCol", \
m_csvDialog->comboBoxInv_memoCol->currentIndex()); +  \
invcolumnsGroup.writeEntry("QuantityCol", \
m_csvDialog->comboBoxInv_quantityCol->currentIndex()); +  \
invcolumnsGroup.writeEntry("AmountCol", \
m_csvDialog->comboBoxInv_amountCol->currentIndex()); +  \
invcolumnsGroup.writeEntry("PriceCol", \
m_csvDialog->comboBoxInv_priceCol->currentIndex()); +  \
invcolumnsGroup.writeEntry("FeeCol", \
m_csvDialog->comboBoxInv_feeCol->currentIndex()); +  \
invcolumnsGroup.config()->sync(); +
+  KConfigGroup securitiesGroup(config, "Securities");
+  securitiesGroup.writeEntry("SecurityNameList", \
m_investProcessing->securityList()); +  securitiesGroup.config()->sync();
+
+  /*    These settings do not get altered so need not be saved.
+
+  investmentGroup.writeEntry( "ShrsinParam", invcsv->shrsinList);
+  investmentGroup.writeEntry( "DivXParam", invcsv->divXList);
+  investmentGroup.writeEntry( "BrokerageParam", invcsv->brokerageList);
+  investmentGroup.writeEntry( "ReinvdivParam", invcsv->reinvdivList);
+  investmentGroup.writeEntry( "BuyParam", invcsv->buyList);
+  investmentGroup.writeEntry( "SellParam", invcsv->sellList);
+  investmentGroup.writeEntry( "RemoveParam", invcsv->removeList);
+  investmentGroup.config()->sync();*/
+
+  m_investProcessing->inFileName().clear();
   m_csvDialog->tableWidget->clear();//     in case later reopening window, clear old \
contents now  }
 
@@ -166,7 +167,7 @@ void InvestmentDlg::resizeEvent(QResizeEvent * event)
 {
   event->accept();
   if (!m_investProcessing->inFileName().isEmpty())
-    m_investProcessing->updateScreen();
+    m_investProcessing->updateScreen(m_investProcessing->m_startLine);///m_investProcessing->m_startLine
  }
 
 void InvestmentDlg::fileDialog()
diff --git a/kmymoney/plugins/csvimport/investprocessing.cpp \
b/kmymoney/plugins/csvimport/investprocessing.cpp index 9f8e638..2328b24 100644
--- a/kmymoney/plugins/csvimport/investprocessing.cpp
+++ b/kmymoney/plugins/csvimport/investprocessing.cpp
@@ -68,6 +68,7 @@ InvestProcessing::InvestProcessing()
   m_priceSelected = false;
   m_quantitySelected = false;
   m_typeSelected = false;
+  m_columnsNotSet = true;
 
   m_dateFormatIndex = 0;
   m_fieldDelimiterIndex = 0;
@@ -93,7 +94,7 @@ InvestProcessing::InvestProcessing()
   m_parse = new Parse;
   m_redefine = new RedefineDlg;
 
-  connect(m_redefine, SIGNAL(changedType(QString)), this, \
SLOT(changedType(QString))); +  connect(m_redefine, SIGNAL(changedType(const \
QString)), this, SLOT(changedType(const QString)));  
 }
 
@@ -162,6 +163,7 @@ void InvestProcessing::fileDialog()
     return;
   }
   m_endLine = 0;
+  m_columnsNotSet = true;
   int position;
   if (m_invPath.isEmpty()) {
     m_invPath  = "~/";
@@ -170,7 +172,7 @@ void InvestProcessing::fileDialog()
   if (m_inFileName.isEmpty()) {
   }
 
-  QPointer<KFileDialog> dialog = new \
KFileDialog(KUrl("kfiledialog:///kmymoney-csvinvest"), +  QPointer<KFileDialog> \
dialog = new KFileDialog(KUrl(m_invPath),  i18n("*.csv *.PRN *.txt | CSV Files\n \
*|All files"), 0);  
   //  Add encoding selection to FileDialog
@@ -198,12 +200,12 @@ void InvestProcessing::fileDialog()
   }
   if (m_inFileName.isEmpty())
     return;
-  clearComboBoxText();//                    to clear any '*' in memo combo text
-  m_importNow = false;//                    Avoid attempting date formatting on \
                headers
-
+  clearComboBoxText();//                        to clear any '*' in memo combo text
+  m_importNow = false;//                        Avoid attempting date formatting on \
headers +  m_csvDialog->m_acceptAllInvalid = false;  //  Don't accept further invalid \
values.  for (int i = 0; i < MAXCOL; i++)
     if (columnType(i) == "memo") {
-      clearColumnType(i);   //    ensure no memo entries remain
+      clearColumnType(i);   //                  ensure no memo entries remain
     }
 
   //  set large field height to ensure resizing sees all lines in new file
@@ -211,7 +213,10 @@ void InvestProcessing::fileDialog()
   QRect rect = m_csvDialog->tableWidget->geometry();
   rect.setHeight(9999);
   m_csvDialog->tableWidget->setGeometry(rect);
-  readFile(m_inFileName , 0);
+  int tmp = m_startLine;
+  readFile(m_inFileName , 0);  //  Display all headers
+  m_startLine = tmp;
+  m_csvDialog->spinBox_skip->setValue(m_startLine);  //  Now set saved skip value
   m_invPath  = m_inFileName ;
   position = m_invPath .lastIndexOf("/");
   m_invPath .truncate(position + 1);
@@ -220,7 +225,7 @@ void InvestProcessing::fileDialog()
   KSharedConfigPtr config = \
KSharedConfig::openConfig(KStandardDirs::locateLocal("config", "csvimporterrc"));  
   KConfigGroup investmentGroup(config, "InvestmentSettings");
-  QString str = "$HOME/" + m_invPath.section('/', 3);
+  QString str = "~/" + m_invPath.section('/', 3);
   investmentGroup.writeEntry("InvDirectory", str);
   investmentGroup.config()->sync();//               save selected path
 #endif
@@ -279,6 +284,12 @@ void InvestProcessing::clearColumnNumbers()
   m_csvDialog->comboBoxInv_typeCol->setCurrentIndex(-1);
 }
 
+void InvestProcessing::clearColumnTypes()
+{
+  for (int i = 0; i < MAXCOL; i++) {
+    m_columnType[i].clear();
+  }
+}
 
 void InvestProcessing::clearComboBoxText()
 {
@@ -297,6 +308,7 @@ void InvestProcessing::encodingChanged(int index)
 void InvestProcessing::dateColumnSelected(int col)
 {
   QString type = "date";
+  m_dateColumn = col;
   if (col < 0) { //                              it is unset
     return;
   }
@@ -356,7 +368,10 @@ void InvestProcessing::findCodecs()
 
 int InvestProcessing::validateNewColumn(const int& col, const QString& type)
 {
-  //  First check if selection is in range
+  if (m_columnsNotSet) {  //                         Don't check columns until \
they've been selected. +    return KMessageBox::Ok;
+  }
+  //  Now check if selection is in range
   if ((col < 0) || (col >= m_endColumn)) {
     return KMessageBox::No;
   }
@@ -393,6 +408,7 @@ int InvestProcessing::validateNewColumn(const int& col, const \
QString& type)  void InvestProcessing::feeColumnSelected(int col)
 {
   QString type = "fee";
+  m_feeColumn = col;
   if (col < 0) { //                              it is unset
     return;
   }
@@ -422,6 +438,7 @@ void InvestProcessing::feeColumnSelected(int col)
 void InvestProcessing::typeColumnSelected(int col)
 {
   QString type = "type";
+  m_typeColumn = col;
   if (col < 0) { //                              it is unset
     return;
   }
@@ -452,6 +469,7 @@ void InvestProcessing::typeColumnSelected(int col)
 void InvestProcessing::memoColumnSelected(int col)
 {
   QString type = "memo";
+  m_memoColumn = col;
   if ((col < 0) || (col >= m_endColumn)) { //      out of range so...
     m_csvDialog->comboBoxInv_memoCol->setCurrentIndex(-1);// ..clear selection
     return;
@@ -482,6 +500,7 @@ void InvestProcessing::memoColumnSelected(int col)
 void InvestProcessing::quantityColumnSelected(int col)
 {
   QString type = "quantity";
+  m_quantityColumn = col;
   if (col < 0) { //                              it is unset
     return;
   }
@@ -512,6 +531,7 @@ void InvestProcessing::quantityColumnSelected(int col)
 void InvestProcessing::priceColumnSelected(int col)
 {
   QString type = "price";
+  m_priceColumn = col;
   if (col < 0) { //                              it is unset
     return;
   }
@@ -543,6 +563,7 @@ void InvestProcessing::priceColumnSelected(int col)
 void InvestProcessing::amountColumnSelected(int col)
 {
   QString type = "amount";
+  m_amountColumn = col;
   if (col < 0) { //                              it is unset
     return;
   }
@@ -608,7 +629,6 @@ void InvestProcessing::readFile(const QString& fname, int \
skipLines)  
   if (!fname.isEmpty())
     m_inFileName  = fname;
-  m_startLine = skipLines;
   QFile inFile(m_inFileName);
   inFile.open(QIODevice::ReadOnly | QIODevice::Text);
 
@@ -620,7 +640,7 @@ void InvestProcessing::readFile(const QString& fname, int \
skipLines)  
   //  Parse the buffer
 
-  QStringList lineList = m_parse->parseFile(buf, m_startLine, m_endLine);
+  QStringList lineList = m_parse->parseFile(buf, 0, m_endLine);
   m_endLine = m_parse->lastLine();
   m_csvDialog->spinBox_skipToLast->setValue(m_parse->lastLine());
 
@@ -633,9 +653,10 @@ void InvestProcessing::readFile(const QString& fname, int \
skipLines)  m_inBuffer = lineList[i];
 
     displayLine(m_inBuffer);//                             display it
-    if (m_importNow) {
+    if ((m_importNow) && (i >= m_startLine) && (i <= \
                m_csvDialog->spinBox_skipToLast->value() - 1)) {
       int ret = processInvestLine(m_inBuffer);  //         parse input line
       if (ret == KMessageBox::Ok) {
+        skipLines = 0;
         if (m_brokerage)
           investCsvImport(stBrokerage);//       add non-investment transaction to \
Brokerage statement  else
@@ -647,7 +668,7 @@ void InvestProcessing::readFile(const QString& fname, int \
skipLines)  
   //  Adjust table size (drop header lines)
 
-  updateScreen();
+  updateScreen(skipLines);
 
   m_csvDialog->labelSet_skip->setEnabled(true);
   m_csvDialog->spinBox_skip->setEnabled(true);
@@ -694,7 +715,6 @@ void InvestProcessing::displayLine(const QString& data)
       item->setTextAlignment(Qt::AlignRight);
     m_csvDialog->tableWidget->setRowCount(m_row + 1);
     m_csvDialog->tableWidget->setItem(m_row, col, item);     //add items to UI here
-    QRect rect = m_csvDialog->tableWidget->visualItemRect(item);
     m_csvDialog->tableWidget->resizeColumnToContents(col);
     col ++;
   }
@@ -704,12 +724,8 @@ void InvestProcessing::displayLine(const QString& data)
 int InvestProcessing::processInvestLine(const QString& inBuffer)
 {
   QString newTxt;
-  if ((m_priceColumn >= m_maxColumnCount) || (m_quantityColumn >= m_maxColumnCount) \
                || (m_amountColumn >= m_maxColumnCount)) {
-    KMessageBox::sorry(0, (i18n("The price, quantity and/or amount column values \
                appear to be invalid."
-                                "<center>Please correct the settings.</center>")),
-                       i18n("CSV import"));
-    return KMessageBox::Cancel;
-  }
+
+  int neededFieldsCount = 0;//            ensure essential fields are present
   //                                      validate all columns
   QString memo;
   QString payee;
@@ -730,9 +746,10 @@ int InvestProcessing::processInvestLine(const QString& inBuffer)
 
   m_brokerage = false;
   memo.clear();
-
-  for (int i = 0; i < m_endColumn; i++) {
+//BUG: 287786
+  for(int i = 0; i < m_columnList.count(); i++) {//  Use actual column count for \
this line instead of m_endColumn, which could be greater.  if (m_columnType[i] == \
"date") { //                    Date Col +      ++neededFieldsCount;
       txt = m_columnList[i];
       txt = txt.remove('"');
       QDate dat = m_convertDat->convertDate(txt);
@@ -754,6 +771,7 @@ int InvestProcessing::processInvestLine(const QString& inBuffer)
         return KMessageBox::Cancel;
       }
       m_trInvestData.type = txt;
+      ++neededFieldsCount;
       int ret = processActionType(m_trInvestData.type);
       if (ret == KMessageBox::Cancel) {
         return KMessageBox::Cancel;
@@ -780,6 +798,7 @@ int InvestProcessing::processInvestLine(const QString& inBuffer)
     }//end of memo field
 
     else if (m_columnType[i] == "quantity") { //           Quantity Col
+      ++neededFieldsCount;
       txt = m_columnList[i];
       newTxt = m_parse->possiblyReplaceSymbol(txt);
       m_trInvestData.quantity = MyMoneyMoney(newTxt);
@@ -787,6 +806,7 @@ int InvestProcessing::processInvestLine(const QString& inBuffer)
     }
 
     else if (m_columnType[i] == "price") { //              Price Col
+      ++neededFieldsCount;
       txt = m_csvDialog->comboBoxInv_priceFraction->currentText(); //fraction
       txt = txt.replace(m_csvDialog->decimalSymbol(), \
KGlobal::locale()->decimalSymbol());  MyMoneyMoney fraction = MyMoneyMoney(txt);
@@ -801,6 +821,7 @@ int InvestProcessing::processInvestLine(const QString& inBuffer)
     }
 
     else if (m_columnType[i] == "amount") { //             Amount Col
+      ++neededFieldsCount;
       txt = m_columnList[i];
       txt = txt.remove('"');
       if (txt.contains(')')) {
@@ -871,6 +892,13 @@ int InvestProcessing::processInvestLine(const QString& inBuffer)
     m_outBuffer += "^\n";
     m_outBuffer = m_outBuffer.remove('"');
   }
+  if (neededFieldsCount > 3) {
+    return KMessageBox::Ok;
+  } else {
+    KMessageBox::sorry(0, i18n("<center>The columns selected are \
invalid.\n</center>" +                               "There must an amount or \
quantity fields, symbol or security name, plus date and type field."), i18n("CSV \
import")); +    return KMessageBox::Cancel;
+  }
   return KMessageBox::Ok;
 }
 
@@ -1070,6 +1098,8 @@ void InvestProcessing::importClicked()
   if (!m_securityList.contains(m_securityName)) {
     m_securityList << m_securityName;
   }
+  m_dateSelected = (m_csvDialog->comboBoxInv_dateCol->currentIndex() >= 0);
+  m_typeSelected = (m_csvDialog->comboBoxInv_typeCol->currentIndex() >= 0);
   m_priceSelected = (m_csvDialog->comboBoxInv_priceCol->currentIndex() > 0);
   m_quantitySelected = (m_csvDialog->comboBoxInv_quantityCol->currentIndex() > 0);
   m_amountSelected = (m_csvDialog->comboBoxInv_amountCol->currentIndex() > 0);
@@ -1084,18 +1114,12 @@ void InvestProcessing::importClicked()
                                  "<center>Please correct your settings.</center>"), \
i18n("CSV import"));  return;
     }
-
+    if (!m_csvDialog->validateAmounts()) {
+      //  Invalid numeric field found
+      return;
+    }
     readFile(m_inFileName, skp);//StartLines
     m_screenUpdated = true;
-    //--- create the vertical (row) headers ---
-    QStringList vertHeaders;
-    for (int i = skp; i < m_csvDialog->tableWidget->rowCount() + skp; i++) {
-      QString hdr = QString::number(i + 1);
-      vertHeaders += hdr;
-    }
-    m_csvDialog->tableWidget->setVerticalHeaderLabels(vertHeaders);
-    m_csvDialog->tableWidget->hide();//     to ensure....
-    m_csvDialog->tableWidget->show();//    ....vertical header width redraws
   } else {
     KMessageBox::information(0, i18n("The Security Name, and Date and Type columns \
are needed.<center>Also, the Price, Quantity and Amount \
columns.</center><center>Please try again.</center>"));  }
@@ -1129,10 +1153,10 @@ void InvestProcessing::setCodecList(const QList<QTextCodec *> \
&list)  m_comboBoxEncode->addItem(codec->name(), codec->mibEnum());
 }
 
-void InvestProcessing::startLineChanged()
+void InvestProcessing::startLineChanged(int val)
 {
-  int val = m_csvDialog->spinBox_skip->value();
-  if (val < 1) {
+  val = m_csvDialog->spinBox_skip->value();
+  if ((val < 1) || (m_csvDialog->m_fileType == "Banking")) {
     return;
   }
   m_startLine = val - 1;
@@ -1140,7 +1164,7 @@ void InvestProcessing::startLineChanged()
 
 void InvestProcessing::endLineChanged()
 {
-  m_endLine = m_csvDialog->spinBox_skipToLast->value() ;
+  m_endLine = m_csvDialog->spinBox_skipToLast->value();
 }
 
 void InvestProcessing::dateFormatSelected(int dF)
@@ -1174,6 +1198,8 @@ QString InvestProcessing::accountName(const QString& aName)
 
 void InvestProcessing::readSettings()
 {
+  clearColumnTypes();//  Needs to be here in case user selects new profile after \
cancelling prior one. +  clearSelectedFlags();
   int tmp;
 
   KSharedConfigPtr config = \
KSharedConfig::openConfig(KStandardDirs::locateLocal("config", "csvimporterrc")); @@ \
-1205,11 +1231,11 @@ void InvestProcessing::readSettings()  
   KConfigGroup invcolumnsGroup(config, "InvColumns");
   if (invcolumnsGroup.exists()) {
-    tmp = invcolumnsGroup.readEntry("DateCol", QString()).toInt();
+    tmp = invcolumnsGroup.readEntry("DateCol", -1);
     m_csvDialog->comboBoxInv_dateCol->setCurrentIndex(-1);
     m_csvDialog->comboBoxInv_dateCol->setCurrentIndex(tmp);
 
-    tmp = invcolumnsGroup.readEntry("PayeeCol", QString()).toInt();//use for type \
col. +    tmp = invcolumnsGroup.readEntry("PayeeCol", -1);//use for type col.
     m_csvDialog->comboBoxInv_typeCol->setCurrentIndex(-1);
     m_csvDialog->comboBoxInv_typeCol->setCurrentIndex(tmp);
 
@@ -1248,12 +1274,29 @@ void InvestProcessing::readSettings()
   m_csvDialog->comboBoxInv_securityName->setCurrentIndex(-1);
 }
 
-void InvestProcessing::updateScreen()
+void InvestProcessing::updateScreen(int start)
 {
   if (m_row < 1)
     return;
   m_csvDialog->tableWidget->setRowCount(m_row);
   m_csvDialog->tableWidget->setFocus();
+  updateRowHeaders(start);
+}
+
+void InvestProcessing::updateRowHeaders(int skp)
+{
+ //--- create the (revised) vertical (row) headers ---
+
+  QStringList vertHeaders;
+  for (int i = skp; i < m_csvDialog->tableWidget->rowCount() + skp; i++) {
+    QString hdr = (QString::number(i + 1));
+    vertHeaders += hdr;
+  }
+  //  verticalHeader()->width() varies with its content so....
+
+  m_csvDialog->tableWidget->setVerticalHeaderLabels(vertHeaders);
+  m_csvDialog->tableWidget->hide();//             to ensure....
+  m_csvDialog->tableWidget->show();//             ..vertical header width redraws
 }
 
 void InvestProcessing::clearColumnType(int column)
@@ -1354,6 +1397,16 @@ int InvestProcessing::amountColumn()
   return m_amountColumn;
 }
 
+int InvestProcessing::dateColumn()
+{
+  return m_dateColumn;
+}
+
+int InvestProcessing::feeColumn()
+{
+  return m_feeColumn;
+}
+
 int InvestProcessing::quantityColumn()
 {
   return m_quantityColumn;
@@ -1364,6 +1417,11 @@ int InvestProcessing::priceColumn()
   return m_priceColumn;
 }
 
+int InvestProcessing::memoColumn()
+{
+  return m_memoColumn;
+}
+
 bool InvestProcessing::importNow()
 {
   return m_importNow;
@@ -1397,7 +1455,7 @@ void InvestProcessing::securityNameEdited()
            "<center>Otherwise, click \'Cancel\'.</center>",
            name), i18n("Add Security Name"));
   if (rc == KMessageBox::Cancel) {
-    m_csvDialog->comboBoxInv_securityName->clearEditText();///
+    m_csvDialog->comboBoxInv_securityName->clearEditText();
     m_csvDialog->comboBoxInv_securityName->setCurrentIndex(-1);
   } else {
     m_securityName = name;
diff --git a/kmymoney/plugins/csvimport/investprocessing.h \
b/kmymoney/plugins/csvimport/investprocessing.h index 337b485..2d96e06 100644
--- a/kmymoney/plugins/csvimport/investprocessing.h
+++ b/kmymoney/plugins/csvimport/investprocessing.h
@@ -96,6 +96,7 @@ public:
   * clear incorrect column number entries.
   */
   void           clearColumnNumbers();
+  void           clearColumnTypes();
 
   /**
   * Because the memo field allows multiple selections, it helps to be able
@@ -108,7 +109,7 @@ public:
   void           clearComboBoxText();
 
   void           setInFileName(const QString& val);
-  void           updateScreen();
+  void           updateScreen(int start);
 
   QString        columnType(int column);
   QString        invPath();
@@ -120,12 +121,21 @@ public:
   int            amountColumn();
   int            priceColumn();
   int            quantityColumn();
+  int            dateColumn();
+  int            detailColumn();
+  int            feeColumn();
+  int            symbolColumn();
+  int            typeColumn();
+  int            memoColumn();
 
   bool           importNow();
 
   int            m_endColumn;
+  int            m_endLine;
+  int            m_startLine;
 
   bool           m_screenUpdated;
+  bool           m_columnsNotSet;
 
 public:
 signals:
@@ -225,7 +235,7 @@ public slots:
   * This method is called when the user selects the start line.  The requested
   * start line  value is saved.
   */
-  void           startLineChanged();
+  void           startLineChanged(int);
 
   /**
   * This method is called when the user selects the end line.  The requested
@@ -311,6 +321,11 @@ private:
   */
   void           setCodecList(const QList<QTextCodec *> &list);
 
+  /**
+   * Called after rows have been dropped, to produce the (revised) vertical (row) \
headers. +   */
+  void updateRowHeaders(int skp);
+
   struct qifInvestData {
     QString      memo;
     MyMoneyMoney price;
@@ -349,8 +364,6 @@ private:
   int            m_quantityColumn;
   int            m_textDelimiterIndex;
   int            m_typeColumn;
-  int            m_endLine;
-  int            m_startLine;
   int            m_row;
   int            m_height;
 
diff --git a/kmymoney/plugins/csvimport/redefinedlg.cpp \
b/kmymoney/plugins/csvimport/redefinedlg.cpp index 332985a..b08d353 100644
--- a/kmymoney/plugins/csvimport/redefinedlg.cpp
+++ b/kmymoney/plugins/csvimport/redefinedlg.cpp
@@ -39,6 +39,7 @@ RedefineDlg::RedefineDlg()
   m_accountName.clear();
   m_amountColumn = 0;
   m_columnTotalWidth = 0;
+  m_maxWidth = 0;
   m_mainHeight = 0;
   m_mainWidth = 0;
   m_priceColumn = 0;
@@ -46,9 +47,9 @@ RedefineDlg::RedefineDlg()
   m_ret = 0;
   m_typeColumn = 0;
 
-  m_price = 0;
-  m_quantity = 0;
-  m_amount = 0;
+  m_price = MyMoneyMoney();
+  m_quantity = MyMoneyMoney();
+  m_amount = MyMoneyMoney();
 
   m_typesList << "buy" << "sell" << "divx" << "reinvdiv" << "shrsin" << "shrsout";
 
@@ -94,6 +95,7 @@ void RedefineDlg::displayLine(const QString& info)
   brush.setStyle(Qt::SolidPattern);
   int row;
   m_columnTotalWidth = 0;
+  m_maxWidth = 0;
   m_widget->tableWidget->setRowCount(2);
   for (int col = 0; col < m_maxCol; col++) {
     row = 1;
@@ -106,8 +108,8 @@ void RedefineDlg::displayLine(const QString& info)
     if (m_typeColumn == col) {
       item->setBackground(brush);
     }
-    m_columnTotalWidth += m_widget->tableWidget->columnWidth(col);
-
+///    m_columnTotalWidth += m_widget->tableWidget->columnWidth(col);
+///
     row = 0;
     if (col == m_quantityColumn) {
       QTableWidgetItem *item = new QTableWidgetItem;//        add items to UI
@@ -126,8 +128,19 @@ void RedefineDlg::displayLine(const QString& info)
       QTableWidgetItem *item = new QTableWidgetItem;//        add items to UI
       item->setText(i18n("Type"));
       m_widget->tableWidget->setItem(row, col, item);
+      } else if (col == m_detailColumn) {
+      QTableWidgetItem *item = new QTableWidgetItem;//        add items to UI
+      item->setText(i18n("Detail"));
+      m_widget->tableWidget->setItem(row, col, item);
     }
   }
+  m_widget->tableWidget->resizeColumnsToContents();
+  for (int col = 0; col < m_maxCol; col++) {
+    m_columnTotalWidth += m_widget->tableWidget->columnWidth(col);
+  }
+  if (m_columnTotalWidth > m_maxWidth) {
+    m_maxWidth = m_columnTotalWidth;
+  }
   updateWindow();
 }
 
@@ -273,22 +286,21 @@ void RedefineDlg::resizeEvent(QResizeEvent * event)
 {
   event->accept();
 
-  m_mainWidth = m_widget->verticalLayout->geometry().size().width() - 10;
-  m_mainHeight = m_widget->tableWidget->geometry().size().height();
+///  m_mainWidth = m_widget->verticalLayout->geometry().size().width() - 10;
+///  m_mainHeight = m_widget->tableWidget->geometry().size().height();
   updateWindow();
 }
 
 void RedefineDlg::updateWindow()
 {
-  int w = m_widget->tableWidget->width();
-  int hght = 4 + (m_widget->tableWidget->rowHeight(0) * 2);
-  hght += m_widget->tableWidget->horizontalHeader()->height() + 2;//  frig factor \
for vert. headers? +  int hght = 6 + (m_widget->tableWidget->rowHeight(0) * 2);
+  hght += m_widget->tableWidget->horizontalHeader()->height();//  frig factor for \
horiz. headers?  
-  if (m_columnTotalWidth > (m_mainWidth - 12))
-    hght += m_widget->tableWidget->horizontalScrollBar()->height() + 1;//  ....and \
for hor. scroll bar +  if (m_maxWidth > (m_mainWidth - 12)) {
+    hght += m_widget->tableWidget->horizontalScrollBar()->height() - 2;//  ....and \
for hor. scroll bar +  }
 
   m_widget->tableWidget->setFixedHeight(hght);
-  w = m_widget->tableWidget->width();
 }
 
 void RedefineDlg::convertValues()
@@ -296,9 +308,9 @@ void RedefineDlg::convertValues()
   QString txt;
   QString txt1;
   if (m_priceColumn < m_columnList.count())//  Ensure this is valid column
-    m_price = m_columnList[m_priceColumn].remove('"');
+    m_price = MyMoneyMoney(m_columnList[m_priceColumn].remove('"'));
   if (m_quantityColumn <  m_columnList.count())//  Ensure this is valid column
-    m_quantity = m_columnList[m_quantityColumn].remove('"');
+    m_quantity = MyMoneyMoney(m_columnList[m_quantityColumn].remove('"'));
   if (m_amountColumn <  m_columnList.count())//  Ensure this is valid column
     txt = m_columnList[m_amountColumn];
   if ((txt.startsWith('"')) && (!txt.endsWith('"')))  {
@@ -310,7 +322,7 @@ void RedefineDlg::convertValues()
   if (txt.contains(')')) {  //          replace negative ( ) with '-'
     txt = '-' + txt.remove(QRegExp("[(),]"));
   }
-  m_amount = txt;
+  m_amount = MyMoneyMoney(txt);
 }
 
 void RedefineDlg::setAmountColumn(int col)
diff --git a/kmymoney/plugins/csvimport/redefinedlg.h \
b/kmymoney/plugins/csvimport/redefinedlg.h index 1385feb..975d524 100644
--- a/kmymoney/plugins/csvimport/redefinedlg.h
+++ b/kmymoney/plugins/csvimport/redefinedlg.h
@@ -1,6 +1,6 @@
 /***************************************************************************
-redefine.h
--------------------
+                          redefine.h
+                      -------------------
 begin                 : Sat Jan 01 2010
 copyright             : (C) 2010 by Allan Anderson
 email                 : agander93@gmail.com
@@ -95,6 +95,7 @@ private:
 
   int              m_amountColumn;
   int              m_columnTotalWidth;
+  int              m_maxWidth;
   int              m_mainHeight;
   int              m_mainWidth;
   int              m_maxCol;
@@ -102,6 +103,7 @@ private:
   int              m_quantityColumn;
   int              m_ret;
   int              m_typeColumn;
+  int              m_detailColumn;
 
   MyMoneyMoney     m_price;
   MyMoneyMoney     m_quantity;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic