void MyMoneyAccountTest::testAssignmentConstructor() { MyMoneyAccount a; a.setAccountType(MyMoneyAccount::Checkings); a.setName("Account"); a.setInstitutionId("Inst1"); a.setDescription("Bla"); a.setNumber("assigned Number"); a.setValue("Key", "Value"); a.addAccountId("ChildAccount"); MyMoneyAccount b; b.setLastModified(QDate::currentDate()); b = a; QVERIFY(b.name() == "Account"); QVERIFY(b.institutionId() == "Inst1"); QVERIFY(b.accountType() == MyMoneyAccount::Checkings); QVERIFY(b.lastModified() == QDate()); QVERIFY(b.openingDate() == a.openingDate()); QVERIFY(b.description() == "Bla"); QVERIFY(b.number() == "assigned Number"); QVERIFY(b.value("Key") == "Value"); QVERIFY(b.accountList().count() == 1); QVERIFY(b.accountList()[0] == "ChildAccount"); }
void MyMoneyForecast::addFutureTransactions(void) { MyMoneyTransactionFilter filter; MyMoneyFile* file = MyMoneyFile::instance(); // collect and process all transactions that have already been entered but // are located in the future. filter.setDateFilter(forecastStartDate(), forecastEndDate()); filter.setReportAllSplits(false); QValueList<MyMoneyTransaction> transactions = file->transactionList(filter); QValueList<MyMoneyTransaction>::const_iterator it_t = transactions.begin(); for(; it_t != transactions.end(); ++it_t ) { const QValueList<MyMoneySplit>& splits = (*it_t).splits(); QValueList<MyMoneySplit>::const_iterator it_s = splits.begin(); for(; it_s != splits.end(); ++it_s ) { if(!(*it_s).shares().isZero()) { MyMoneyAccount acc = file->account((*it_s).accountId()); if(isForecastAccount(acc)) { dailyBalances balance; balance = m_accountList[acc.id()]; //if it is income, the balance is stored as negative number if(acc.accountType() == MyMoneyAccount::Income) { balance[(*it_t).postDate()] += ((*it_s).shares() * MyMoneyMoney(-1, 1)); } else { balance[(*it_t).postDate()] += (*it_s).shares(); } m_accountList[acc.id()] = balance; } } } } #if 0 QFile trcFile("forecast.csv"); trcFile.open(IO_WriteOnly); QTextStream s(&trcFile); { s << "Already present transactions\n"; QMap<QString, dailyBalances>::Iterator it_a; QMap<QString, QString>::ConstIterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); it_a = m_accountList.find(*it_n); s << "\"" << acc.name() << "\","; for(int i = 0; i < 90; ++i) { s << "\"" << (*it_a)[i].formatMoney("") << "\","; } s << "\n"; } } #endif }
QString CsvUtil::nameToId(const QString& name, MyMoneyAccount& parent) { // Adapted from KMyMoneyApp::createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal) // Needed to find/create category:sub-categories MyMoneyFile* file = MyMoneyFile::instance(); QString id = file->categoryToAccount(name, MyMoneyAccount::UnknownAccountType); // if it does not exist, we have to create it if (id.isEmpty()) { MyMoneyAccount newAccount; MyMoneyAccount parentAccount = parent; newAccount.setName(name) ; int pos; // check for ':' in the name and use it as separator for a hierarchy while ((pos = newAccount.name().indexOf(MyMoneyFile::AccountSeperator)) != -1) { QString part = newAccount.name().left(pos); QString remainder = newAccount.name().mid(pos + 1); const MyMoneyAccount& existingAccount = file->subAccountByName(parentAccount, part); if (existingAccount.id().isEmpty()) { newAccount.setName(part); newAccount.setAccountType(parentAccount.accountType()); file->addAccount(newAccount, parentAccount); parentAccount = newAccount; } else { parentAccount = existingAccount; } newAccount.setParentAccountId(QString()); // make sure, there's no parent newAccount.clearId(); // and no id set for adding newAccount.removeAccountIds(); // and no sub-account ids newAccount.setName(remainder); }//end while newAccount.setAccountType(parentAccount.accountType()); // make sure we have a currency. If none is assigned, we assume base currency if (newAccount.currencyId().isEmpty()) newAccount.setCurrencyId(file->baseCurrency().id()); file->addAccount(newAccount, parentAccount); id = newAccount.id(); } return id; }
void MyMoneyAccountTest::testEmptyConstructor() { MyMoneyAccount a; QVERIFY(a.id().isEmpty()); QVERIFY(a.name().isEmpty()); QVERIFY(a.accountType() == MyMoneyAccount::UnknownAccountType); QVERIFY(a.openingDate() == QDate()); QVERIFY(a.lastModified() == QDate()); QVERIFY(a.lastReconciliationDate() == QDate()); QVERIFY(a.accountList().count() == 0); QVERIFY(a.balance().isZero()); }
void MyMoneyQifWriter::writeCategoryEntry(QTextStream &s, const QString& accountId, const QString& leadIn) { MyMoneyAccount acc = MyMoneyFile::instance()->account(accountId); QString name = acc.name(); s << "N" << leadIn << name << endl; s << (MyMoneyAccount::accountGroup(acc.accountType()) == MyMoneyAccount::Expense ? "E" : "I") << endl; s << "^" << endl; QStringList list = acc.accountList(); QStringList::Iterator it; name += ":"; for(it = list.begin(); it != list.end(); ++it) { writeCategoryEntry(s, *it, name); } }
void CsvUtil::scanCategories(QString& id, const MyMoneyAccount& invAcc, const MyMoneyAccount& parentAccount, const QString& defaultName) { if (!m_scannedCategories) { previouslyUsedCategories(invAcc.id(), m_feeId, m_interestId); m_scannedCategories = true; } if (id.isEmpty()) { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyAccount acc = file->accountByName(defaultName); // if it does not exist, we have to create it if (acc.id().isEmpty()) { MyMoneyAccount parent = parentAccount; acc.setName(defaultName); acc.setAccountType(parent.accountType()); acc.setCurrencyId(parent.currencyId()); file->addAccount(acc, parent); } id = acc.id(); } }
void KForecastView::updateBudget(QTreeWidgetItem *item) { MyMoneySecurity currency; MyMoneyMoney tAmountMM; MyMoneyForecast forecast = item->data(0, ForecastRole).value<MyMoneyForecast>(); MyMoneyFile* file = MyMoneyFile::instance(); int it_c = 1; // iterator for the columns of the listview QDate forecastDate = forecast.forecastStartDate(); MyMoneyAccount account = item->data(0, AccountRole).value<MyMoneyAccount>(); if (account.isInvest()) { MyMoneySecurity underSecurity = file->security(account.currencyId()); currency = file->security(underSecurity.tradingCurrency()); } else { currency = file->security(account.currencyId()); } //iterate columns for (; forecastDate <= forecast.forecastEndDate(); forecastDate = forecastDate.addMonths(1), ++it_c) { MyMoneyMoney amountMM; amountMM = forecast.forecastBalance(account, forecastDate); if (account.accountType() == MyMoneyAccount::Expense) amountMM = -amountMM; tAmountMM += amountMM; setAmount(item, it_c, amountMM); setValue(item, it_c, amountMM, forecastDate); showAmount(item, it_c, amountMM, currency); } //set total column setAmount(item, it_c, tAmountMM); setValue(item, it_c, tAmountMM, forecast.forecastEndDate()); showAmount(item, it_c, tAmountMM, currency); }
void MyMoneyAccountTest::testSetFunctions() { MyMoneyAccount a; QDate today(QDate::currentDate()); QVERIFY(a.name().isEmpty()); QVERIFY(a.lastModified() == QDate()); QVERIFY(a.description().isEmpty()); a.setName("Account"); a.setInstitutionId("Institution1"); a.setLastModified(today); a.setDescription("Desc"); a.setNumber("123456"); a.setAccountType(MyMoneyAccount::MoneyMarket); QVERIFY(a.name() == "Account"); QVERIFY(a.institutionId() == "Institution1"); QVERIFY(a.lastModified() == today); QVERIFY(a.description() == "Desc"); QVERIFY(a.number() == "123456"); QVERIFY(a.accountType() == MyMoneyAccount::MoneyMarket); }
const MyMoneySplit KMyMoneyUtils::stockSplit(const MyMoneyTransaction& t) { QList<MyMoneySplit>::ConstIterator it_s; MyMoneySplit investmentAccountSplit; for (it_s = t.splits().begin(); it_s != t.splits().end(); ++it_s) { if (!(*it_s).accountId().isEmpty()) { MyMoneyAccount acc = MyMoneyFile::instance()->account((*it_s).accountId()); if (acc.isInvest()) { return *it_s; } // if we have a reference to an investment account, we remember it here if (acc.accountType() == MyMoneyAccount::Investment) investmentAccountSplit = *it_s; } } // if we haven't found a stock split, we see if we've seen // an investment account on the way. If so, we return it. if (!investmentAccountSplit.id().isEmpty()) return investmentAccountSplit; // if none was found, we return an empty split. return MyMoneySplit(); }
bool MyMoneyTemplate::addAccountStructure(QDomElement& parent, const MyMoneyAccount& acc) { QDomElement account = m_doc.createElement("account"); parent.appendChild(account); if (MyMoneyFile::instance()->isStandardAccount(acc.id())) account.setAttribute(QString("name"), QString()); else account.setAttribute(QString("name"), acc.name()); account.setAttribute(QString("type"), acc.accountType()); // FIXME: add tax flag stuff // any child accounts? if (acc.accountList().count() > 0) { QList<MyMoneyAccount> list; MyMoneyFile::instance()->accountList(list, acc.accountList(), false); QList<MyMoneyAccount>::Iterator it; for (it = list.begin(); it != list.end(); ++it) { addAccountStructure(account, *it); } } return true; }
void MyMoneyForecast::addScheduledTransactions (void) { MyMoneyFile* file = MyMoneyFile::instance(); // now process all the schedules that may have an impact QValueList<MyMoneySchedule> schedule; schedule = file->scheduleList("", MyMoneySchedule::TYPE_ANY, MyMoneySchedule::OCCUR_ANY, MyMoneySchedule::STYPE_ANY, QDate(), forecastEndDate()); if(schedule.count() > 0) { QValueList<MyMoneySchedule>::Iterator it; do { qBubbleSort(schedule); it = schedule.begin(); if(it == schedule.end()) break; if((*it).isFinished()) { schedule.erase(it); continue; } QDate date = (*it).nextPayment((*it).lastPayment()); if(!date.isValid()) { schedule.remove(it); continue; } QDate nextDate = (*it).adjustedNextPayment((*it).adjustedDate((*it).lastPayment(), (*it).weekendOption())); if (nextDate > forecastEndDate()) { // We're done with this schedule, let's move on to the next schedule.remove(it); continue; } // found the next schedule. process it MyMoneyAccount acc = (*it).account(); if(!acc.id().isEmpty()) { try { if(acc.accountType() != MyMoneyAccount::Investment) { MyMoneyTransaction t = (*it).transaction(); // only process the entry, if it is still active if(!(*it).isFinished() && nextDate != QDate()) { // make sure we have all 'starting balances' so that the autocalc works QValueList<MyMoneySplit>::const_iterator it_s; QMap<QString, MyMoneyMoney> balanceMap; for(it_s = t.splits().begin(); it_s != t.splits().end(); ++it_s ) { MyMoneyAccount acc = file->account((*it_s).accountId()); if(isForecastAccount(acc)) { // collect all overdues on the first day QDate forecastDate = nextDate; if(QDate::currentDate() >= nextDate) forecastDate = QDate::currentDate().addDays(1); dailyBalances balance; balance = m_accountList[acc.id()]; for(QDate f_day = QDate::currentDate(); f_day < forecastDate; ) { balanceMap[acc.id()] += m_accountList[acc.id()][f_day]; f_day = f_day.addDays(1); } } } // take care of the autoCalc stuff calculateAutoLoan(*it, t, balanceMap); // now add the splits to the balances for(it_s = t.splits().begin(); it_s != t.splits().end(); ++it_s ) { MyMoneyAccount acc = file->account((*it_s).accountId()); if(isForecastAccount(acc)) { dailyBalances balance; balance = m_accountList[acc.id()]; //int offset = QDate::currentDate().daysTo(nextDate); //if(offset <= 0) { // collect all overdues on the first day // offset = 1; //} // collect all overdues on the first day QDate forecastDate = nextDate; if(QDate::currentDate() >= nextDate) forecastDate = QDate::currentDate().addDays(1); if(acc.accountType() == MyMoneyAccount::Income) { balance[forecastDate] += ((*it_s).shares() * MyMoneyMoney(-1, 1)); } else { balance[forecastDate] += (*it_s).shares(); } m_accountList[acc.id()] = balance; } } } } (*it).setLastPayment(date); } catch(MyMoneyException* e) { kdDebug(2) << __func__ << " Schedule " << (*it).id() << " (" << (*it).name() << "): " << e->what() << endl; schedule.remove(it); delete e; } } else { // remove schedule from list schedule.remove(it); } } while(1); } #if 0 { s << "\n\nAdded scheduled transactions\n"; QMap<QString, dailyBalances>::Iterator it_a; QMap<QString, QString>::ConstIterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); it_a = m_accountList.find(*it_n); s << "\"" << acc.name() << "\","; for(int i = 0; i < 90; ++i) { s << "\"" << (*it_a)[i].formatMoney("") << "\","; } s << "\n"; } } #endif }
void MyMoneyForecast::calculateAccountTrendList() { MyMoneyFile* file = MyMoneyFile::instance(); int auxForecastTerms; int totalWeight = 0; //Calculate account trends QMap<QString, QString>::Iterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); m_accountTrendList[acc.id()][0] = MyMoneyMoney(0,1); // for today, the trend is 0 auxForecastTerms = forecastCycles(); if(skipOpeningDate()) { QDate openingDate; if(acc.accountType() == MyMoneyAccount::Stock) { MyMoneyAccount parentAccount = file->account(acc.parentAccountId()); openingDate = parentAccount.openingDate(); } else { openingDate = acc.openingDate(); } if(openingDate > historyStartDate() ) { //if acc opened after forecast period auxForecastTerms = 1 + ((openingDate.daysTo(historyEndDate()) + 1)/ accountsCycle()); // set forecastTerms to a lower value, to calculate only based on how long this account was opened } } switch (historyMethod()) { //moving average case 0: { for(int t_day = 1; t_day <= accountsCycle(); t_day++) m_accountTrendList[acc.id()][t_day] = accountMovingAverage(acc, t_day, auxForecastTerms); //moving average break; } //weighted moving average case 1: { //calculate total weight for moving average if(auxForecastTerms == forecastCycles()) { totalWeight = (auxForecastTerms * (auxForecastTerms + 1))/2; //totalWeight is the triangular number of auxForecastTerms } else { //if only taking a few periods, totalWeight is the sum of the weight for most recent periods for(int i = 1, w = forecastCycles(); i <= auxForecastTerms; ++i, --w) totalWeight += w; } for(int t_day = 1; t_day <= accountsCycle(); t_day++) m_accountTrendList[acc.id()][t_day] = accountWeightedMovingAverage(acc, t_day, totalWeight); break; } case 2: { //calculate mean term MyMoneyMoney meanTerms = MyMoneyMoney((auxForecastTerms * (auxForecastTerms + 1))/2, 1) / MyMoneyMoney(auxForecastTerms, 1); for(int t_day = 1; t_day <= accountsCycle(); t_day++) m_accountTrendList[acc.id()][t_day] = accountLinearRegression(acc, t_day, auxForecastTerms, meanTerms); break; } default: break; } } }
void MyMoneyForecast::setStartingBalance(const MyMoneyAccount &acc) { MyMoneyFile* file = MyMoneyFile::instance(); //Get current account balance if ( acc.isInvest() ) { //investments require special treatment //get the security id of that account MyMoneySecurity undersecurity = file->security ( acc.currencyId() ); //only do it if the security is not an actual currency if ( ! undersecurity.isCurrency() ) { //set the default value MyMoneyMoney rate = MyMoneyMoney ( 1, 1 ); //get te MyMoneyPrice price = file->price ( undersecurity.id(), undersecurity.tradingCurrency(), QDate::currentDate() ); if ( price.isValid() ) { rate = price.rate ( undersecurity.tradingCurrency() ); } m_accountList[acc.id()][QDate::currentDate()] = file->balance(acc.id(), QDate::currentDate()) * rate; } } else { m_accountList[acc.id()][QDate::currentDate()] = file->balance(acc.id(), QDate::currentDate()); } //if the method is linear regression, we have to add the opening balance to m_accountListPast if(forecastMethod() == eHistoric && historyMethod() == 2) { //FIXME workaround for stock opening dates QDate openingDate; if(acc.accountType() == MyMoneyAccount::Stock) { MyMoneyAccount parentAccount = file->account(acc.parentAccountId()); openingDate = parentAccount.openingDate(); } else { openingDate = acc.openingDate(); } //add opening balance only if it opened after the history start if(openingDate >= historyStartDate()) { MyMoneyMoney openingBalance; openingBalance = file->balance(acc.id(), openingDate); //calculate running sum for(QDate it_date = openingDate; it_date <= historyEndDate(); it_date = it_date.addDays(1) ) { //investments require special treatment if ( acc.isInvest() ) { //get the security id of that account MyMoneySecurity undersecurity = file->security ( acc.currencyId() ); //only do it if the security is not an actual currency if ( ! undersecurity.isCurrency() ) { //set the default value MyMoneyMoney rate = MyMoneyMoney ( 1, 1 ); //get the rate for that specific date MyMoneyPrice price = file->price ( undersecurity.id(), undersecurity.tradingCurrency(), it_date ); if ( price.isValid() ) { rate = price.rate ( undersecurity.tradingCurrency() ); } m_accountListPast[acc.id()][it_date] += openingBalance * rate; } } else { m_accountListPast[acc.id()][it_date] += openingBalance; } } } } }
void MyMoneyForecast::pastTransactions() { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyTransactionFilter filter; filter.setDateFilter(historyStartDate(), historyEndDate()); filter.setReportAllSplits(false); QValueList<MyMoneyTransaction> transactions = file->transactionList(filter); QValueList<MyMoneyTransaction>::const_iterator it_t = transactions.begin(); //Check past transactions for(; it_t != transactions.end(); ++it_t ) { const QValueList<MyMoneySplit>& splits = (*it_t).splits(); QValueList<MyMoneySplit>::const_iterator it_s = splits.begin(); for(; it_s != splits.end(); ++it_s ) { if(!(*it_s).shares().isZero()) { MyMoneyAccount acc = file->account((*it_s).accountId()); //workaround for stock accounts which have faulty opening dates QDate openingDate; if(acc.accountType() == MyMoneyAccount::Stock) { MyMoneyAccount parentAccount = file->account(acc.parentAccountId()); openingDate = parentAccount.openingDate(); } else { openingDate = acc.openingDate(); } if(isForecastAccount(acc) //If it is one of the accounts we are checking, add the amount of the transaction && ( (openingDate < (*it_t).postDate() && skipOpeningDate()) || !skipOpeningDate() ) ){ //don't take the opening day of the account to calculate balance dailyBalances balance; //FIXME deal with leap years balance = m_accountListPast[acc.id()]; if(acc.accountType() == MyMoneyAccount::Income) {//if it is income, the balance is stored as negative number balance[(*it_t).postDate()] += ((*it_s).shares() * MyMoneyMoney(-1, 1)); } else { balance[(*it_t).postDate()] += (*it_s).shares(); } // check if this is a new account for us m_accountListPast[acc.id()] = balance; } } } } //purge those accounts with no transactions on the period if(isIncludingUnusedAccounts() == false) purgeForecastAccountsList(m_accountListPast); //calculate running sum QMap<QString, QString>::Iterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); m_accountListPast[acc.id()][historyStartDate().addDays(-1)] = file->balance(acc.id(), historyStartDate().addDays(-1)); for(QDate it_date = historyStartDate(); it_date <= historyEndDate(); ) { m_accountListPast[acc.id()][it_date] += m_accountListPast[acc.id()][it_date.addDays(-1)]; //Running sum it_date = it_date.addDays(1); } } //adjust value of investments to deep currency for ( it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n ) { MyMoneyAccount acc = file->account ( *it_n ); if ( acc.isInvest() ) { //get the id of the security for that account MyMoneySecurity undersecurity = file->security ( acc.currencyId() ); if ( ! undersecurity.isCurrency() ) //only do it if the security is not an actual currency { MyMoneyMoney rate = MyMoneyMoney ( 1, 1 ); //set the default value MyMoneyPrice price; for ( QDate it_date = historyStartDate().addDays(-1) ; it_date <= historyEndDate();) { //get the price for the tradingCurrency that day price = file->price ( undersecurity.id(), undersecurity.tradingCurrency(), it_date ); if ( price.isValid() ) { rate = price.rate ( undersecurity.tradingCurrency() ); } //value is the amount of shares multiplied by the rate of the deep currency m_accountListPast[acc.id() ][it_date] = m_accountListPast[acc.id() ][it_date] * rate; it_date = it_date.addDays(1); } } } } }
void CsvUtil::createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal) { MyMoneyFile* file = MyMoneyFile::instance(); // make sure we have a currency. If none is assigned, we assume base currency if (newAccount.currencyId().isEmpty()) newAccount.setCurrencyId(file->baseCurrency().id()); MyMoneyFileTransaction ft; try { int pos; // check for ':' in the name and use it as separator for a hierarchy while ((pos = newAccount.name().indexOf(MyMoneyFile::AccountSeperator)) != -1) { QString part = newAccount.name().left(pos); QString remainder = newAccount.name().mid(pos + 1); const MyMoneyAccount& existingAccount = file->subAccountByName(parentAccount, part); if (existingAccount.id().isEmpty()) { newAccount.setName(part); file->addAccount(newAccount, parentAccount); parentAccount = newAccount; } else { parentAccount = existingAccount; } newAccount.setParentAccountId(QString()); // make sure, there's no parent newAccount.clearId(); // and no id set for adding newAccount.removeAccountIds(); // and no sub-account ids newAccount.setName(remainder); } const MyMoneySecurity& sec = file->security(newAccount.currencyId()); // Check the opening balance if (openingBal.isPositive() && newAccount.accountGroup() == MyMoneyAccount::Liability) { QString message = i18n("This account is a liability and if the " "opening balance represents money owed, then it should be negative. " "Negate the amount?\n\n" "Please click Yes to change the opening balance to %1,\n" "Please click No to leave the amount as %2,\n" "Please click Cancel to abort the account creation." , MyMoneyUtils::formatMoney(-openingBal, newAccount, sec) , MyMoneyUtils::formatMoney(openingBal, newAccount, sec)); int ans = KMessageBox::questionYesNoCancel(0, message); if (ans == KMessageBox::Yes) { openingBal = -openingBal; } else if (ans == KMessageBox::Cancel) return; } file->addAccount(newAccount, parentAccount); if (newAccount.accountType() == MyMoneyAccount::Investment && !brokerageAccount.name().isEmpty()) { file->addAccount(brokerageAccount, parentAccount); // set a link from the investment account to the brokerage account file->modifyAccount(newAccount); file->createOpeningBalanceTransaction(brokerageAccount, openingBal); } else file->createOpeningBalanceTransaction(newAccount, openingBal); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::information(0, i18n("Unable to add account: %1", e.what())); } }
KNewAccountDlg::KNewAccountDlg(const MyMoneyAccount& account, bool isEditing, bool categoryEditor, QWidget *parent, const char *name, const QString& title) : KNewAccountDlgDecl(parent,name,true), m_account(account), m_bSelectedParentAccount(false), m_categoryEditor(categoryEditor), m_isEditing(isEditing) { QString columnName = ( (categoryEditor) ? i18n("Categories") : i18n("Accounts") ); m_qlistviewParentAccounts->setRootIsDecorated(true); m_qlistviewParentAccounts->setAllColumnsShowFocus(true); m_qlistviewParentAccounts->setSectionHeader(columnName); m_qlistviewParentAccounts->setMultiSelection(false); m_qlistviewParentAccounts->header()->setResizeEnabled(true); m_qlistviewParentAccounts->setColumnWidthMode(0, QListView::Maximum); m_qlistviewParentAccounts->setEnabled(false); // never show the horizontal scroll bar m_qlistviewParentAccounts->setHScrollBarMode(QScrollView::AlwaysOff); m_subAccountLabel->setText(i18n("Is a sub account")); m_qlistviewParentAccounts->header()->setFont(KMyMoneyGlobalSettings::listHeaderFont()); accountNameEdit->setText(account.name()); descriptionEdit->setText(account.description()); typeCombo->setEnabled(true); MyMoneyFile *file = MyMoneyFile::instance(); // load the price mode combo m_priceMode->insertItem(i18n("default price mode", "<default>"), 0); m_priceMode->insertItem(i18n("Price per share"), 1); m_priceMode->insertItem(i18n("Total for all shares"), 2); int priceMode = 0; if(m_account.accountType() == MyMoneyAccount::Investment) { m_priceMode->setEnabled(true); if(!m_account.value("priceMode").isEmpty()) priceMode = m_account.value("priceMode").toInt(); } m_priceMode->setCurrentItem(priceMode); bool haveMinBalance = false; bool haveMaxCredit = false; if (categoryEditor) { // get rid of the tabs that are not used for categories QWidget* tab = m_tab->page(m_tab->indexOf(m_institutionTab)); if(tab) m_tab->removePage(tab); tab = m_tab->page(m_tab->indexOf(m_limitsTab)); if(tab) m_tab->removePage(tab); //m_qlistviewParentAccounts->setEnabled(true); startDateEdit->setEnabled(false); accountNoEdit->setEnabled(false); m_institutionBox->hide(); m_qcheckboxNoVat->hide(); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Income)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Expense)); // Hardcoded but acceptable switch (account.accountType()) { case MyMoneyAccount::Income: typeCombo->setCurrentItem(0); break; case MyMoneyAccount::Expense: default: typeCombo->setCurrentItem(1); break; } m_currency->setEnabled(true); if (m_isEditing) { typeCombo->setEnabled(false); m_currency->setDisabled(MyMoneyFile::instance()->isReferenced(m_account)); } m_qcheckboxPreferred->hide(); m_qcheckboxTax->setChecked(account.value("Tax") == "Yes"); loadVatAccounts(); } else { // get rid of the tabs that are not used for accounts QWidget* taxtab = m_tab->page(m_tab->indexOf(m_taxTab)); if (taxtab) { if(m_account.isAssetLiability()) { m_vatCategory->setText(i18n( "VAT account")); m_vatAssignmentFrame->hide(); m_qcheckboxTax->setChecked(account.value("Tax") == "Yes"); } else { m_tab->removePage(taxtab); } } switch(m_account.accountType()) { case MyMoneyAccount::Savings: case MyMoneyAccount::Cash: haveMinBalance = true; break; case MyMoneyAccount::Checkings: haveMinBalance = true; haveMaxCredit = true; break; case MyMoneyAccount::CreditCard: haveMaxCredit = true; break; default: // no limit available, so we might get rid of the tab QWidget* tab = m_tab->page(m_tab->indexOf(m_limitsTab)); if(tab) m_tab->removePage(tab); // don't try to hide the widgets we just wiped // in the next step haveMaxCredit = haveMinBalance = true; break; } if(!haveMaxCredit) { m_maxCreditLabel->setEnabled(false); m_maxCreditLabel->hide(); m_maxCreditEarlyEdit->hide(); m_maxCreditAbsoluteEdit->hide(); } if(!haveMinBalance) { m_minBalanceLabel->setEnabled(false); m_minBalanceLabel->hide(); m_minBalanceEarlyEdit->hide(); m_minBalanceAbsoluteEdit->hide(); } typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Checkings)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Savings)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Cash)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::CreditCard)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Loan)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Investment)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Asset)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Liability)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Stock)); /* typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::CertificateDep)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::MoneyMarket)); typeCombo->insertItem(KMyMoneyUtils::accountTypeToString(MyMoneyAccount::Currency)); */ // Hardcoded but acceptable switch (account.accountType()) { default: case MyMoneyAccount::Checkings: typeCombo->setCurrentItem(0); break; case MyMoneyAccount::Savings: typeCombo->setCurrentItem(1); break; case MyMoneyAccount::Cash: typeCombo->setCurrentItem(2); break; case MyMoneyAccount::CreditCard: typeCombo->setCurrentItem(3); break; case MyMoneyAccount::Loan: typeCombo->setCurrentItem(4); break; case MyMoneyAccount::Investment: typeCombo->setCurrentItem(5); break; case MyMoneyAccount::Asset: typeCombo->setCurrentItem(6); break; case MyMoneyAccount::Liability: typeCombo->setCurrentItem(7); break; case MyMoneyAccount::Stock: m_institutionBox->hide(); typeCombo->setCurrentItem(8); break; /* case MyMoneyAccount::CertificateDep: typeCombo->setCurrentItem(5); break; case MyMoneyAccount::MoneyMarket: typeCombo->setCurrentItem(7); break; case MyMoneyAccount::Currency: typeCombo->setCurrentItem(8); break; */ } if(!m_account.openingDate().isValid()) m_account.setOpeningDate(QDate::currentDate()); startDateEdit->setDate(m_account.openingDate()); accountNoEdit->setText(account.number()); m_qcheckboxPreferred->setChecked(account.value("PreferredAccount") == "Yes"); m_qcheckboxNoVat->setChecked(account.value("NoVat") == "Yes"); loadKVP("iban", ibanEdit); loadKVP("minBalanceAbsolute", m_minBalanceAbsoluteEdit); loadKVP("minBalanceEarly", m_minBalanceEarlyEdit); loadKVP("maxCreditAbsolute", m_maxCreditAbsoluteEdit); loadKVP("maxCreditEarly", m_maxCreditEarlyEdit); // reverse the sign for display purposes if(!m_maxCreditAbsoluteEdit->lineedit()->text().isEmpty()) m_maxCreditAbsoluteEdit->setValue(m_maxCreditAbsoluteEdit->value()*MyMoneyMoney(-1,1)); if(!m_maxCreditEarlyEdit->lineedit()->text().isEmpty()) m_maxCreditEarlyEdit->setValue(m_maxCreditEarlyEdit->value()*MyMoneyMoney(-1,1)); loadKVP("lastNumberUsed", m_lastCheckNumberUsed); // we do not allow to change the account type once an account // was created. Same applies to currency if it is referenced. if (m_isEditing) { typeCombo->setEnabled(false); m_currency->setDisabled(MyMoneyFile::instance()->isReferenced(m_account)); } if(m_account.isInvest()) { typeCombo->setEnabled(false); m_qcheckboxPreferred->hide(); m_currencyText->hide(); m_currency->hide(); } else { // use the old field and override a possible new value if(!MyMoneyMoney(account.value("minimumBalance")).isZero()) { m_minBalanceAbsoluteEdit->setValue(MyMoneyMoney(account.value("minimumBalance"))); } } // m_qcheckboxTax->hide(); TODO should only be visible for VAT category/account } m_currency->setSecurity(file->currency(account.currencyId())); // Load the institutions // then the accounts QString institutionName; try { if (m_isEditing && !account.institutionId().isEmpty()) institutionName = file->institution(account.institutionId()).name(); else institutionName = QString(); } catch (MyMoneyException *e) { qDebug("exception in init for account dialog: %s", e->what().latin1()); delete e; } initParentWidget(account.parentAccountId(), account.id()); if(m_account.isInvest()) m_qlistviewParentAccounts->setEnabled(false); if (!categoryEditor) slotLoadInstitutions(institutionName); accountNameEdit->setFocus(); if (title) setCaption(title); // load button icons KIconLoader* il = KGlobal::iconLoader(); cancelButton->setGuiItem(KStdGuiItem::cancel()); createButton->setGuiItem(KStdGuiItem::ok()); connect(cancelButton, SIGNAL(clicked()), SLOT(reject())); connect(createButton, SIGNAL(clicked()), this, SLOT(okClicked())); connect(m_qlistviewParentAccounts, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(slotSelectionChanged(QListViewItem*))); connect(m_qbuttonNew, SIGNAL(clicked()), this, SLOT(slotNewClicked())); connect(typeCombo, SIGNAL(activated(const QString&)), this, SLOT(slotAccountTypeChanged(const QString&))); connect(accountNameEdit, SIGNAL(textChanged(const QString&)), this, SLOT(slotCheckFinished())); connect(m_vatCategory, SIGNAL(toggled(bool)), this, SLOT(slotVatChanged(bool))); connect(m_vatAssignment, SIGNAL(toggled(bool)), this, SLOT(slotVatAssignmentChanged(bool))); connect(m_vatCategory, SIGNAL(toggled(bool)), this, SLOT(slotCheckFinished())); connect(m_vatAssignment, SIGNAL(toggled(bool)), this, SLOT(slotCheckFinished())); connect(m_vatRate, SIGNAL(textChanged(const QString&)), this, SLOT(slotCheckFinished())); connect(m_vatAccount, SIGNAL(stateChanged()), this, SLOT(slotCheckFinished())); connect(m_minBalanceEarlyEdit, SIGNAL(valueChanged(const QString&)), this, SLOT(slotAdjustMinBalanceAbsoluteEdit(const QString&))); connect(m_minBalanceAbsoluteEdit, SIGNAL(valueChanged(const QString&)), this, SLOT(slotAdjustMinBalanceEarlyEdit(const QString&))); connect(m_maxCreditEarlyEdit, SIGNAL(valueChanged(const QString&)), this, SLOT(slotAdjustMaxCreditAbsoluteEdit(const QString&))); connect(m_maxCreditAbsoluteEdit, SIGNAL(valueChanged(const QString&)), this, SLOT(slotAdjustMaxCreditEarlyEdit(const QString&))); connect(m_qcomboboxInstitutions, SIGNAL(activated(const QString&)), this, SLOT(slotLoadInstitutions(const QString&))); m_vatCategory->setChecked(false); m_vatAssignment->setChecked(false); // make sure our account does not have an id and no parent assigned // and certainly no children in case we create a new account if(!m_isEditing) { m_account.clearId(); m_account.setParentAccountId(QString()); QStringList::ConstIterator it; while((it = m_account.accountList().begin()) != m_account.accountList().end()) m_account.removeAccountId(*it); if(m_parentItem == 0) { // force loading of initial parent m_account.setAccountType(MyMoneyAccount::UnknownAccountType); MyMoneyAccount::_accountTypeE type = account.accountType(); if(type == MyMoneyAccount::UnknownAccountType) type = MyMoneyAccount::Checkings; slotAccountTypeChanged(KMyMoneyUtils::accountTypeToString(type)); } } else { if(!m_account.value("VatRate").isEmpty()) { m_vatCategory->setChecked(true); m_vatRate->setValue(MyMoneyMoney(m_account.value("VatRate"))*MyMoneyMoney(100,1)); } else { if(!m_account.value("VatAccount").isEmpty()) { QString accId = m_account.value("VatAccount").latin1(); try { // make sure account exists MyMoneyFile::instance()->account(accId); m_vatAssignment->setChecked(true); m_vatAccount->setSelected(accId); m_grossAmount->setChecked(true); if(m_account.value("VatAmount") == "Net") m_netAmount->setChecked(true); } catch(MyMoneyException *e) { delete e; } } } } slotVatChanged(m_vatCategory->isChecked()); slotVatAssignmentChanged(m_vatAssignment->isChecked()); slotCheckFinished(); kMandatoryFieldGroup* requiredFields = new kMandatoryFieldGroup (this); requiredFields->setOkButton(createButton); // button to be enabled when all fields present requiredFields->add(accountNameEdit); // using a timeout is the only way, I got the 'ensureItemVisible' // working when creating the dialog. I assume, this // has something to do with the delayed update of the display somehow. QTimer::singleShot(50, this, SLOT(timerDone())); }