From kde-commits Sat Jun 30 19:16:48 2012 From: Allan Anderson Date: Sat, 30 Jun 2012 19:16:48 +0000 To: kde-commits Subject: [kmymoney/4.6] kmymoney/plugins/csvimport: Backporting a number of fixes from git, including Message-Id: <20120630191648.85E63A60A6 () git ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=134108404123610 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 st= rict linkage is used. Bug 302181 Bug 287786 Deal with case where a 'field seperator' is within quotes and the quotes do= n'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/c= svimport/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/plugi= ns/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_investPr= ocessing, SLOT(securityNameSelected(QString))); = connect(spinBox_skip, SIGNAL(valueChanged(int)), this, SLOT(startLineCha= nged(int))); - connect(spinBox_skip, SIGNAL(valueChanged(int)), m_csvprocessing, SLOT(s= tartLineChanged())); + connect(spinBox_skip, SIGNAL(valueChanged(int)), m_csvprocessing, SLOT(s= tartLineChanged(int))); + connect(spinBox_skip, SIGNAL(valueChanged(int)), m_investProcessing, SLO= T(startLineChanged(int))); connect(spinBox_skipToLast, SIGNAL(valueChanged(int)), this, SLOT(endLin= eChanged(int))); connect(spinBox_skipToLast, SIGNAL(editingFinished()), m_csvprocessing, = SLOT(endLineChanged())); connect(spinBox_skipToLast, SIGNAL(editingFinished()), m_investProcessin= g, SLOT(endLineChanged())); @@ -230,17 +231,22 @@ void CsvImporterDlg::endLineChanged(int val) = void CsvImporterDlg::startLineChanged(int val) { + if (m_fileType !=3D "Banking") { + return; + } m_startLine =3D 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 un= til they've been selected. + return KMessageBox::Ok; + } + // Now check if selection is in range if ((col < 0) || (col >=3D m_csvprocessing->endColumn())) { return KMessageBox::No; }// selection was in range = - if ((!m_columnType[col].isEmpty()) && (m_columnType[col] !=3D type)) { // BUT column is already = in use = @@ -249,7 +255,7 @@ int CsvImporterDlg::validateColumn(const int& col, cons= t QString& type) = m_previousColumn =3D -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 =3D "$HOME/" + m_csvprocessing->csvPath().section('/', 3); + QString str =3D "~/" + m_csvprocessing->csvPath().section('/', 3); profileGroup.writeEntry("CsvDirectory", str); profileGroup.writeEntry("DateFormat", comboBox_dateFormat->currentInde= x()); profileGroup.writeEntry("FieldDelimiter", m_csvprocessing->fieldDelimi= terIndex()); @@ -691,7 +697,9 @@ void CsvImporterDlg::tabSelected(int index) } } if ((m_csvprocessing->inFileName().isEmpty()) || (m_currentUI =3D=3D= "Invest")) { - m_investmentDlg->saveSettings();// leaving "Invest" so = save settings + if (m_investProcessing->m_columnsNotSet =3D=3D false) { + m_investmentDlg->saveSettings();// leaving "Invest" s= o 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 =3D "Banking"; m_currentUI =3D "Banking"; + m_csvprocessing->m_columnsNotSet =3D false; break; case 1 :// "Invest" selected if ((!m_csvprocessing->inFileName().isEmpty()) && (m_currentUI =3D= =3D "Banking")) { @@ -711,7 +720,9 @@ void CsvImporterDlg::tabSelected(int index) } } if ((m_investProcessing->inFileName().isEmpty()) || (m_currentUI =3D= =3D "Banking")) { - saveSettings();// leaving "Banking" so= save settings + if (m_csvprocessing->m_columnsNotSet =3D=3D 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 =3D "Invest"; m_currentUI =3D "Invest"; + m_investProcessing->m_columnsNotSet =3D false; break; } } @@ -728,7 +740,16 @@ void CsvImporterDlg::updateDecimalSymbol(const QString= & type, int col) QString txt; bool symbolFound =3D false; bool invalidResult =3D false; + int startLine; + int endLine; = + if (m_fileType =3D=3D "Banking") { + startLine =3D m_csvprocessing->startLine(); + endLine =3D m_endLine; + } else { + startLine =3D m_investProcessing->m_startLine; + endLine =3D m_investProcessing->m_endLine; + } // Clear background = for (int row =3D 0; row < m_endLine; row++) { @@ -741,17 +762,17 @@ void CsvImporterDlg::updateDecimalSymbol(const QStrin= g& type, int col) = // Set first and last rows = - int first =3D m_startLine; - int last =3D m_endLine; m_parse->setSymbolFound(false); = QString newTxt; int errorRow =3D 0; QTableWidgetItem* errorItem(0); // Check if this col contains empty cells - int row =3D 0; - for (row =3D first - 1; row < last; row++) { - if (tableWidget->item(row, col) =3D=3D 0) { // empty cell + for (int row =3D startLine; row < tableWidget->rowCount(); row++) { + if (row > endLine - 1) { + break; + } + if (tableWidget->item(row, col) =3D=3D 0) { // empty cell if (((m_fileType =3D=3D "Banking") && (m_csvprocessing->importNow(= ))) || ((m_fileType =3D=3D "Invest") && (m_investProcessing->importNo= w()))) { // if importing, this is err= or @@ -768,13 +789,10 @@ void CsvImporterDlg::updateDecimalSymbol(const QStrin= g& type, int col) if (ret =3D=3D KMessageBox::Continue) { continue; } - return;// empty cell + return;// empty cell } else { - // Check if this col contains decimal symbol - - txt =3D tableWidget->item(row, col)->text();// get data - + txt =3D tableWidget->item(row, col)->text();// get data newTxt =3D m_parse->possiblyReplaceSymbol(txt);// update data tableWidget->item(row, col)->setText(newTxt);// highlight selecti= on tableWidget->item(row, col)->setBackground(m_colorBrush); @@ -790,7 +808,7 @@ void CsvImporterDlg::updateDecimalSymbol(const QString&= type, int col) if (m_parse->symbolFound()) { symbolFound =3D true; } - if (newTxt =3D=3D txt) { // no matching sym= bol found + if (newTxt =3D=3D txt) { // no matching s= ymbol found continue; } } @@ -815,11 +833,7 @@ void CsvImporterDlg::updateDecimalSymbol(const QString= & type, int col) KMessageBox::sorry(0, i18n("
The selected decimal symbol/thou= sands separator
" "
have produced invalid results in= row %1, and possibly more.
" "
Please try again.
", err= orRow + 1), i18n("Invalid Conversion")); - if (m_fileType =3D=3D "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 =3D=3D "Banking") && (m_startLine > m_endLine)) || ((m_= fileType =3D=3D "Invest") && (m_investProcessing->m_startLine > m_investPro= cessing->m_endLine))) { KMessageBox::sorry(0, i18n("
The start line is greater than the= end line.\n
" "
Please correct your settings."), i18n("CSV import")); return; @@ -840,12 +854,11 @@ void CsvImporterDlg::decimalSymbolSelected(int index) = if (m_decimalSymbolChanged) { if (m_fileType =3D=3D "Banking") { - m_csvprocessing->readFile("", 0); + m_csvprocessing->readFile(""); } else { m_investProcessing->readFile("", 0); } } - // Save new decimal symbol and thousands separator = m_decimalSymbolIndex =3D index; @@ -906,3 +919,87 @@ void CsvImporterDlg::setCurrentUI(QString val) { m_currentUI =3D val; } + +bool CsvImporterDlg::validateAmounts() +{ + bool ok; + QString value; + QString pattern =3D "[" + KGlobal::locale()->currencySymbol() + "(), ]"; + // + // Ensure numeric columns do contain valid numeric values + // + if (m_fileType =3D=3D "Banking") { + for (int row =3D m_csvprocessing->startLine(); row < tableWidget->rowC= ount(); row++) { + for (int col =3D 0; col < tableWidget->columnCount(); col++) { + if ((columnType(col) =3D=3D "amount") || (columnType(col) =3D=3D "= debit") || (columnType(col) =3D=3D "credit")) { + if (tableWidget->item(row, col) =3D=3D 0) { // Does cell exist? + continue; // No + } + value =3D tableWidget->item(row, col)->text().remove(QRegExp(pat= tern)); + if (value.isEmpty()) { // An empty cell is OK= , probably. + continue; + } + value.toDouble(&ok); // Test validity. + if ((!ok) && (!m_acceptAllInvalid)) { + QString str =3D KGlobal::locale()->currencySymbol(); + int rc =3D KMessageBox::questionYesNoCancel(this, i18n("An invalid value has been detected in column %1 on row %2.
" + "Please c= heck that you have selected the correct columns." + "
= You may accept all similar items, or just this one, or cancel.
", + 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: // =3D "Accept All" + m_acceptAllInvalid =3D true; + continue; + + case KMessageBox::No: // =3D "Accept This" + m_acceptAllInvalid =3D false; + continue; + + case KMessageBox::Cancel: + return false; + } + } + } + } + } + } else { + for (int row =3D m_investProcessing->m_startLine; row < m_investProces= sing->m_endLine; row++) { + for (int col =3D 0; col < tableWidget->columnCount(); col++) { + if ((m_investProcessing->columnType(col) =3D=3D "amount") || (m_in= vestProcessing->columnType(col) =3D=3D "quantity") || (m_investProcessing->= columnType(col) =3D=3D "price")) { + if (tableWidget->item(row, col) =3D=3D 0) { // Does cell exist= ... + continue; // No + } + value =3D tableWidget->item(row, col)->text().remove(QRegExp(pat= tern)); + if (value.isEmpty()) { // An empty cell is OK= , probably. + continue; + } + value.toDouble(&ok); // Test validity. + if ((!ok) && (!m_acceptAllInvalid)) { + QString str =3D KGlobal::locale()->currencySymbol(); + int rc =3D KMessageBox::questionYesNoCancel(this, i18n("An invalid value has been detected in column %1 on row %2." + "Please c= heck that you have selected the correct columns." + "
= You may accept all similar items, or just this one, or cancel.
", + col + 1, = row + 1), i18n("CSV import"), + KGuiItem(= i18n("Accept All")), + KGuiItem(= i18n("Accept This")), + KGuiItem(= i18n("Cancel"))); + switch (rc) { + case KMessageBox::Yes: // =3D "Accept All" + m_acceptAllInvalid =3D true; + continue; + case KMessageBox::No: // =3D "Accept This" + m_acceptAllInvalid =3D 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/plugin= s/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 =3D false; m_showEmptyCheckBox =3D true; + m_columnsNotSet =3D true; = m_dateFormatIndex =3D 0; m_endLine =3D 0; @@ -114,6 +115,8 @@ void CsvProcessing::fileDialog() = m_endLine =3D 0; m_flagCol =3D -1; + m_debitFlag =3D -1; + m_columnsNotSet =3D true; m_accept =3D false; m_csvDialog->m_decimalSymbolChanged =3D false; int posn; @@ -121,8 +124,7 @@ void CsvProcessing::fileDialog() m_csvPath =3D "~/"; } = - QPointer dialog =3D - new KFileDialog(KUrl("kfiledialog:///kmymoney-csvbank"), + QPointer dialog =3D 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 =3D false;// Avoid attempting date for= matting on headers + m_csvDialog->m_acceptAllInvalid =3D false; // Don't accept= further invalid values. clearComboBoxText();// to clear any '*' in memo co= mbo text = for (int i =3D 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 =3D m_inFileName; posn =3D m_csvPath.lastIndexOf("/"); m_csvPath.truncate(posn + 1); // keep last "/" = - QString str =3D "$HOME/" + m_csvPath.section('/', 3); + QString str =3D "~/" + m_csvPath.section('/', 3); profileGroup.writeEntry("CsvDirectory", str);// save selected p= ath 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 b= e cleared. m_trData.number.clear();// this needs to be cleared or gets added to nex= t transaction m_trData.memo.clear();// this too, as neither might be overwritten by = new data + m_columnsNotSet =3D false; } = void CsvProcessing::enableInputs() @@ -268,7 +272,7 @@ void CsvProcessing::encodingChanged(int index) { m_encodeIndex =3D 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 =3D MyMoneyStatement(); if (!fname.isEmpty()) { m_inFileName =3D fname; } - m_startLine =3D 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 =3D m_parse->parseFile(buf, m_startLine, m_endLine); + QStringList lineList =3D m_parse->parseFile(buf, 0, m_endLine); // Sho= w whole of file m_csvDialog->spinBox_skipToLast->setValue(m_parse->lastLine()); m_csvDialog->tableWidget->horizontalHeader()->setResizeMode(QHeaderView:= :Interactive); m_screenUpdated =3D 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 >=3D m_startLine) && (i <=3D m_csvDialog->spin= Box_skipToLast->value() - 1)) { // user now ready to continue int ret =3D (processQifLine(m_inBuffer));// parse a line if (ret =3D=3D 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(MyMoneyStateme= nt& st) return ; } } - tr.m_amount =3D m_trData.amount; - tr.m_shares =3D m_trData.amount; + tr.m_amount =3D MyMoneyMoney(m_trData.amount); + tr.m_shares =3D MyMoneyMoney(m_trData.amount); = tmp =3D m_trData.number; tr.m_strNumber =3D tmp; @@ -491,6 +495,8 @@ void CsvProcessing::csvImportTransaction(MyMoneyStateme= nt& st) int CsvProcessing::processQifLine(QString& iBuff)// parse input line { QString newTxt; + bool firstField =3D true; + QString firstValue =3D QString(); = if (m_columnList.count() < m_endColumn) { if (!m_accept) { @@ -516,7 +522,9 @@ int CsvProcessing::processQifLine(QString& iBuff)// p= arse input line iBuff =3D iBuff.remove(m_textDelimiterCharacter); memo.clear();// memo & number may no= t have been used m_trData.number.clear();// .. so need to clear = prior contents - for (int i =3D 0; i < m_endColumn; i++) {// check each column + + for (int i =3D 0; i < m_columnList.count(); i++) { // check each= column + // Use actual column count for this line instead of m_endColumn, (cra= sh if last field missing). if (m_csvDialog->columnType(i) =3D=3D "number") { txt =3D m_columnList[i]; m_trData.number =3D txt; @@ -598,15 +606,28 @@ int CsvProcessing::processQifLine(QString& iBuff)// = parse input line else if ((m_csvDialog->columnType(i) =3D=3D "debit") || (m_csvDialog->= columnType(i) =3D=3D "credit")) { // Credit or debit? ++neededFieldsCount; txt =3D m_columnList[i]; - if (!txt.isEmpty()) { - if (m_csvDialog->debitColumn() =3D=3D i) - txt =3D '-' + txt;// Mark as -ve - if ((m_csvDialog->debitColumn() =3D=3D i) || (m_csvDialog->creditC= olumn() =3D=3D i)) { - newTxt =3D m_parse->possiblyReplaceSymbol(txt); - m_trData.amount =3D newTxt; - m_qifBuffer =3D m_qifBuffer + 'T' + newTxt + '\n'; + if ((!txt.isEmpty()) && ((i =3D=3D m_csvDialog->debitColumn()))) { + txt =3D '-' + txt;// Mark as -= ve + } + // + // Fix problem where both fields are empty (previous value was bein= g re-used) + // + if (firstField) { // Debit or cr= edit, whichever comes first. + firstValue =3D txt; // Save fiel= d until second arrives. + } else { // Second fiel= d. + if (txt.isEmpty()) { // If second f= ield empty,... + txt =3D firstValue; // ...use fi= rst (which could also be empty..) } } + if (txt.isEmpty()) { + txt =3D '0'; + } + if (!firstField) { // Process out= come. + newTxt =3D m_parse->possiblyReplaceSymbol(txt); + m_trData.amount =3D newTxt; + m_qifBuffer =3D m_qifBuffer + 'T' + newTxt + '\n'; + } + firstField =3D !firstField; } = else if (m_csvDialog->columnType(i) =3D=3D "memo") { // could be more = than one @@ -649,14 +670,18 @@ void CsvProcessing::importClicked() "
Please correct your settings."), 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 =3D skp; i < m_csvDialog->tableWidget->rowCount() + skp; i+= +) { + for (int i =3D 0; i < m_csvDialog->tableWidget->rowCount() + skp; i++)= { QString hdr =3D (QString::number(i + 1)); vertHeaders +=3D hdr; } @@ -674,7 +699,7 @@ void CsvProcessing::readSettings() { int tmp; QString txt; - KSharedConfigPtr config =3D KSharedConfig::openConfig(KStandardDirs::loc= ateLocal("config", "csvimporterrc")); + KSharedConfigPtr config =3D KSharedConfig::openConfig(KStandardDirs::loc= ate("config", "csvimporterrc")); = KConfigGroup profileGroup(config, "Profile"); m_dateFormatIndex =3D profileGroup.readEntry("DateFormat", QString()).to= Int(); @@ -696,7 +721,7 @@ void CsvProcessing::readSettings() = m_csvPath =3D profileGroup.readEntry("CsvDirectory", QString()); = - m_debitFlag =3D profileGroup.readEntry("DebitFlag", QString().toInt()); + m_debitFlag =3D 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 =3D m_csvDialog->spinBox_skip->value(); + val =3D 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 selec= tor @@ -136,7 +137,7 @@ public slots: * This method is called when the user selects the start line. The reque= sted * start line value is saved. */ - void startLineChanged(); + void startLineChanged(int); = /** * This method is called when the user selects the end line. The request= ed diff --git a/kmymoney/plugins/csvimport/csvutil.cpp b/kmymoney/plugins/csvi= mport/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 =3D m_fieldDelimiterCharList[m_fieldDelimiterI= ndex]; m_inBuffer =3D data; - if (m_inBuffer.endsWith(',')) { + if (m_inBuffer.endsWith(m_fieldDelimiterCharacter)) { m_inBuffer.chop(1); } = - m_fieldDelimiterCharacter =3D m_fieldDelimiterCharList[m_fieldDelimiterI= ndex]; listIn =3D 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 =3D (*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 de= limitor. - - 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).co= ntains(m_textDelimiterCharacter))) { if (++constIterator < listIn.constEnd()) { txt1 =3D (*constIterator);// second part of = the split string txt +=3D m_fieldDelimiterCharacter + txt1;// rejoin the stri= ng diff --git a/kmymoney/plugins/csvimport/investmentdlg.cpp b/kmymoney/plugin= s/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 sav= e column numbers if no file loaded - KSharedConfigPtr config =3D KSharedConfig::openConfig(KStandardDirs::l= ocateLocal("config", "csvimporterrc")); - - KConfigGroup investmentGroup(config, "InvestmentSettings"); - - QString str =3D "$HOME/" + m_investProcessing->invPath().section('/', = 3); - investmentGroup.writeEntry("InvDirectory", str); - investmentGroup.writeEntry("StartLine", m_csvDialog->spinBox_skip->val= ue() - 1); - investmentGroup.config()->sync(); - - KConfigGroup profileGroup(config, "Profile"); - profileGroup.writeEntry("DateFormat", m_csvDialog->comboBox_dateFormat= ->currentIndex()); - profileGroup.writeEntry("FieldDelimiter", m_csvDialog->comboBox_fieldD= elimiter->currentIndex()); - profileGroup.config()->sync(); - - KConfigGroup invcolumnsGroup(config, "InvColumns"); - invcolumnsGroup.writeEntry("DateCol", m_csvDialog->comboBoxInv_dateCol= ->currentIndex()); - invcolumnsGroup.writeEntry("PayeeCol", m_csvDialog->comboBoxInv_typeCo= l->currentIndex()); - invcolumnsGroup.writeEntry("MemoCol", m_csvDialog->comboBoxInv_memoCol= ->currentIndex()); - invcolumnsGroup.writeEntry("QuantityCol", m_csvDialog->comboBoxInv_qua= ntityCol->currentIndex()); - invcolumnsGroup.writeEntry("AmountCol", m_csvDialog->comboBoxInv_amoun= tCol->currentIndex()); - invcolumnsGroup.writeEntry("PriceCol", m_csvDialog->comboBoxInv_priceC= ol->currentIndex()); - invcolumnsGroup.writeEntry("FeeCol", m_csvDialog->comboBoxInv_feeCol->= currentIndex()); - invcolumnsGroup.config()->sync(); - - KConfigGroup securitiesGroup(config, "Securities"); - securitiesGroup.writeEntry("SecurityNameList", m_investProcessing->sec= urityList()); - 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 !=3D "Invest") || (m_investProcessing->inFi= leName().isEmpty())) { // don't save if no file loaded + return; } + KSharedConfigPtr config =3D KSharedConfig::openConfig(KStandardDirs::loc= ateLocal("config", "csvimporterrc")); + + KConfigGroup investmentGroup(config, "InvestmentSettings"); + + QString str =3D "~/" + 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_fieldDel= imiter->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_quant= ityCol->currentIndex()); + invcolumnsGroup.writeEntry("AmountCol", m_csvDialog->comboBoxInv_amountC= ol->currentIndex()); + invcolumnsGroup.writeEntry("PriceCol", m_csvDialog->comboBoxInv_priceCol= ->currentIndex()); + invcolumnsGroup.writeEntry("FeeCol", m_csvDialog->comboBoxInv_feeCol->cu= rrentIndex()); + invcolumnsGroup.config()->sync(); + + KConfigGroup securitiesGroup(config, "Securities"); + securitiesGroup.writeEntry("SecurityNameList", m_investProcessing->secur= ityList()); + 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/plu= gins/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 =3D false; m_quantitySelected =3D false; m_typeSelected =3D false; + m_columnsNotSet =3D true; = m_dateFormatIndex =3D 0; m_fieldDelimiterIndex =3D 0; @@ -93,7 +94,7 @@ InvestProcessing::InvestProcessing() m_parse =3D new Parse; m_redefine =3D new RedefineDlg; = - connect(m_redefine, SIGNAL(changedType(QString)), this, SLOT(changedType= (QString))); + connect(m_redefine, SIGNAL(changedType(const QString)), this, SLOT(chang= edType(const QString))); = } = @@ -162,6 +163,7 @@ void InvestProcessing::fileDialog() return; } m_endLine =3D 0; + m_columnsNotSet =3D true; int position; if (m_invPath.isEmpty()) { m_invPath =3D "~/"; @@ -170,7 +172,7 @@ void InvestProcessing::fileDialog() if (m_inFileName.isEmpty()) { } = - QPointer dialog =3D new KFileDialog(KUrl("kfiledialog:///km= ymoney-csvinvest"), + QPointer dialog =3D 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 =3D false;// Avoid attempting date format= ting on headers - + clearComboBoxText();// to clear any '*' in memo c= ombo text + m_importNow =3D false;// Avoid attempting date fo= rmatting on headers + m_csvDialog->m_acceptAllInvalid =3D false; // Don't accept further inv= alid values. for (int i =3D 0; i < MAXCOL; i++) if (columnType(i) =3D=3D "memo") { - clearColumnType(i); // ensure no memo entries remain + clearColumnType(i); // ensure no memo entries rem= ain } = // set large field height to ensure resizing sees all lines in new file @@ -211,7 +213,10 @@ void InvestProcessing::fileDialog() QRect rect =3D m_csvDialog->tableWidget->geometry(); rect.setHeight(9999); m_csvDialog->tableWidget->setGeometry(rect); - readFile(m_inFileName , 0); + int tmp =3D m_startLine; + readFile(m_inFileName , 0); // Display all headers + m_startLine =3D tmp; + m_csvDialog->spinBox_skip->setValue(m_startLine); // Now set saved ski= p value m_invPath =3D m_inFileName ; position =3D m_invPath .lastIndexOf("/"); m_invPath .truncate(position + 1); @@ -220,7 +225,7 @@ void InvestProcessing::fileDialog() KSharedConfigPtr config =3D KSharedConfig::openConfig(KStandardDirs::loc= ateLocal("config", "csvimporterrc")); = KConfigGroup investmentGroup(config, "InvestmentSettings"); - QString str =3D "$HOME/" + m_invPath.section('/', 3); + QString str =3D "~/" + 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 =3D 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 =3D "date"; + m_dateColumn =3D col; if (col < 0) { // it is unset return; } @@ -356,7 +368,10 @@ void InvestProcessing::findCodecs() = int InvestProcessing::validateNewColumn(const int& col, const QString& typ= e) { - // First check if selection is in range + if (m_columnsNotSet) { // Don't check columns u= ntil they've been selected. + return KMessageBox::Ok; + } + // Now check if selection is in range if ((col < 0) || (col >=3D 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 =3D "fee"; + m_feeColumn =3D col; if (col < 0) { // it is unset return; } @@ -422,6 +438,7 @@ void InvestProcessing::feeColumnSelected(int col) void InvestProcessing::typeColumnSelected(int col) { QString type =3D "type"; + m_typeColumn =3D col; if (col < 0) { // it is unset return; } @@ -452,6 +469,7 @@ void InvestProcessing::typeColumnSelected(int col) void InvestProcessing::memoColumnSelected(int col) { QString type =3D "memo"; + m_memoColumn =3D col; if ((col < 0) || (col >=3D m_endColumn)) { // out of range so... m_csvDialog->comboBoxInv_memoCol->setCurrentIndex(-1);// ..clear selec= tion return; @@ -482,6 +500,7 @@ void InvestProcessing::memoColumnSelected(int col) void InvestProcessing::quantityColumnSelected(int col) { QString type =3D "quantity"; + m_quantityColumn =3D col; if (col < 0) { // it is unset return; } @@ -512,6 +531,7 @@ void InvestProcessing::quantityColumnSelected(int col) void InvestProcessing::priceColumnSelected(int col) { QString type =3D "price"; + m_priceColumn =3D col; if (col < 0) { // it is unset return; } @@ -543,6 +563,7 @@ void InvestProcessing::priceColumnSelected(int col) void InvestProcessing::amountColumnSelected(int col) { QString type =3D "amount"; + m_amountColumn =3D col; if (col < 0) { // it is unset return; } @@ -608,7 +629,6 @@ void InvestProcessing::readFile(const QString& fname, i= nt skipLines) = if (!fname.isEmpty()) m_inFileName =3D fname; - m_startLine =3D skipLines; QFile inFile(m_inFileName); inFile.open(QIODevice::ReadOnly | QIODevice::Text); = @@ -620,7 +640,7 @@ void InvestProcessing::readFile(const QString& fname, i= nt skipLines) = // Parse the buffer = - QStringList lineList =3D m_parse->parseFile(buf, m_startLine, m_endLine); + QStringList lineList =3D m_parse->parseFile(buf, 0, m_endLine); m_endLine =3D 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 =3D lineList[i]; = displayLine(m_inBuffer);// display it - if (m_importNow) { + if ((m_importNow) && (i >=3D m_startLine) && (i <=3D m_csvDialog->spin= Box_skipToLast->value() - 1)) { int ret =3D processInvestLine(m_inBuffer); // parse input l= ine if (ret =3D=3D KMessageBox::Ok) { + skipLines =3D 0; if (m_brokerage) investCsvImport(stBrokerage);// add non-investment transac= tion to Brokerage statement else @@ -647,7 +668,7 @@ void InvestProcessing::readFile(const QString& fname, i= nt 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 t= o UI here - QRect rect =3D 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 >=3D m_maxColumnCount) || (m_quantityColumn >=3D m_ma= xColumnCount) || (m_amountColumn >=3D m_maxColumnCount)) { - KMessageBox::sorry(0, (i18n("The price, quantity and/or amount column = values appear to be invalid." - "
Please correct the settings.")), - i18n("CSV import")); - return KMessageBox::Cancel; - } + + int neededFieldsCount =3D 0;// ensure essential fields are pr= esent // validate all columns QString memo; QString payee; @@ -730,9 +746,10 @@ int InvestProcessing::processInvestLine(const QString&= inBuffer) = m_brokerage =3D false; memo.clear(); - - for (int i =3D 0; i < m_endColumn; i++) { +//BUG: 287786 + for(int i =3D 0; i < m_columnList.count(); i++) {// Use actual column c= ount for this line instead of m_endColumn, which could be greater. if (m_columnType[i] =3D=3D "date") { // Date Col + ++neededFieldsCount; txt =3D m_columnList[i]; txt =3D txt.remove('"'); QDate dat =3D m_convertDat->convertDate(txt); @@ -754,6 +771,7 @@ int InvestProcessing::processInvestLine(const QString& = inBuffer) return KMessageBox::Cancel; } m_trInvestData.type =3D txt; + ++neededFieldsCount; int ret =3D processActionType(m_trInvestData.type); if (ret =3D=3D KMessageBox::Cancel) { return KMessageBox::Cancel; @@ -780,6 +798,7 @@ int InvestProcessing::processInvestLine(const QString& = inBuffer) }//end of memo field = else if (m_columnType[i] =3D=3D "quantity") { // Quantity Col + ++neededFieldsCount; txt =3D m_columnList[i]; newTxt =3D m_parse->possiblyReplaceSymbol(txt); m_trInvestData.quantity =3D MyMoneyMoney(newTxt); @@ -787,6 +806,7 @@ int InvestProcessing::processInvestLine(const QString& = inBuffer) } = else if (m_columnType[i] =3D=3D "price") { // Price Col + ++neededFieldsCount; txt =3D m_csvDialog->comboBoxInv_priceFraction->currentText(); //fra= ction txt =3D txt.replace(m_csvDialog->decimalSymbol(), KGlobal::locale()-= >decimalSymbol()); MyMoneyMoney fraction =3D MyMoneyMoney(txt); @@ -801,6 +821,7 @@ int InvestProcessing::processInvestLine(const QString& = inBuffer) } = else if (m_columnType[i] =3D=3D "amount") { // Amount Col + ++neededFieldsCount; txt =3D m_columnList[i]; txt =3D txt.remove('"'); if (txt.contains(')')) { @@ -871,6 +892,13 @@ int InvestProcessing::processInvestLine(const QString&= inBuffer) m_outBuffer +=3D "^\n"; m_outBuffer =3D m_outBuffer.remove('"'); } + if (neededFieldsCount > 3) { + return KMessageBox::Ok; + } else { + KMessageBox::sorry(0, i18n("
The columns selected are invalid.\= n
" + "There must an amount or quantity fields, s= ymbol 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 =3D (m_csvDialog->comboBoxInv_dateCol->currentIndex() >= =3D 0); + m_typeSelected =3D (m_csvDialog->comboBoxInv_typeCol->currentIndex() >= =3D 0); m_priceSelected =3D (m_csvDialog->comboBoxInv_priceCol->currentIndex() >= 0); m_quantitySelected =3D (m_csvDialog->comboBoxInv_quantityCol->currentInd= ex() > 0); m_amountSelected =3D (m_csvDialog->comboBoxInv_amountCol->currentIndex()= > 0); @@ -1084,18 +1114,12 @@ void InvestProcessing::importClicked() "
Please correct your settings."), i18n("CSV import")); return; } - + if (!m_csvDialog->validateAmounts()) { + // Invalid numeric field found + return; + } readFile(m_inFileName, skp);//StartLines m_screenUpdated =3D true; - //--- create the vertical (row) headers --- - QStringList vertHeaders; - for (int i =3D skp; i < m_csvDialog->tableWidget->rowCount() + skp; i+= +) { - QString hdr =3D QString::number(i + 1); - vertHeaders +=3D hdr; - } - m_csvDialog->tableWidget->setVerticalHeaderLabels(vertHeaders); - m_csvDialog->tableWidget->hide();// to ensure.... - m_csvDialog->tableWidget->show();// ....vertical header width redra= ws } else { KMessageBox::information(0, i18n("The Security Name, and Date and Type= columns are needed.
Also, the Price, Quantity and Amount columns.
Please try again.
")); } @@ -1129,10 +1153,10 @@ void InvestProcessing::setCodecList(const QList &list) m_comboBoxEncode->addItem(codec->name(), codec->mibEnum()); } = -void InvestProcessing::startLineChanged() +void InvestProcessing::startLineChanged(int val) { - int val =3D m_csvDialog->spinBox_skip->value(); - if (val < 1) { + val =3D m_csvDialog->spinBox_skip->value(); + if ((val < 1) || (m_csvDialog->m_fileType =3D=3D "Banking")) { return; } m_startLine =3D val - 1; @@ -1140,7 +1164,7 @@ void InvestProcessing::startLineChanged() = void InvestProcessing::endLineChanged() { - m_endLine =3D m_csvDialog->spinBox_skipToLast->value() ; + m_endLine =3D 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 =3D KSharedConfig::openConfig(KStandardDirs::loc= ateLocal("config", "csvimporterrc")); @@ -1205,11 +1231,11 @@ void InvestProcessing::readSettings() = KConfigGroup invcolumnsGroup(config, "InvColumns"); if (invcolumnsGroup.exists()) { - tmp =3D invcolumnsGroup.readEntry("DateCol", QString()).toInt(); + tmp =3D invcolumnsGroup.readEntry("DateCol", -1); m_csvDialog->comboBoxInv_dateCol->setCurrentIndex(-1); m_csvDialog->comboBoxInv_dateCol->setCurrentIndex(tmp); = - tmp =3D invcolumnsGroup.readEntry("PayeeCol", QString()).toInt();//use= for type col. + tmp =3D 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 =3D skp; i < m_csvDialog->tableWidget->rowCount() + skp; i++)= { + QString hdr =3D (QString::number(i + 1)); + vertHeaders +=3D 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() "
Otherwise, click \'Cancel\'.
", name), i18n("Add Security Name")); if (rc =3D=3D KMessageBox::Cancel) { - m_csvDialog->comboBoxInv_securityName->clearEditText();/// + m_csvDialog->comboBoxInv_securityName->clearEditText(); m_csvDialog->comboBoxInv_securityName->setCurrentIndex(-1); } else { m_securityName =3D name; diff --git a/kmymoney/plugins/csvimport/investprocessing.h b/kmymoney/plugi= ns/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 reque= sted * start line value is saved. */ - void startLineChanged(); + void startLineChanged(int); = /** * This method is called when the user selects the end line. The request= ed @@ -311,6 +321,11 @@ private: */ void setCodecList(const QList &list); = + /** + * Called after rows have been dropped, to produce the (revised) vertica= l (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 =3D 0; m_columnTotalWidth =3D 0; + m_maxWidth =3D 0; m_mainHeight =3D 0; m_mainWidth =3D 0; m_priceColumn =3D 0; @@ -46,9 +47,9 @@ RedefineDlg::RedefineDlg() m_ret =3D 0; m_typeColumn =3D 0; = - m_price =3D 0; - m_quantity =3D 0; - m_amount =3D 0; + m_price =3D MyMoneyMoney(); + m_quantity =3D MyMoneyMoney(); + m_amount =3D MyMoneyMoney(); = m_typesList << "buy" << "sell" << "divx" << "reinvdiv" << "shrsin" << "s= hrsout"; = @@ -94,6 +95,7 @@ void RedefineDlg::displayLine(const QString& info) brush.setStyle(Qt::SolidPattern); int row; m_columnTotalWidth =3D 0; + m_maxWidth =3D 0; m_widget->tableWidget->setRowCount(2); for (int col =3D 0; col < m_maxCol; col++) { row =3D 1; @@ -106,8 +108,8 @@ void RedefineDlg::displayLine(const QString& info) if (m_typeColumn =3D=3D col) { item->setBackground(brush); } - m_columnTotalWidth +=3D m_widget->tableWidget->columnWidth(col); - +/// m_columnTotalWidth +=3D m_widget->tableWidget->columnWidth(col); +/// row =3D 0; if (col =3D=3D m_quantityColumn) { QTableWidgetItem *item =3D new QTableWidgetItem;// add items = to UI @@ -126,8 +128,19 @@ void RedefineDlg::displayLine(const QString& info) QTableWidgetItem *item =3D new QTableWidgetItem;// add items = to UI item->setText(i18n("Type")); m_widget->tableWidget->setItem(row, col, item); + } else if (col =3D=3D m_detailColumn) { + QTableWidgetItem *item =3D new QTableWidgetItem;// add items = to UI + item->setText(i18n("Detail")); + m_widget->tableWidget->setItem(row, col, item); } } + m_widget->tableWidget->resizeColumnsToContents(); + for (int col =3D 0; col < m_maxCol; col++) { + m_columnTotalWidth +=3D m_widget->tableWidget->columnWidth(col); + } + if (m_columnTotalWidth > m_maxWidth) { + m_maxWidth =3D m_columnTotalWidth; + } updateWindow(); } = @@ -273,22 +286,21 @@ void RedefineDlg::resizeEvent(QResizeEvent * event) { event->accept(); = - m_mainWidth =3D m_widget->verticalLayout->geometry().size().width() - 10; - m_mainHeight =3D m_widget->tableWidget->geometry().size().height(); +/// m_mainWidth =3D m_widget->verticalLayout->geometry().size().width() -= 10; +/// m_mainHeight =3D m_widget->tableWidget->geometry().size().height(); updateWindow(); } = void RedefineDlg::updateWindow() { - int w =3D m_widget->tableWidget->width(); - int hght =3D 4 + (m_widget->tableWidget->rowHeight(0) * 2); - hght +=3D m_widget->tableWidget->horizontalHeader()->height() + 2;// fr= ig factor for vert. headers? + int hght =3D 6 + (m_widget->tableWidget->rowHeight(0) * 2); + hght +=3D m_widget->tableWidget->horizontalHeader()->height();// frig f= actor for horiz. headers? = - if (m_columnTotalWidth > (m_mainWidth - 12)) - hght +=3D m_widget->tableWidget->horizontalScrollBar()->height() + 1;/= / ....and for hor. scroll bar + if (m_maxWidth > (m_mainWidth - 12)) { + hght +=3D m_widget->tableWidget->horizontalScrollBar()->height() - 2;/= / ....and for hor. scroll bar + } = m_widget->tableWidget->setFixedHeight(hght); - w =3D 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 =3D m_columnList[m_priceColumn].remove('"'); + m_price =3D MyMoneyMoney(m_columnList[m_priceColumn].remove('"')); if (m_quantityColumn < m_columnList.count())// Ensure this is valid co= lumn - m_quantity =3D m_columnList[m_quantityColumn].remove('"'); + m_quantity =3D MyMoneyMoney(m_columnList[m_quantityColumn].remove('"')= ); if (m_amountColumn < m_columnList.count())// Ensure this is valid colu= mn txt =3D m_columnList[m_amountColumn]; if ((txt.startsWith('"')) && (!txt.endsWith('"'))) { @@ -310,7 +322,7 @@ void RedefineDlg::convertValues() if (txt.contains(')')) { // replace negative ( ) with '-' txt =3D '-' + txt.remove(QRegExp("[(),]")); } - m_amount =3D txt; + m_amount =3D MyMoneyMoney(txt); } = void RedefineDlg::setAmountColumn(int col) diff --git a/kmymoney/plugins/csvimport/redefinedlg.h b/kmymoney/plugins/cs= vimport/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;