diff --git a/kmymoney/kmymoney.cpp b/kmymoney/kmymoney.cpp index 030a1e4fd..8cdc86ef2 100644 --- a/kmymoney/kmymoney.cpp +++ b/kmymoney/kmymoney.cpp @@ -1,7592 +1,7595 @@ /*************************************************************************** kmymoney.cpp ------------------- copyright : (C) 2000 by Michael Edwardes (C) 2007 by Thomas Baumgart ****************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "config-kmymoney.h" #include "kmymoney.h" // ---------------------------------------------------------------------------- // Std C++ / STL Includes #include #include #include // ---------------------------------------------------------------------------- // QT Includes #include #include // only for performance tests #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include // ---------------------------------------------------------------------------- // KDE Includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef KF5Holidays_FOUND #include #include #endif // ---------------------------------------------------------------------------- // Project Includes #include "kmymoneyglobalsettings.h" #include "kmymoneyadaptor.h" #include "dialogs/settings/ksettingskmymoney.h" #include "dialogs/kbackupdlg.h" #include "dialogs/kenterscheduledlg.h" #include "dialogs/kconfirmmanualenterdlg.h" #include "dialogs/kmymoneypricedlg.h" #include "dialogs/kcurrencyeditdlg.h" #include "dialogs/kequitypriceupdatedlg.h" #include "dialogs/kmymoneyfileinfodlg.h" #include "dialogs/kfindtransactiondlg.h" #include "dialogs/knewbankdlg.h" #include "wizards/newinvestmentwizard/knewinvestmentwizard.h" #include "dialogs/knewaccountdlg.h" #include "dialogs/editpersonaldatadlg.h" #include "dialogs/kselectdatabasedlg.h" #include "dialogs/kcurrencycalculator.h" #include "dialogs/keditscheduledlg.h" #include "wizards/newloanwizard/keditloanwizard.h" #include "dialogs/kpayeereassigndlg.h" #include "dialogs/ktagreassigndlg.h" #include "dialogs/kcategoryreassigndlg.h" #include "wizards/endingbalancedlg/kendingbalancedlg.h" #include "dialogs/kbalancechartdlg.h" #include "dialogs/kgeneratesqldlg.h" #include "dialogs/kloadtemplatedlg.h" #include "dialogs/kgpgkeyselectiondlg.h" #include "dialogs/ktemplateexportdlg.h" #include "dialogs/transactionmatcher.h" #include "wizards/newuserwizard/knewuserwizard.h" #include "wizards/newaccountwizard/knewaccountwizard.h" #include "dialogs/kbalancewarning.h" +#include "widgets/kmymoneyaccountselector.h" +#include "widgets/kmymoneypayeecombo.h" #include "widgets/onlinejobmessagesview.h" #include "widgets/kmymoneymvccombo.h" #include "views/kmymoneyview.h" #include "views/konlinejoboutbox.h" #include "models/onlinejobmessagesmodel.h" #include "mymoney/mymoneyobject.h" #include "mymoney/mymoneyfile.h" #include "mymoney/mymoneyinstitution.h" #include "mymoney/mymoneyaccount.h" #include "mymoney/mymoneyaccountloan.h" #include "mymoney/mymoneysecurity.h" #include "mymoney/mymoneypayee.h" #include "mymoney/mymoneytag.h" #include "mymoney/mymoneybudget.h" #include "mymoney/mymoneysplit.h" #include "mymoney/mymoneyutils.h" #include "mymoney/mymoneystatement.h" #include "mymoney/storage/mymoneystoragedump.h" #include "mymoney/storage/imymoneystorage.h" #include "mymoney/mymoneyforecast.h" #include "mymoney/onlinejobmessage.h" #include "converter/mymoneystatementreader.h" #include "converter/mymoneytemplate.h" #include "plugins/interfaces/kmmviewinterface.h" #include "plugins/interfaces/kmmstatementinterface.h" #include "plugins/interfaces/kmmimportinterface.h" #include "plugins/interfaceloader.h" #include "plugins/onlinepluginextended.h" #include "pluginloader.h" #include "tasks/credittransfer.h" #include "icons/icons.h" #include "misc/webconnect.h" #include "storage/imymoneyserialize.h" #include "storage/mymoneystoragesql.h" #include #include "transactioneditor.h" #include "konlinetransferform.h" #include #include #include "kmymoneyutils.h" #include "kcreditswindow.h" #include "ledgerdelegate.h" #include "storageenums.h" #include "mymoneyenums.h" #include "dialogenums.h" #include "misc/platformtools.h" using namespace Icons; static constexpr char recoveryKeyId[] = "59B0F826D2B08440"; // define the default period to warn about an expiring recoverkey to 30 days // but allows to override this setting during build time #ifndef RECOVER_KEY_EXPIRATION_WARNING #define RECOVER_KEY_EXPIRATION_WARNING 30 #endif const QHash KMyMoneyApp::s_Actions { {Action::FileOpenDatabase, QStringLiteral("open_database")}, {Action::FileSaveAsDatabase, QStringLiteral("saveas_database")}, {Action::FileBackup, QStringLiteral("file_backup")}, {Action::FileImportGNC, QStringLiteral("file_import_gnc")}, {Action::FileImportStatement, QStringLiteral("file_import_statement")}, {Action::FileImportTemplate, QStringLiteral("file_import_template")}, {Action::FileExportTemplate, QStringLiteral("file_export_template")}, {Action::FilePersonalData, QStringLiteral("view_personal_data")}, #ifdef KMM_DEBUG {Action::FileDump, QStringLiteral("file_dump")}, #endif {Action::FileInformation, QStringLiteral("view_file_info")}, {Action::EditFindTransaction, QStringLiteral("edit_find_transaction")}, {Action::ViewTransactionDetail, QStringLiteral("view_show_transaction_detail")}, {Action::ViewHideReconciled, QStringLiteral("view_hide_reconciled_transactions")}, {Action::ViewHideCategories, QStringLiteral("view_hide_unused_categories")}, {Action::ViewShowAll, QStringLiteral("view_show_all_accounts")}, {Action::InstitutionNew, QStringLiteral("institution_new")}, {Action::InstitutionEdit, QStringLiteral("institution_edit")}, {Action::InstitutionDelete, QStringLiteral("institution_delete")}, {Action::AccountNew, QStringLiteral("account_new")}, {Action::AccountOpen, QStringLiteral("account_open")}, {Action::AccountStartReconciliation, QStringLiteral("account_reconcile")}, {Action::AccountFinishReconciliation, QStringLiteral("account_reconcile_finish")}, {Action::AccountPostponeReconciliation, QStringLiteral("account_reconcile_postpone")}, {Action::AccountEdit, QStringLiteral("account_edit")}, {Action::AccountDelete, QStringLiteral("account_delete")}, {Action::AccountClose, QStringLiteral("account_close")}, {Action::AccountReopen, QStringLiteral("account_reopen")}, {Action::AccountTransactionReport, QStringLiteral("account_transaction_report")}, {Action::AccountBalanceChart, QStringLiteral("account_chart")}, {Action::AccountOnlineMap, QStringLiteral("account_online_map")}, {Action::AccountOnlineUnmap, QStringLiteral("account_online_unmap")}, {Action::AccountUpdateMenu, QStringLiteral("account_online_update_menu")}, {Action::AccountUpdate, QStringLiteral("account_online_update")}, {Action::AccountUpdateAll, QStringLiteral("account_online_update_all")}, {Action::AccountCreditTransfer, QStringLiteral("account_online_new_credit_transfer")}, {Action::CategoryNew, QStringLiteral("category_new")}, {Action::CategoryEdit, QStringLiteral("category_edit")}, {Action::CategoryDelete, QStringLiteral("category_delete")}, {Action::ToolCurrencies, QStringLiteral("tools_currency_editor")}, {Action::ToolPrices, QStringLiteral("tools_price_editor")}, {Action::ToolUpdatePrices, QStringLiteral("tools_update_prices")}, {Action::ToolConsistency, QStringLiteral("tools_consistency_check")}, {Action::ToolPerformance, QStringLiteral("tools_performancetest")}, {Action::ToolSQL, QStringLiteral("tools_generate_sql")}, {Action::ToolCalculator, QStringLiteral("tools_kcalc")}, {Action::SettingsAllMessages, QStringLiteral("settings_enable_messages")}, {Action::HelpShow, QStringLiteral("help_show_tip")}, {Action::TransactionNew, QStringLiteral("transaction_new")}, {Action::TransactionEdit, QStringLiteral("transaction_edit")}, {Action::TransactionEnter, QStringLiteral("transaction_enter")}, {Action::TransactionEditSplits, QStringLiteral("transaction_editsplits")}, {Action::TransactionCancel, QStringLiteral("transaction_cancel")}, {Action::TransactionDelete, QStringLiteral("transaction_delete")}, {Action::TransactionDuplicate, QStringLiteral("transaction_duplicate")}, {Action::TransactionMatch, QStringLiteral("transaction_match")}, {Action::TransactionAccept, QStringLiteral("transaction_accept")}, {Action::TransactionToggleReconciled, QStringLiteral("transaction_mark_toggle")}, {Action::TransactionToggleCleared, QStringLiteral("transaction_mark_cleared")}, {Action::TransactionReconciled, QStringLiteral("transaction_mark_reconciled")}, {Action::TransactionNotReconciled, QStringLiteral("transaction_mark_notreconciled")}, {Action::TransactionSelectAll, QStringLiteral("transaction_select_all")}, {Action::TransactionGoToAccount, QStringLiteral("transaction_goto_account")}, {Action::TransactionGoToPayee, QStringLiteral("transaction_goto_payee")}, {Action::TransactionCreateSchedule, QStringLiteral("transaction_create_schedule")}, {Action::TransactionAssignNumber, QStringLiteral("transaction_assign_number")}, {Action::TransactionCombine, QStringLiteral("transaction_combine")}, {Action::TransactionCopySplits, QStringLiteral("transaction_copy_splits")}, {Action::TransactionMoveMenu, QStringLiteral("transaction_move_menu")}, {Action::TransactionMarkMenu, QStringLiteral("transaction_mark_menu")}, {Action::TransactionContextMarkMenu, QStringLiteral("transaction_context_mark_menu")}, {Action::InvestmentNew, QStringLiteral("investment_new")}, {Action::InvestmentEdit, QStringLiteral("investment_edit")}, {Action::InvestmentDelete, QStringLiteral("investment_delete")}, {Action::InvestmentOnlinePrice, QStringLiteral("investment_online_price_update")}, {Action::InvestmentManualPrice, QStringLiteral("investment_manual_price_update")}, {Action::ScheduleNew, QStringLiteral("schedule_new")}, {Action::ScheduleEdit, QStringLiteral("schedule_edit")}, {Action::ScheduleDelete, QStringLiteral("schedule_delete")}, {Action::ScheduleDuplicate, QStringLiteral("schedule_duplicate")}, {Action::ScheduleEnter, QStringLiteral("schedule_enter")}, {Action::ScheduleSkip, QStringLiteral("schedule_skip")}, {Action::PayeeNew, QStringLiteral("payee_new")}, {Action::PayeeRename, QStringLiteral("payee_rename")}, {Action::PayeeDelete, QStringLiteral("payee_delete")}, {Action::PayeeMerge, QStringLiteral("payee_merge")}, {Action::TagNew, QStringLiteral("tag_new")}, {Action::TagRename, QStringLiteral("tag_rename")}, {Action::TagDelete, QStringLiteral("tag_delete")}, {Action::BudgetNew, QStringLiteral("budget_new")}, {Action::BudgetRename, QStringLiteral("budget_rename")}, {Action::BudgetDelete, QStringLiteral("budget_delete")}, {Action::BudgetCopy, QStringLiteral("budget_copy")}, {Action::BudgetChangeYear, QStringLiteral("budget_change_year")}, {Action::BudgetForecast, QStringLiteral("budget_forecast")}, {Action::CurrencyNew, QStringLiteral("currency_new")}, {Action::CurrencyRename, QStringLiteral("currency_rename")}, {Action::CurrencyDelete, QStringLiteral("currency_delete")}, {Action::CurrencySetBase, QStringLiteral("currency_setbase")}, {Action::PriceNew, QStringLiteral("price_new")}, {Action::PriceEdit, QStringLiteral("price_edit")}, {Action::PriceUpdate, QStringLiteral("price_update")}, {Action::PriceDelete, QStringLiteral("price_delete")}, #ifdef KMM_DEBUG {Action::WizardNewUser, QStringLiteral("new_user_wizard")}, {Action::DebugTraces, QStringLiteral("debug_traces")}, #endif {Action::DebugTimers, QStringLiteral("debug_timers")}, {Action::OnlineJobDelete, QStringLiteral("onlinejob_delete")}, {Action::OnlineJobEdit, QStringLiteral("onlinejob_edit")}, {Action::OnlineJobLog, QStringLiteral("onlinejob_log")}, }; enum backupStateE { BACKUP_IDLE = 0, BACKUP_MOUNTING, BACKUP_COPYING, BACKUP_UNMOUNTING }; class KMyMoneyApp::Private { public: Private(KMyMoneyApp *app) : q(app), m_ft(0), m_moveToAccountSelector(0), m_statementXMLindex(0), m_balanceWarning(0), m_collectingStatements(false), m_pluginLoader(0), m_backupResult(0), m_backupMount(0), m_ignoreBackupExitCode(false), m_myMoneyView(0), m_progressBar(0), m_smtReader(0), m_searchDlg(0), m_autoSaveTimer(0), m_progressTimer(0), m_inAutoSaving(false), m_transactionEditor(0), m_endingBalanceDlg(0), m_saveEncrypted(0), m_additionalKeyLabel(0), m_additionalKeyButton(0), m_recentFiles(0), #ifdef KF5Holidays_FOUND m_holidayRegion(0), #endif m_applicationIsReady(true), m_webConnect(new WebConnect(app)) { // since the days of the week are from 1 to 7, // and a day of the week is used to index this bit array, // resize the array to 8 elements (element 0 is left unused) m_processingDays.resize(8); } void closeFile(); void unlinkStatementXML(); void moveInvestmentTransaction(const QString& fromId, const QString& toId, const MyMoneyTransaction& t); QList > automaticReconciliation(const MyMoneyAccount &account, const QList > &transactions, const MyMoneyMoney &amount); /** * The public interface. */ KMyMoneyApp * const q; MyMoneyFileTransaction* m_ft; KMyMoneyAccountSelector* m_moveToAccountSelector; int m_statementXMLindex; KBalanceWarning* m_balanceWarning; bool m_collectingStatements; QStringList m_statementResults; KMyMoneyPlugin::PluginLoader* m_pluginLoader; QString m_lastPayeeEnteredId; /** the configuration object of the application */ KSharedConfigPtr m_config; /** * @brief List of all plugged plugins * * The key is the file name of the plugin. */ QMap m_plugins; /** * @brief List of plugged importer plugins * * The key is the objectName of the plugin. */ QMap m_importerPlugins; /** * @brief List of plugged online plugins * * The key is the objectName of the plugin. */ QMap m_onlinePlugins; /** * The following variable represents the state while crafting a backup. * It can have the following values * * - IDLE: the default value if not performing a backup * - MOUNTING: when a mount command has been issued * - COPYING: when a copy command has been issued * - UNMOUNTING: when an unmount command has been issued */ backupStateE m_backupState; /** * This variable keeps the result of the backup operation. */ int m_backupResult; /** * This variable is set, when the user selected to mount/unmount * the backup volume. */ bool m_backupMount; /** * Flag for internal run control */ bool m_ignoreBackupExitCode; KProcess m_proc; /// A pointer to the view holding the tabs. KMyMoneyView *m_myMoneyView; /// The URL of the file currently being edited when open. QUrl m_fileName; bool m_startDialog; QString m_mountpoint; QProgressBar* m_progressBar; QTime m_lastUpdate; QLabel* m_statusLabel; MyMoneyStatementReader* m_smtReader; // allows multiple imports to be launched trough web connect and to be executed sequentially QQueue m_importUrlsQueue; KFindTransactionDlg* m_searchDlg; QObject* m_pluginInterface; MyMoneyAccount m_selectedAccount; MyMoneyAccount m_reconciliationAccount; MyMoneyAccount m_selectedInvestment; MyMoneyInstitution m_selectedInstitution; MyMoneySchedule m_selectedSchedule; MyMoneySecurity m_selectedCurrency; MyMoneyPrice m_selectedPrice; QList m_selectedPayees; QList m_selectedTags; QList m_selectedBudgets; KMyMoneyRegister::SelectedTransactions m_selectedTransactions; // This is Auto Saving related bool m_autoSaveEnabled; QTimer* m_autoSaveTimer; QTimer* m_progressTimer; int m_autoSavePeriod; bool m_inAutoSaving; // pointer to the current transaction editor TransactionEditor* m_transactionEditor; // Reconciliation dialog KEndingBalanceDlg* m_endingBalanceDlg; // Pointer to the combo box used for key selection during // File/Save as KComboBox* m_saveEncrypted; // id's that need to be remembered QString m_accountGoto, m_payeeGoto; QStringList m_additionalGpgKeys; QLabel* m_additionalKeyLabel; QPushButton* m_additionalKeyButton; KRecentFilesAction* m_recentFiles; #ifdef KF5Holidays_FOUND // used by the calendar interface for schedules KHolidays::HolidayRegion* m_holidayRegion; #endif QBitArray m_processingDays; QMap m_holidayMap; QStringList m_consistencyCheckResult; bool m_applicationIsReady; WebConnect* m_webConnect; // methods void consistencyCheck(bool alwaysDisplayResults); static void setThemedCSS(); void copyConsistencyCheckResults(); void saveConsistencyCheckResults(); }; KMyMoneyApp::KMyMoneyApp(QWidget* parent) : KXmlGuiWindow(parent), d(new Private(this)) { #ifdef KMM_DBUS new KmymoneyAdaptor(this); QDBusConnection::sessionBus().registerObject("/KMymoney", this); QDBusConnection::sessionBus().interface()->registerService( "org.kde.kmymoney", QDBusConnectionInterface::DontQueueService); #endif // Register the main engine types used as meta-objects qRegisterMetaType("MyMoneyMoney"); qRegisterMetaType("MyMoneySecurity"); // preset the pointer because we need it during the course of this constructor kmymoney = this; d->m_config = KSharedConfig::openConfig(); d->setThemedCSS(); MyMoneyTransactionFilter::setFiscalYearStart(KMyMoneyGlobalSettings::firstFiscalMonth(), KMyMoneyGlobalSettings::firstFiscalDay()); updateCaption(true); QFrame* frame = new QFrame; frame->setFrameStyle(QFrame::NoFrame); // values for margin (11) and spacing(6) taken from KDialog implementation QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom, frame); layout->setContentsMargins(2, 2, 2, 2); layout->setSpacing(6); { QString themeName = KMyMoneySettings::iconsTheme(); // get theme user wants if (!themeName.isEmpty() && themeName != QLatin1Literal("system")) // if it isn't default theme then set it QIcon::setThemeName(themeName); Icons::setIconThemeNames(QIcon::themeName()); // get whatever theme user ends up with and hope our icon names will fit that theme } initStatusBar(); initActions(); initDynamicMenus(); d->m_myMoneyView = new KMyMoneyView(this/*the global variable kmymoney is not yet assigned. So we pass it here*/); layout->addWidget(d->m_myMoneyView, 10); connect(d->m_myMoneyView, &KMyMoneyView::aboutToChangeView, this, &KMyMoneyApp::slotResetSelections); connect(d->m_myMoneyView, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), this, SLOT(slotUpdateActions())); connectActionsAndViews(); /////////////////////////////////////////////////////////////////// // call inits to invoke all other construction parts readOptions(); // now initialize the plugin structure createInterfaces(); loadPlugins(); setCentralWidget(frame); connect(&d->m_proc, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotBackupHandleEvents())); // force to show the home page if the file is closed connect(actionCollection()->action(s_Actions[Action::ViewTransactionDetail]), &QAction::toggled, d->m_myMoneyView, &KMyMoneyView::slotShowTransactionDetail); d->m_backupState = BACKUP_IDLE; QLocale locale; int weekStart = locale.firstDayOfWeek(); int weekEnd = weekStart-1; if (weekEnd < Qt::Monday) { weekEnd = Qt::Sunday; } bool startFirst = (weekStart < weekEnd); for (int i = 0; i < 8; i++) { if (startFirst) d->m_processingDays.setBit(i, (i >= weekStart && i <= weekEnd)); else d->m_processingDays.setBit(i, (i >= weekStart || i <= weekEnd)); } d->m_autoSaveTimer = new QTimer(this); d->m_progressTimer = new QTimer(this); connect(d->m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave())); connect(d->m_progressTimer, SIGNAL(timeout()), this, SLOT(slotStatusProgressDone())); // make sure, we get a note when the engine changes state connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotDataChanged())); // connect the WebConnect server connect(d->m_webConnect, SIGNAL(gotUrl(QUrl)), this, SLOT(webConnect(QUrl))); // make sure we have a balance warning object d->m_balanceWarning = new KBalanceWarning(this); // setup the initial configuration slotUpdateConfiguration(); // kickstart date change timer slotDateChanged(); connect(this, SIGNAL(fileLoaded(QUrl)), onlineJobAdministration::instance(), SLOT(updateOnlineTaskProperties())); } KMyMoneyApp::~KMyMoneyApp() { // delete cached objects since the are in the way // when unloading the plugins onlineJobAdministration::instance()->clearCaches(); // we need to unload all plugins before we destroy anything else unloadPlugins(); delete d->m_searchDlg; delete d->m_transactionEditor; delete d->m_endingBalanceDlg; delete d->m_moveToAccountSelector; #ifdef KF5Holidays_FOUND delete d->m_holidayRegion; #endif delete d; } QUrl KMyMoneyApp::lastOpenedURL() { QUrl url = d->m_startDialog ? QUrl() : d->m_fileName; if (!url.isValid()) { url = QUrl::fromUserInput(readLastUsedFile()); } ready(); return url; } void KMyMoneyApp::slotObjectDestroyed(QObject* o) { if (o == d->m_moveToAccountSelector) { d->m_moveToAccountSelector = 0; } } void KMyMoneyApp::slotInstallConsistencyCheckContextMenu() { // this code relies on the implementation of KMessageBox::informationList to add a context menu to that list, // please adjust it if it's necessary or rewrite the way the consistency check results are displayed if (QWidget* dialog = QApplication::activeModalWidget()) { if (QListWidget* widget = dialog->findChild()) { // give the user a hint that the data can be saved widget->setToolTip(i18n("This is the consistency check log, use the context menu to copy or save it.")); widget->setWhatsThis(widget->toolTip()); widget->setContextMenuPolicy(Qt::CustomContextMenu); connect(widget, SIGNAL(customContextMenuRequested(QPoint)), SLOT(slotShowContextMenuForConsistencyCheck(QPoint))); } } } void KMyMoneyApp::slotShowContextMenuForConsistencyCheck(const QPoint &pos) { // allow the user to save the consistency check results if (QWidget* widget = qobject_cast< QWidget* >(sender())) { QMenu contextMenu(widget); QAction* copy = new QAction(i18n("Copy to clipboard"), widget); QAction* save = new QAction(i18n("Save to file"), widget); contextMenu.addAction(copy); contextMenu.addAction(save); QAction *result = contextMenu.exec(widget->mapToGlobal(pos)); if (result == copy) { // copy the consistency check results to the clipboard d->copyConsistencyCheckResults(); } else if (result == save) { // save the consistency check results to a file d->saveConsistencyCheckResults(); } } } void KMyMoneyApp::createTransactionMoveMenu() { if (!d->m_moveToAccountSelector) { QWidget* w = factory()->container("transaction_move_menu", this); QMenu *menu = dynamic_cast(w); if (menu) { QWidgetAction *accountSelectorAction = new QWidgetAction(menu); d->m_moveToAccountSelector = new KMyMoneyAccountSelector(menu, 0, false); d->m_moveToAccountSelector->setObjectName("transaction_move_menu_selector"); accountSelectorAction->setDefaultWidget(d->m_moveToAccountSelector); menu->addAction(accountSelectorAction); connect(d->m_moveToAccountSelector, SIGNAL(destroyed(QObject*)), this, SLOT(slotObjectDestroyed(QObject*))); connect(d->m_moveToAccountSelector, SIGNAL(itemSelected(QString)), this, SLOT(slotMoveToAccount(QString))); } } } void KMyMoneyApp::initDynamicMenus() { connect(this, SIGNAL(accountSelected(MyMoneyAccount)), this, SLOT(slotUpdateMoveToAccountMenu())); connect(this, SIGNAL(transactionsSelected(KMyMoneyRegister::SelectedTransactions)), this, SLOT(slotUpdateMoveToAccountMenu())); connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotUpdateMoveToAccountMenu())); } void KMyMoneyApp::initActions() { KActionCollection *aC = actionCollection(); // ************* // Adding standard actions // ************* KStandardAction::openNew(this, &KMyMoneyApp::slotFileNew, aC); KStandardAction::open(this, &KMyMoneyApp::slotFileOpen, aC); d->m_recentFiles = KStandardAction::openRecent(this, &KMyMoneyApp::slotFileOpenRecent, aC); KStandardAction::save(this, &KMyMoneyApp::slotFileSave, aC); KStandardAction::saveAs(this, &KMyMoneyApp::slotFileSaveAs, aC); KStandardAction::close(this, &KMyMoneyApp::slotFileClose, aC); KStandardAction::quit(this, &KMyMoneyApp::slotFileQuit, aC); KStandardAction::print(this, &KMyMoneyApp::slotPrintView, aC); KStandardAction::preferences(this, &KMyMoneyApp::slotSettings, aC); /* Look-up table for all custom actions. It's required for: 1) building QList with QActions to be added to ActionCollection 2) adding custom features to QActions like e.g. overlaid icon or keyboard shortcut */ QHash lutActions; // ************* // Adding all actions // ************* { // struct for QAction's vital (except icon) informations struct actionInfo { Action action; KMyMoneyAppFunc callback; QString text; Icon icon; }; const QVector actionInfos { // ************* // The File menu // ************* {Action::FileOpenDatabase, &KMyMoneyApp::slotOpenDatabase, i18n("Open database..."), Icon::SVNUpdate}, {Action::FileSaveAsDatabase, &KMyMoneyApp::slotSaveAsDatabase, i18n("Save as database..."), Icon::FileArchiver}, {Action::FileBackup, &KMyMoneyApp::slotBackupFile, i18n("Backup..."), Icon::Empty}, {Action::FileImportGNC, &KMyMoneyApp::slotGncImport, i18n("GnuCash..."), Icon::Empty}, {Action::FileImportStatement, &KMyMoneyApp::slotStatementImport, i18n("Statement file..."), Icon::Empty}, {Action::FileImportTemplate, &KMyMoneyApp::slotLoadAccountTemplates, i18n("Account Template..."), Icon::Empty}, {Action::FileExportTemplate, &KMyMoneyApp::slotSaveAccountTemplates, i18n("Account Template..."), Icon::Empty}, {Action::FilePersonalData, &KMyMoneyApp::slotFileViewPersonal, i18n("Personal Data..."), Icon::UserProperties}, #ifdef KMM_DEBUG {Action::FileDump, &KMyMoneyApp::slotFileFileInfo, i18n("Dump Memory"), Icon::Empty}, #endif {Action::FileInformation, &KMyMoneyApp::slotFileInfoDialog, i18n("File-Information..."), Icon::DocumentProperties}, // ************* // The Edit menu // ************* {Action::EditFindTransaction, &KMyMoneyApp::slotFindTransaction, i18n("Find transaction..."), Icon::Empty}, // ************* // The View menu // ************* {Action::ViewTransactionDetail, &KMyMoneyApp::slotShowTransactionDetail, i18n("Show Transaction Detail"), Icon::ViewTransactionDetail}, {Action::ViewHideReconciled, &KMyMoneyApp::slotHideReconciledTransactions, i18n("Hide reconciled transactions"), Icon::HideReconciled}, {Action::ViewHideCategories, &KMyMoneyApp::slotHideUnusedCategories, i18n("Hide unused categories"), Icon::HideCategories}, {Action::ViewShowAll, &KMyMoneyApp::slotShowAllAccounts, i18n("Show all accounts"), Icon::Empty}, // ********************* // The institutions menu // ********************* {Action::InstitutionNew, &KMyMoneyApp::slotInstitutionNew, i18n("New institution..."), Icon::Empty}, {Action::InstitutionEdit, &KMyMoneyApp::slotInstitutionEditEmpty, i18n("Edit institution..."), Icon::Empty}, {Action::InstitutionDelete, &KMyMoneyApp::slotInstitutionDelete, i18n("Delete institution..."), Icon::Empty}, // ***************** // The accounts menu // ***************** {Action::AccountNew, &KMyMoneyApp::slotAccountNew, i18n("New account..."), Icon::Empty}, {Action::AccountOpen, &KMyMoneyApp::slotAccountOpenEmpty, i18n("Open ledger"), Icon::ViewFinancialList}, {Action::AccountStartReconciliation, &KMyMoneyApp::slotAccountReconcileStart, i18n("Reconcile..."), Icon::Reconcile}, {Action::AccountFinishReconciliation, &KMyMoneyApp::slotAccountReconcileFinish, i18nc("Finish reconciliation", "Finish"), Icon::Empty}, {Action::AccountPostponeReconciliation, &KMyMoneyApp::slotAccountReconcilePostpone, i18n("Postpone reconciliation"), Icon::MediaPlaybackPause}, {Action::AccountEdit, &KMyMoneyApp::slotAccountEdit, i18n("Edit account..."), Icon::Empty}, {Action::AccountDelete, &KMyMoneyApp::slotAccountDelete, i18n("Delete account..."), Icon::Empty}, {Action::AccountClose, &KMyMoneyApp::slotAccountClose, i18n("Close account"), Icon::Empty}, {Action::AccountReopen, &KMyMoneyApp::slotAccountReopen, i18n("Reopen account"), Icon::Empty}, {Action::AccountTransactionReport, &KMyMoneyApp::slotAccountTransactionReport, i18n("Transaction report"), Icon::ViewFinancialList}, {Action::AccountBalanceChart, &KMyMoneyApp::slotAccountChart, i18n("Show balance chart..."), Icon::OfficeChartLine}, {Action::AccountOnlineMap, &KMyMoneyApp::slotAccountMapOnline, i18n("Map account..."), Icon::NewsSubscribe}, {Action::AccountOnlineUnmap, &KMyMoneyApp::slotAccountUnmapOnline, i18n("Unmap account..."), Icon::NewsUnsubscribe}, {Action::AccountUpdateMenu, &KMyMoneyApp::slotAccountUpdateOnline, i18nc("Update online accounts menu", "Update"), Icon::Empty}, {Action::AccountUpdate, &KMyMoneyApp::slotAccountUpdateOnline, i18n("Update account..."), Icon::Empty}, {Action::AccountUpdateAll, &KMyMoneyApp::slotAccountUpdateOnlineAll, i18n("Update all accounts..."), Icon::Empty}, {Action::AccountCreditTransfer, &KMyMoneyApp::slotNewOnlineTransfer, i18n("New credit transfer"), Icon::Empty}, // ******************* // The categories menu // ******************* {Action::CategoryNew, &KMyMoneyApp::slotCategoryNew, i18n("New category..."), Icon::Empty}, {Action::CategoryEdit, &KMyMoneyApp::slotAccountEdit, i18n("Edit category..."), Icon::Empty}, {Action::CategoryDelete, &KMyMoneyApp::slotAccountDelete, i18n("Delete category..."), Icon::Empty}, // ************** // The tools menu // ************** {Action::ToolCurrencies, &KMyMoneyApp::slotCurrencyDialog, i18n("Currencies..."), Icon::ViewCurrencyList}, {Action::ToolPrices, &KMyMoneyApp::slotPriceDialog, i18n("Prices..."), Icon::Empty}, {Action::ToolUpdatePrices, &KMyMoneyApp::slotEquityPriceUpdate, i18n("Update Stock and Currency Prices..."), Icon::Empty}, {Action::ToolConsistency, &KMyMoneyApp::slotFileConsistencyCheck, i18n("Consistency Check"), Icon::Empty}, {Action::ToolPerformance, &KMyMoneyApp::slotPerformanceTest, i18n("Performance-Test"), Icon::Fork}, {Action::ToolSQL, &KMyMoneyApp::slotGenerateSql, i18n("Generate Database SQL"), Icon::Empty}, {Action::ToolCalculator, &KMyMoneyApp::slotToolsStartKCalc, i18n("Calculator..."), Icon::AccessoriesCalculator}, // ***************** // The settings menu // ***************** {Action::SettingsAllMessages, &KMyMoneyApp::slotEnableMessages, i18n("Enable all messages"), Icon::Empty}, // ************* // The help menu // ************* {Action::HelpShow, &KMyMoneyApp::slotShowTipOfTheDay, i18n("&Show tip of the day"), Icon::Tip}, // *************************** // Actions w/o main menu entry // *************************** {Action::TransactionNew, &KMyMoneyApp::slotTransactionsNew, i18nc("New transaction button", "New"), Icon::Empty}, {Action::TransactionEdit, &KMyMoneyApp::slotTransactionsEdit, i18nc("Edit transaction button", "Edit"), Icon::Empty}, {Action::TransactionEnter, &KMyMoneyApp::slotTransactionsEnter, i18nc("Enter transaction", "Enter"), Icon::DialogOK}, {Action::TransactionEditSplits, &KMyMoneyApp::slotTransactionsEditSplits, i18nc("Edit split button", "Edit splits"), Icon::Split}, {Action::TransactionCancel, &KMyMoneyApp::slotTransactionsCancel, i18nc("Cancel transaction edit", "Cancel"), Icon::DialogCancel}, {Action::TransactionDelete, &KMyMoneyApp::slotTransactionsDelete, i18nc("Delete transaction", "Delete"), Icon::EditDelete}, {Action::TransactionDuplicate, &KMyMoneyApp::slotTransactionDuplicate, i18nc("Duplicate transaction", "Duplicate"), Icon::EditCopy}, {Action::TransactionMatch, &KMyMoneyApp::slotTransactionMatch, i18nc("Button text for match transaction", "Match"),Icon::Empty}, {Action::TransactionAccept, &KMyMoneyApp::slotTransactionsAccept, i18nc("Accept 'imported' and 'matched' transaction", "Accept"), Icon::Empty}, {Action::TransactionToggleReconciled, &KMyMoneyApp::slotToggleReconciliationFlag, i18nc("Toggle reconciliation flag", "Toggle"), Icon::Empty}, {Action::TransactionToggleCleared, &KMyMoneyApp::slotMarkTransactionCleared, i18nc("Mark transaction cleared", "Cleared"), Icon::Empty}, {Action::TransactionReconciled, &KMyMoneyApp::slotMarkTransactionReconciled, i18nc("Mark transaction reconciled", "Reconciled"), Icon::Empty}, {Action::TransactionNotReconciled, &KMyMoneyApp::slotMarkTransactionNotReconciled, i18nc("Mark transaction not reconciled", "Not reconciled"), Icon::Empty}, {Action::TransactionSelectAll, &KMyMoneyApp::selectAllTransactions, i18nc("Select all transactions", "Select all"), Icon::Empty}, {Action::TransactionGoToAccount, &KMyMoneyApp::slotTransactionGotoAccount, i18n("Go to account"), Icon::GoJump}, {Action::TransactionGoToPayee, &KMyMoneyApp::slotTransactionGotoPayee, i18n("Go to payee"), Icon::GoJump}, {Action::TransactionCreateSchedule, &KMyMoneyApp::slotTransactionCreateSchedule, i18n("Create scheduled transaction..."), Icon::AppointmentNew}, {Action::TransactionAssignNumber, &KMyMoneyApp::slotTransactionAssignNumber, i18n("Assign next number"), Icon::Empty}, {Action::TransactionCombine, &KMyMoneyApp::slotTransactionCombine, i18nc("Combine transactions", "Combine"), Icon::Empty}, {Action::TransactionCopySplits, &KMyMoneyApp::slotTransactionCopySplits, i18n("Copy splits"), Icon::Empty}, //Investment {Action::InvestmentNew, &KMyMoneyApp::slotInvestmentNew, i18n("New investment..."), Icon::Empty}, {Action::InvestmentEdit, &KMyMoneyApp::slotInvestmentEdit, i18n("Edit investment..."), Icon::Empty}, {Action::InvestmentDelete, &KMyMoneyApp::slotInvestmentDelete, i18n("Delete investment..."), Icon::Empty}, {Action::InvestmentOnlinePrice, &KMyMoneyApp::slotOnlinePriceUpdate, i18n("Online price update..."), Icon::Empty}, {Action::InvestmentManualPrice, &KMyMoneyApp::slotManualPriceUpdate, i18n("Manual price update..."), Icon::Empty}, //Schedule {Action::ScheduleNew, &KMyMoneyApp::slotScheduleNew, i18n("New scheduled transaction"), Icon::AppointmentNew}, {Action::ScheduleEdit, &KMyMoneyApp::slotScheduleEdit, i18n("Edit scheduled transaction"), Icon::DocumentEdit}, {Action::ScheduleDelete, &KMyMoneyApp::slotScheduleDelete, i18n("Delete scheduled transaction"), Icon::EditDelete}, {Action::ScheduleDuplicate, &KMyMoneyApp::slotScheduleDuplicate, i18n("Duplicate scheduled transaction"), Icon::EditCopy}, {Action::ScheduleEnter, &KMyMoneyApp::slotScheduleEnter, i18n("Enter next transaction..."), Icon::KeyEnter}, {Action::ScheduleSkip, &KMyMoneyApp::slotScheduleSkip, i18n("Skip next transaction..."), Icon::MediaSeekForward}, //Payees {Action::PayeeNew, &KMyMoneyApp::slotPayeeNew, i18n("New payee"), Icon::ListAddUser}, {Action::PayeeRename, &KMyMoneyApp::payeeRename, i18n("Rename payee"), Icon::PayeeRename}, {Action::PayeeDelete, &KMyMoneyApp::slotPayeeDelete, i18n("Delete payee"), Icon::ListRemoveUser}, {Action::PayeeMerge, &KMyMoneyApp::slotPayeeMerge, i18n("Merge payees"), Icon::PayeeMerge}, //Tags {Action::TagNew, &KMyMoneyApp::slotTagNew, i18n("New tag"), Icon::ListAddTag}, {Action::TagRename, &KMyMoneyApp::slotTagRename, i18n("Rename tag"), Icon::TagRename}, {Action::TagDelete, &KMyMoneyApp::slotTagDelete, i18n("Delete tag"), Icon::ListRemoveTag}, //Budget {Action::BudgetNew, &KMyMoneyApp::slotBudgetNew, i18n("New budget"), Icon::Empty}, {Action::BudgetRename, &KMyMoneyApp::budgetRename, i18n("Rename budget"), Icon::Empty}, {Action::BudgetDelete, &KMyMoneyApp::slotBudgetDelete, i18n("Delete budget"), Icon::Empty}, {Action::BudgetCopy, &KMyMoneyApp::slotBudgetCopy, i18n("Copy budget"), Icon::Empty}, {Action::BudgetChangeYear, &KMyMoneyApp::slotBudgetChangeYear, i18n("Change budget year"), Icon::ViewCalendar}, {Action::BudgetForecast, &KMyMoneyApp::slotBudgetForecast, i18n("Budget based on forecast"), Icon::ViewForecast}, //Currency actions {Action::CurrencyNew, &KMyMoneyApp::slotCurrencyNew, i18n("New currency"), Icon::Empty}, {Action::CurrencyRename, &KMyMoneyApp::currencyRename, i18n("Rename currency"), Icon::EditRename}, {Action::CurrencyDelete, &KMyMoneyApp::slotCurrencyDelete, i18n("Delete currency"), Icon::EditDelete}, {Action::CurrencySetBase, &KMyMoneyApp::slotCurrencySetBase, i18n("Select as base currency"), Icon::KMyMoney}, //Price actions {Action::PriceNew, &KMyMoneyApp::priceNew, i18n("New price..."), Icon::DocumentNew}, {Action::PriceEdit, &KMyMoneyApp::priceEdit, i18n("Edit price..."), Icon::DocumentEdit}, {Action::PriceUpdate, &KMyMoneyApp::priceOnlineUpdate, i18n("Online Price Update..."), Icon::Empty}, {Action::PriceDelete, &KMyMoneyApp::priceDelete, i18n("Delete price..."), Icon::EditDelete}, //debug actions #ifdef KMM_DEBUG {Action::WizardNewUser, &KMyMoneyApp::slotNewFeature, i18n("Test new feature"), Icon::Empty}, {Action::DebugTraces, &KMyMoneyApp::slotToggleTraces, i18n("Debug Traces"), Icon::Empty}, #endif {Action::DebugTimers, &KMyMoneyApp::slotToggleTimers, i18n("Debug Timers"), Icon::Empty}, // onlineJob actions {Action::OnlineJobDelete, &KMyMoneyApp::slotRemoveJob, i18n("Remove credit transfer"), Icon::EditDelete}, {Action::OnlineJobEdit, &KMyMoneyApp::slotEditJob, i18n("Edit credit transfer"), Icon::DocumentEdit}, {Action::OnlineJobLog, &KMyMoneyApp::slotOnlineJobLog, i18n("Show log"), Icon::Empty}, }; foreach (const auto info, actionInfos) { QAction *a = new QAction(0); // KActionCollection::addAction by name sets object name anyways, // so, as better alternative, set it here right from the start a->setObjectName(s_Actions.value(info.action)); a->setText(info.text); if (info.icon != Icon::Empty) // no need to set empty icon a->setIcon(QIcon::fromTheme(g_Icons.value(info.icon))); connect(a, &QAction::triggered, this, info.callback); lutActions.insert(info.action, a); // store QAction's pointer for later processing } } // ************* // Setting some of added actions checkable // ************* { // Some of acitions schould be checkable, // so set them here const QVector checkableActions { Action::ViewTransactionDetail, Action::ViewHideReconciled, Action::ViewHideCategories, #ifdef KMM_DEBUG Action::DebugTraces, #endif Action::ViewShowAll }; foreach (const auto it, checkableActions) lutActions[it]->setCheckable(true); } // ************* // Setting custom icons for some of added actions // ************* { // struct for QAction's icon overlays struct iconOverlayInfo { Action action; Icon icon; Icon overlay; Qt::Corner corner; }; const QVector actionOverlaidIcons { {Action::EditFindTransaction, Icon::ViewFinancialTransfer, Icon::EditFind, Qt::BottomRightCorner}, {Action::InstitutionNew, Icon::ViewBank, Icon::ListAdd, Qt::BottomRightCorner}, {Action::InstitutionEdit, Icon::ViewBank, Icon::DocumentEdit, Qt::BottomRightCorner}, {Action::InstitutionDelete, Icon::ViewBank, Icon::EditDelete, Qt::BottomRightCorner}, {Action::AccountNew, Icon::ViewBankAccount, Icon::ListAdd, Qt::TopRightCorner}, {Action::AccountFinishReconciliation, Icon::Merge, Icon::DialogOK, Qt::BottomRightCorner}, {Action::AccountEdit, Icon::ViewBankAccount, Icon::DocumentEdit, Qt::BottomRightCorner}, {Action::AccountDelete, Icon::ViewBankAccount, Icon::EditDelete, Qt::BottomRightCorner}, {Action::AccountClose, Icon::ViewBankAccount, Icon::DialogClose, Qt::BottomRightCorner}, {Action::AccountReopen, Icon::ViewBankAccount, Icon::DialogOK, Qt::BottomRightCorner}, {Action::AccountUpdateMenu, Icon::ViewBankAccount, Icon::Download, Qt::BottomRightCorner}, {Action::AccountUpdate, Icon::ViewBankAccount, Icon::Download, Qt::BottomRightCorner}, {Action::AccountUpdateAll, Icon::ViewBankAccount, Icon::Download, Qt::BottomRightCorner}, {Action::AccountCreditTransfer, Icon::ViewBankAccount, Icon::MailMessageNew, Qt::BottomRightCorner}, {Action::CategoryNew, Icon::ViewFinancialCategories, Icon::ListAdd, Qt::TopRightCorner}, {Action::CategoryEdit, Icon::ViewFinancialCategories, Icon::DocumentEdit, Qt::BottomRightCorner}, {Action::CategoryDelete, Icon::ViewFinancialCategories, Icon::EditDelete, Qt::BottomRightCorner}, {Action::ToolUpdatePrices, Icon::ViewInvestment, Icon::Download, Qt::BottomRightCorner}, {Action::TransactionNew, Icon::ViewFinancialTransfer, Icon::ListAdd, Qt::TopRightCorner}, {Action::TransactionEdit, Icon::ViewFinancialTransfer, Icon::DocumentEdit, Qt::BottomRightCorner}, {Action::TransactionMatch, Icon::ViewFinancialTransfer, Icon::DocumentImport, Qt::BottomRightCorner}, {Action::TransactionAccept, Icon::ViewFinancialTransfer, Icon::DialogOKApply, Qt::BottomRightCorner}, {Action::InvestmentNew, Icon::ViewInvestment, Icon::ListAdd, Qt::TopRightCorner}, {Action::InvestmentEdit, Icon::ViewInvestment, Icon::DocumentEdit, Qt::BottomRightCorner}, {Action::InvestmentDelete, Icon::ViewInvestment, Icon::EditDelete, Qt::BottomRightCorner}, {Action::InvestmentOnlinePrice, Icon::ViewInvestment, Icon::Download, Qt::BottomRightCorner}, {Action::BudgetNew, Icon::ViewTimeScheduleCalculus, Icon::ListAdd, Qt::TopRightCorner}, {Action::BudgetRename, Icon::ViewTimeScheduleCalculus, Icon::DocumentEdit, Qt::BottomRightCorner}, {Action::BudgetDelete, Icon::ViewTimeScheduleCalculus, Icon::EditDelete, Qt::BottomRightCorner}, {Action::BudgetCopy, Icon::ViewTimeScheduleCalculus, Icon::EditCopy, Qt::BottomRightCorner}, {Action::PriceUpdate, Icon::ViewCurrencyList, Icon::Download, Qt::BottomRightCorner} }; for(const auto& it : actionOverlaidIcons) lutActions[it.action]->setIcon(KMyMoneyUtils::overlayIcon(g_Icons[it.icon], g_Icons[it.overlay], it.corner)); } // ************* // Setting keyboard shortcuts for some of added actions // ************* { const QVector> actionShortcuts { {qMakePair(Action::EditFindTransaction, Qt::CTRL + Qt::Key_F)}, {qMakePair(Action::ViewTransactionDetail, Qt::CTRL + Qt::Key_T)}, {qMakePair(Action::ViewHideReconciled, Qt::CTRL + Qt::Key_R)}, {qMakePair(Action::ViewHideCategories, Qt::CTRL + Qt::Key_U)}, {qMakePair(Action::ViewShowAll, Qt::CTRL + Qt::SHIFT + Qt::Key_A)}, {qMakePair(Action::AccountStartReconciliation, Qt::CTRL + Qt::SHIFT + Qt::Key_R)}, {qMakePair(Action::TransactionNew, Qt::CTRL + Qt::Key_Insert)}, {qMakePair(Action::TransactionToggleReconciled, Qt::CTRL + Qt::Key_Space)}, {qMakePair(Action::TransactionToggleCleared, Qt::CTRL + Qt::Key_Alt + Qt::Key_Space)}, {qMakePair(Action::TransactionReconciled, Qt::CTRL + Qt::Key_Shift + Qt::Key_Space)}, {qMakePair(Action::TransactionSelectAll, Qt::CTRL + Qt::Key_A)}, #ifdef KMM_DEBUG {qMakePair(Action::WizardNewUser, Qt::CTRL + Qt::Key_G)}, #endif {qMakePair(Action::TransactionAssignNumber, Qt::CTRL + Qt::Key_Shift + Qt::Key_N)} }; for(const auto& it : actionShortcuts) aC->setDefaultShortcut(lutActions[it.first], it.second); } // ************* // Misc settings // ************* connect(onlineJobAdministration::instance(), &onlineJobAdministration::canSendCreditTransferChanged, lutActions.value(Action::AccountCreditTransfer), &QAction::setEnabled); // Setup transaction detail switch lutActions[Action::ViewTransactionDetail]->setChecked(KMyMoneyGlobalSettings::showRegisterDetailed()); lutActions[Action::ViewHideReconciled]->setChecked(KMyMoneyGlobalSettings::hideReconciledTransactions()); lutActions[Action::ViewHideCategories]->setChecked(KMyMoneyGlobalSettings::hideUnusedCategory()); lutActions[Action::ViewShowAll]->setChecked(false); // ************* // Adding actions to ActionCollection // ************* actionCollection()->addActions(lutActions.values()); // ************************ // Currently unused actions // ************************ #if 0 new KToolBarPopupAction(i18n("View back"), "go-previous", 0, this, SLOT(slotShowPreviousView()), actionCollection(), "go_back"); new KToolBarPopupAction(i18n("View forward"), "go-next", 0, this, SLOT(slotShowNextView()), actionCollection(), "go_forward"); action("go_back")->setEnabled(false); action("go_forward")->setEnabled(false); #endif // use the absolute path to your kmymoneyui.rc file for testing purpose in createGUI(); setupGUI(); // reconnect about app entry to dialog with full credits information QAction *aboutApp = aC->action(QString::fromLatin1(KStandardAction::name(KStandardAction::AboutApp))); aboutApp->disconnect(); connect(aboutApp, &QAction::triggered, this, &KMyMoneyApp::slotShowCredits); QMenu *menuContainer; menuContainer = static_cast(factory()->container(QStringLiteral("import"), this)); menuContainer->setIcon(QIcon::fromTheme(g_Icons[Icon::DocumentImport])); menuContainer = static_cast(factory()->container(QStringLiteral("export"), this)); menuContainer->setIcon(QIcon::fromTheme(g_Icons[Icon::DocumentExport])); } void KMyMoneyApp::connectActionsAndViews() { KOnlineJobOutbox *const outbox = d->m_myMoneyView->getOnlineJobOutbox(); Q_CHECK_PTR(outbox); QAction *const onlineJob_delete = actionCollection()->action(s_Actions[Action::OnlineJobDelete]); Q_CHECK_PTR(onlineJob_delete); connect(onlineJob_delete, SIGNAL(triggered()), outbox, SLOT(slotRemoveJob())); QAction *const onlineJob_edit = actionCollection()->action(s_Actions[Action::OnlineJobEdit]); Q_CHECK_PTR(onlineJob_edit); connect(onlineJob_edit, SIGNAL(triggered()), outbox, SLOT(slotEditJob())); } #ifdef KMM_DEBUG void KMyMoneyApp::dumpActions() const { const QList list = actionCollection()->actions(); foreach (const auto it, list) std::cout << qPrintable(it->objectName()) << ": " << qPrintable(it->text()) << std::endl; } #endif bool KMyMoneyApp::isActionToggled(const Action _a) { return actionCollection()->action(s_Actions[_a])->isChecked(); } void KMyMoneyApp::initStatusBar() { /////////////////////////////////////////////////////////////////// // STATUSBAR d->m_statusLabel = new QLabel; statusBar()->addWidget(d->m_statusLabel); ready(); // Initialization of progress bar taken from KDevelop ;-) d->m_progressBar = new QProgressBar; statusBar()->addWidget(d->m_progressBar); d->m_progressBar->setFixedHeight(d->m_progressBar->sizeHint().height() - 8); // hide the progress bar for now slotStatusProgressBar(-1, -1); } void KMyMoneyApp::saveOptions() { KConfigGroup grp = d->m_config->group("General Options"); grp.writeEntry("Geometry", size()); grp.writeEntry("Show Statusbar", actionCollection()->action(KStandardAction::name(KStandardAction::ShowStatusbar))->isChecked()); KConfigGroup toolbarGrp = d->m_config->group("mainToolBar"); toolBar("mainToolBar")->saveSettings(toolbarGrp); d->m_recentFiles->saveEntries(d->m_config->group("Recent Files")); } void KMyMoneyApp::readOptions() { KConfigGroup grp = d->m_config->group("General Options"); actionCollection()->action(s_Actions[Action::ViewHideReconciled])->setChecked(KMyMoneyGlobalSettings::hideReconciledTransactions()); actionCollection()->action(s_Actions[Action::ViewHideCategories])->setChecked(KMyMoneyGlobalSettings::hideUnusedCategory()); d->m_recentFiles->loadEntries(d->m_config->group("Recent Files")); // Startdialog is written in the settings dialog d->m_startDialog = grp.readEntry("StartDialog", true); } void KMyMoneyApp::resizeEvent(QResizeEvent* ev) { KMainWindow::resizeEvent(ev); updateCaption(true); } int KMyMoneyApp::askSaveOnClose() { int ans; if (KMyMoneyGlobalSettings::autoSaveOnClose()) { ans = KMessageBox::Yes; } else { ans = KMessageBox::warningYesNoCancel(this, i18n("The file has been changed, save it?")); } return ans; } bool KMyMoneyApp::queryClose() { if (!isReady()) return false; if (d->m_myMoneyView->dirty()) { int ans = askSaveOnClose(); if (ans == KMessageBox::Cancel) return false; else if (ans == KMessageBox::Yes) { bool saved = slotFileSave(); saveOptions(); return saved; } } if (d->m_myMoneyView->isDatabase()) slotFileClose(); // close off the database saveOptions(); return true; } ///////////////////////////////////////////////////////////////////// // SLOT IMPLEMENTATION ///////////////////////////////////////////////////////////////////// void KMyMoneyApp::slotFileInfoDialog() { QPointer dlg = new KMyMoneyFileInfoDlg(0); dlg->exec(); delete dlg; } void KMyMoneyApp::slotPerformanceTest() { // dump performance report to stderr int measurement[2]; QTime timer; MyMoneyAccount acc; qDebug("--- Starting performance tests ---"); // AccountList MyMoneyFile::instance()->preloadCache(); measurement[0] = measurement[1] = 0; timer.start(); for (int i = 0; i < 1000; ++i) { QList list; MyMoneyFile::instance()->accountList(list); measurement[i != 0] = timer.elapsed(); } std::cerr << "accountList()" << std::endl; std::cerr << "First time: " << measurement[0] << " msec" << std::endl; std::cerr << "Total time: " << (measurement[0] + measurement[1]) << " msec" << std::endl; std::cerr << "Average : " << (measurement[0] + measurement[1]) / 1000 << " msec" << std::endl; // Balance of asset account(s) MyMoneyFile::instance()->preloadCache(); measurement[0] = measurement[1] = 0; acc = MyMoneyFile::instance()->asset(); for (int i = 0; i < 1000; ++i) { timer.start(); MyMoneyMoney result = MyMoneyFile::instance()->balance(acc.id()); measurement[i != 0] += timer.elapsed(); } std::cerr << "balance(Asset)" << std::endl; std::cerr << "First time: " << measurement[0] << " msec" << std::endl; std::cerr << "Average : " << (measurement[0] + measurement[1]) / 1000 << " msec" << std::endl; // total balance of asset account MyMoneyFile::instance()->preloadCache(); measurement[0] = measurement[1] = 0; acc = MyMoneyFile::instance()->asset(); for (int i = 0; i < 1000; ++i) { timer.start(); MyMoneyMoney result = MyMoneyFile::instance()->totalBalance(acc.id()); measurement[i != 0] += timer.elapsed(); } std::cerr << "totalBalance(Asset)" << std::endl; std::cerr << "First time: " << measurement[0] << " msec" << std::endl; std::cerr << "Average : " << (measurement[0] + measurement[1]) / 1000 << " msec" << std::endl; // Balance of expense account(s) MyMoneyFile::instance()->preloadCache(); measurement[0] = measurement[1] = 0; acc = MyMoneyFile::instance()->expense(); for (int i = 0; i < 1000; ++i) { timer.start(); MyMoneyMoney result = MyMoneyFile::instance()->balance(acc.id()); measurement[i != 0] += timer.elapsed(); } std::cerr << "balance(Expense)" << std::endl; std::cerr << "First time: " << measurement[0] << " msec" << std::endl; std::cerr << "Average : " << (measurement[0] + measurement[1]) / 1000 << " msec" << std::endl; // total balance of expense account MyMoneyFile::instance()->preloadCache(); measurement[0] = measurement[1] = 0; acc = MyMoneyFile::instance()->expense(); timer.start(); for (int i = 0; i < 1000; ++i) { MyMoneyMoney result = MyMoneyFile::instance()->totalBalance(acc.id()); measurement[i != 0] = timer.elapsed(); } std::cerr << "totalBalance(Expense)" << std::endl; std::cerr << "First time: " << measurement[0] << " msec" << std::endl; std::cerr << "Total time: " << (measurement[0] + measurement[1]) << " msec" << std::endl; std::cerr << "Average : " << (measurement[0] + measurement[1]) / 1000 << " msec" << std::endl; // transaction list MyMoneyFile::instance()->preloadCache(); measurement[0] = measurement[1] = 0; if (MyMoneyFile::instance()->asset().accountCount()) { MyMoneyTransactionFilter filter(MyMoneyFile::instance()->asset().accountList()[0]); filter.setDateFilter(QDate(), QDate::currentDate()); QList list; timer.start(); for (int i = 0; i < 100; ++i) { list = MyMoneyFile::instance()->transactionList(filter); measurement[i != 0] = timer.elapsed(); } std::cerr << "transactionList()" << std::endl; std::cerr << "First time: " << measurement[0] << " msec" << std::endl; std::cerr << "Total time: " << (measurement[0] + measurement[1]) << " msec" << std::endl; std::cerr << "Average : " << (measurement[0] + measurement[1]) / 100 << " msec" << std::endl; } // transaction list MyMoneyFile::instance()->preloadCache(); measurement[0] = measurement[1] = 0; if (MyMoneyFile::instance()->asset().accountCount()) { MyMoneyTransactionFilter filter(MyMoneyFile::instance()->asset().accountList()[0]); filter.setDateFilter(QDate(), QDate::currentDate()); QList list; timer.start(); for (int i = 0; i < 100; ++i) { MyMoneyFile::instance()->transactionList(list, filter); measurement[i != 0] = timer.elapsed(); } std::cerr << "transactionList(list)" << std::endl; std::cerr << "First time: " << measurement[0] << " msec" << std::endl; std::cerr << "Total time: " << (measurement[0] + measurement[1]) << " msec" << std::endl; std::cerr << "Average : " << (measurement[0] + measurement[1]) / 100 << " msec" << std::endl; } MyMoneyFile::instance()->preloadCache(); } void KMyMoneyApp::slotFileNew() { KMSTATUS(i18n("Creating new document...")); slotFileClose(); if (!d->m_myMoneyView->fileOpen()) { // next line required until we move all file handling out of KMyMoneyView d->m_myMoneyView->newFile(); d->m_fileName = QUrl(); updateCaption(); NewUserWizard::Wizard *wizard = new NewUserWizard::Wizard(); if (wizard->exec() == QDialog::Accepted) { MyMoneyFileTransaction ft; MyMoneyFile* file = MyMoneyFile::instance(); try { // store the user info file->setUser(wizard->user()); // create and setup base currency file->addCurrency(wizard->baseCurrency()); file->setBaseCurrency(wizard->baseCurrency()); // create a possible institution MyMoneyInstitution inst = wizard->institution(); if (inst.name().length()) { file->addInstitution(inst); } // create a possible checking account MyMoneyAccount acc = wizard->account(); if (acc.name().length()) { acc.setInstitutionId(inst.id()); MyMoneyAccount asset = file->asset(); file->addAccount(acc, asset); // create possible opening balance transaction if (!wizard->openingBalance().isZero()) { file->createOpeningBalanceTransaction(acc, wizard->openingBalance()); } } // import the account templates QList templates = wizard->templates(); QList::iterator it_t; for (it_t = templates.begin(); it_t != templates.end(); ++it_t) { (*it_t).importTemplate(&progressCallback); } d->m_fileName = wizard->url(); ft.commit(); KMyMoneyGlobalSettings::setFirstTimeRun(false); // FIXME This is a bit clumsy. We re-read the freshly // created file to be able to run through all the // fixup logic and then save it to keep the modified // flag off. slotFileSave(); d->m_myMoneyView->readFile(d->m_fileName); slotFileSave(); // now keep the filename in the recent files used list //KRecentFilesAction *p = dynamic_cast(action(KStandardAction::name(KStandardAction::OpenRecent))); //if(p) d->m_recentFiles->addUrl(d->m_fileName); writeLastUsedFile(d->m_fileName.url()); } catch (const MyMoneyException &) { // next line required until we move all file handling out of KMyMoneyView d->m_myMoneyView->closeFile(); } if (wizard->startSettingsAfterFinished()) slotSettings(); } else { // next line required until we move all file handling out of KMyMoneyView d->m_myMoneyView->closeFile(); } delete wizard; updateCaption(); emit fileLoaded(d->m_fileName); } } QUrl KMyMoneyApp::selectFile(const QString& title, const QString& _path, const QString& mask, QFileDialog::FileMode mode, QWidget* widget) { QString path(_path); // if the path is not specified open the file dialog in the last used directory // 'kmymoney' is the keyword that identifies the last used directory in KFileDialog if (path.isEmpty()) { path = KRecentDirs::dir(":kmymoney-import"); } QPointer dialog = new QFileDialog(this, title, path, mask); dialog->setFileMode(mode); QUrl url; if (dialog->exec() == QDialog::Accepted && dialog != 0) { QList selectedUrls = dialog->selectedUrls(); if (!selectedUrls.isEmpty()) { url = selectedUrls.first(); if (_path.isEmpty()) { KRecentDirs::add(":kmymoney-import", url.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash).path()); } } } // in case we have an additional widget, we remove it from the // dialog, so that the caller can still access it. Therefore, it is // the callers responsibility to delete the object if (widget) widget->setParent(0); delete dialog; return url; } // General open void KMyMoneyApp::slotFileOpen() { KMSTATUS(i18n("Open a file.")); QString prevDir = readLastUsedDir(); QPointer dialog = new QFileDialog(this, QString(), prevDir, i18n("KMyMoney files (*.kmy *.xml);;All files")); dialog->setFileMode(QFileDialog::ExistingFile); dialog->setAcceptMode(QFileDialog::AcceptOpen); if (dialog->exec() == QDialog::Accepted && dialog != nullptr) { slotFileOpenRecent(dialog->selectedUrls().first()); } delete dialog; } void KMyMoneyApp::slotOpenDatabase() { KMSTATUS(i18n("Open a file.")); QPointer dialog = new KSelectDatabaseDlg(QIODevice::ReadWrite); if (!dialog->checkDrivers()) { delete dialog; return; } if (dialog->exec() == QDialog::Accepted && dialog != 0) { slotFileOpenRecent(dialog->selectedURL()); } delete dialog; } bool KMyMoneyApp::isImportableFile(const QUrl &url) { bool result = false; // Iterate through the plugins and see if there's a loaded plugin who can handle it QMap::const_iterator it_plugin = d->m_importerPlugins.constBegin(); while (it_plugin != d->m_importerPlugins.constEnd()) { if ((*it_plugin)->isMyFormat(url.path())) { result = true; break; } ++it_plugin; } // If we did not find a match, try importing it as a KMM statement file, // which is really just for testing. the statement file is not exposed // to users. if (it_plugin == d->m_importerPlugins.constEnd()) if (MyMoneyStatement::isStatementFile(url.path())) result = true; // Place code here to test for QIF and other locally-supported formats // (i.e. not a plugin). If you add them here, be sure to add it to // the webConnect function. return result; } void KMyMoneyApp::slotFileOpenRecent(const QUrl &url) { KMSTATUS(i18n("Loading file...")); QUrl lastFile = d->m_fileName; // check if there are other instances which might have this file open QList list = instanceList(); QList::ConstIterator it; bool duplicate = false; #ifdef KMM_DBUS for (it = list.constBegin(); duplicate == false && it != list.constEnd(); ++it) { QDBusInterface remoteApp(*it, "/KMymoney", "org.kde.kmymoney"); QDBusReply reply = remoteApp.call("filename"); if (!reply.isValid()) { qDebug("D-Bus error while calling app->filename()"); } else { if (reply.value() == url.url()) { duplicate = true; } } } #endif if (!duplicate) { QUrl newurl = url; if ((newurl.scheme() == QLatin1String("sql"))) { const QString key = QLatin1String("driver"); // take care and convert some old url to their new counterpart QUrlQuery query(newurl); if (query.queryItemValue(key) == QLatin1String("QMYSQL3")) { // fix any old urls query.removeQueryItem(key); query.addQueryItem(key, QLatin1String("QMYSQL")); } if (query.queryItemValue(key) == QLatin1String("QSQLITE3")) { query.removeQueryItem(key); query.addQueryItem(key, QLatin1String("QSQLITE")); } newurl.setQuery(query); if (query.queryItemValue(key) == QLatin1String("QSQLITE")) { newurl.setUserInfo(QString()); newurl.setHost(QString()); } // check if a password is needed. it may be if the URL came from the last/recent file list QPointer dialog = new KSelectDatabaseDlg(QIODevice::ReadWrite, newurl); if (!dialog->checkDrivers()) { delete dialog; return; } // if we need to supply a password, then show the dialog // otherwise it isn't needed if ((query.queryItemValue("secure").toLower() == QLatin1String("yes")) && newurl.password().isEmpty()) { if (dialog->exec() == QDialog::Accepted && dialog != nullptr) { newurl = dialog->selectedURL(); } else { delete dialog; return; } } delete dialog; } // TODO: port KF5 (NetAccess) if ((newurl.scheme() == QLatin1String("sql")) || (newurl.isValid() /*&& KIO::NetAccess::exists(newurl, KIO::NetAccess::SourceSide, this)*/)) { slotFileClose(); if (!d->m_myMoneyView->fileOpen()) { try { if (d->m_myMoneyView->readFile(newurl)) { if ((d->m_myMoneyView->isNativeFile())) { d->m_fileName = newurl; updateCaption(); d->m_recentFiles->addUrl(newurl); writeLastUsedFile(newurl.toDisplayString(QUrl::PreferLocalFile)); } else { d->m_fileName = QUrl(); // imported files have no filename } // Check the schedules slotCheckSchedules(); } } catch (const MyMoneyException &e) { KMessageBox::sorry(this, i18n("Cannot open file as requested. Error was: %1", e.what())); } updateCaption(); emit fileLoaded(d->m_fileName); } else { /*fileOpen failed - should we do something or maybe fileOpen puts out the message... - it does for database*/ } } else { // newurl invalid slotFileClose(); KMessageBox::sorry(this, i18n("

%1 is either an invalid filename or the file does not exist. You can open another file or create a new one.

", url.toDisplayString(QUrl::PreferLocalFile)), i18n("File not found")); } } else { // isDuplicate KMessageBox::sorry(this, i18n("

File %1 is already opened in another instance of KMyMoney

", url.toDisplayString(QUrl::PreferLocalFile)), i18n("Duplicate open")); } } bool KMyMoneyApp::slotFileSave() { // if there's nothing changed, there's no need to save anything if (!d->m_myMoneyView->dirty()) return true; bool rc = false; KMSTATUS(i18n("Saving file...")); if (d->m_fileName.isEmpty()) return slotFileSaveAs(); d->consistencyCheck(false); /*if (myMoneyView->isDatabase()) { rc = myMoneyView->saveDatabase(m_fileName); // the 'save' function is no longer relevant for a database*/ setEnabled(false); rc = d->m_myMoneyView->saveFile(d->m_fileName, MyMoneyFile::instance()->value("kmm-encryption-key")); setEnabled(true); d->m_autoSaveTimer->stop(); updateCaption(); return rc; } void KMyMoneyApp::slotFileSaveAsFilterChanged(const QString& filter) { if (!d->m_saveEncrypted) return; if (filter.compare(QLatin1String("*.kmy"), Qt::CaseInsensitive) != 0) { d->m_saveEncrypted->setCurrentItem(0); d->m_saveEncrypted->setEnabled(false); } else { d->m_saveEncrypted->setEnabled(true); } } void KMyMoneyApp::slotManageGpgKeys() { QPointer dlg = new KGpgKeySelectionDlg(this); dlg->setKeys(d->m_additionalGpgKeys); if (dlg->exec() == QDialog::Accepted && dlg != 0) { d->m_additionalGpgKeys = dlg->keys(); d->m_additionalKeyLabel->setText(i18n("Additional encryption keys to be used: %1", d->m_additionalGpgKeys.count())); } delete dlg; } void KMyMoneyApp::slotKeySelected(int idx) { int cnt = 0; if (idx != 0) { cnt = d->m_additionalGpgKeys.count(); } d->m_additionalKeyLabel->setEnabled(idx != 0); d->m_additionalKeyButton->setEnabled(idx != 0); d->m_additionalKeyLabel->setText(i18n("Additional encryption keys to be used: %1", cnt)); } bool KMyMoneyApp::slotFileSaveAs() { bool rc = false; // in event of it being a database, ensure that all data is read into storage for saveas if (d->m_myMoneyView->isDatabase()) dynamic_cast(MyMoneyFile::instance()->storage())->fillStorage(); KMSTATUS(i18n("Saving file with a new filename...")); // fill the additional key list with the default d->m_additionalGpgKeys = KMyMoneyGlobalSettings::gpgRecipientList(); QWidget* vbox = new QWidget(); QVBoxLayout *vboxVBoxLayout = new QVBoxLayout(vbox); vboxVBoxLayout->setMargin(0); if (KGPGFile::GPGAvailable()) { QWidget* keyBox = new QWidget(vbox); QHBoxLayout *keyBoxHBoxLayout = new QHBoxLayout(keyBox); keyBoxHBoxLayout->setMargin(0); vboxVBoxLayout->addWidget(keyBox); QLabel *keyLabel = new QLabel(i18n("Encryption key to be used"), keyBox); keyBoxHBoxLayout->addWidget(keyLabel); d->m_saveEncrypted = new KComboBox(keyBox); keyBoxHBoxLayout->addWidget(d->m_saveEncrypted); QWidget* labelBox = new QWidget(vbox); QHBoxLayout *labelBoxHBoxLayout = new QHBoxLayout(labelBox); labelBoxHBoxLayout->setMargin(0); vboxVBoxLayout->addWidget(labelBox); d->m_additionalKeyLabel = new QLabel(i18n("Additional encryption keys to be used: %1", d->m_additionalGpgKeys.count()), labelBox); labelBoxHBoxLayout->addWidget(d->m_additionalKeyLabel); d->m_additionalKeyButton = new QPushButton(i18n("Manage additional keys"), labelBox); labelBoxHBoxLayout->addWidget(d->m_additionalKeyButton); connect(d->m_additionalKeyButton, SIGNAL(clicked()), this, SLOT(slotManageGpgKeys())); connect(d->m_saveEncrypted, SIGNAL(activated(int)), this, SLOT(slotKeySelected(int))); // fill the secret key list and combo box QStringList keyList; KGPGFile::secretKeyList(keyList); d->m_saveEncrypted->addItem(i18n("No encryption")); for (QStringList::iterator it = keyList.begin(); it != keyList.end(); ++it) { QStringList fields = (*it).split(':', QString::SkipEmptyParts); if (fields[0] != recoveryKeyId) { // replace parenthesis in name field with brackets QString name = fields[1]; name.replace('(', "["); name.replace(')', "]"); name = QString("%1 (0x%2)").arg(name).arg(fields[0]); d->m_saveEncrypted->addItem(name); if (name.contains(KMyMoneyGlobalSettings::gpgRecipient())) { d->m_saveEncrypted->setCurrentItem(name); } } } } QString prevDir; // don't prompt file name if not a native file if (d->m_myMoneyView->isNativeFile()) prevDir = readLastUsedDir(); QPointer dlg = new QFileDialog(this, i18n("Save As"), prevDir, QString(QLatin1String("%2 (%1);;")).arg(QStringLiteral("*.kmy")).arg(i18nc("KMyMoney (Filefilter)", "KMyMoney files")) + QString(QLatin1String("%2 (%1);;")).arg(QStringLiteral("*.xml")).arg(i18nc("XML (Filefilter)", "XML files")) + QString(QLatin1String("%2 (%1);;")).arg(QStringLiteral("*.anon.xml")).arg(i18nc("Anonymous (Filefilter)", "Anonymous files")) + QString(QLatin1String("%2 (%1);;")).arg(QStringLiteral("*")).arg(i18nc("All files (Filefilter)", "All files"))); dlg->setAcceptMode(QFileDialog::AcceptSave); connect(dlg, SIGNAL(filterChanged(QString)), this, SLOT(slotFileSaveAsFilterChanged(QString))); if (dlg->exec() == QDialog::Accepted && dlg != 0) { QUrl newURL = dlg->selectedUrls().first(); if (!newURL.fileName().isEmpty()) { d->consistencyCheck(false); // deleting the dialog will delete the combobox pointed to by d->m_saveEncrypted so get the key name here QString selectedKeyName; if (d->m_saveEncrypted && d->m_saveEncrypted->currentIndex() != 0) selectedKeyName = d->m_saveEncrypted->currentText(); d->m_saveEncrypted = 0; QString newName = newURL.toDisplayString(QUrl::PreferLocalFile); // append extension if not present if (!newName.endsWith(QLatin1String(".kmy"), Qt::CaseInsensitive) && !newName.endsWith(QLatin1String(".xml"), Qt::CaseInsensitive)) newName.append(QLatin1String(".kmy")); newURL = QUrl::fromUserInput(newName); d->m_recentFiles->addUrl(newURL); setEnabled(false); // If this is the anonymous file export, just save it, don't actually take the // name, or remember it! Don't even try to encrypt it if (newName.endsWith(QLatin1String(".anon.xml"), Qt::CaseInsensitive)) rc = d->m_myMoneyView->saveFile(newURL); else { d->m_fileName = newURL; QString encryptionKeys; QRegExp keyExp(".* \\((.*)\\)"); if (keyExp.indexIn(selectedKeyName) != -1) { encryptionKeys = keyExp.cap(1); } if (!d->m_additionalGpgKeys.isEmpty()) { if (!encryptionKeys.isEmpty()) encryptionKeys.append(QLatin1Char(',')); encryptionKeys.append(d->m_additionalGpgKeys.join(QLatin1Char(','))); } rc = d->m_myMoneyView->saveFile(d->m_fileName, encryptionKeys); //write the directory used for this file as the default one for next time. writeLastUsedDir(newURL.toDisplayString(QUrl::RemoveFilename | QUrl::PreferLocalFile | QUrl::StripTrailingSlash)); writeLastUsedFile(newName); } d->m_autoSaveTimer->stop(); setEnabled(true); } } delete dlg; updateCaption(); return rc; } void KMyMoneyApp::slotSaveAsDatabase() { saveAsDatabase(); } bool KMyMoneyApp::saveAsDatabase() { bool rc = false; QUrl oldUrl; // in event of it being a database, ensure that all data is read into storage for saveas if (d->m_myMoneyView->isDatabase()) { dynamic_cast(MyMoneyFile::instance()->storage())->fillStorage(); oldUrl = d->m_fileName.isEmpty() ? lastOpenedURL() : d->m_fileName; } KMSTATUS(i18n("Saving file to database...")); QPointer dialog = new KSelectDatabaseDlg(QIODevice::WriteOnly); QUrl url = oldUrl; if (!dialog->checkDrivers()) { delete dialog; return (false); } while (oldUrl == url && dialog->exec() == QDialog::Accepted && dialog != 0) { url = dialog->selectedURL(); // If the protocol is SQL for the old and new, and the hostname and database names match // Let the user know that the current database cannot be saved on top of itself. if (url.scheme() == "sql" && oldUrl.scheme() == "sql" && oldUrl.host() == url.host() && QUrlQuery(oldUrl).queryItemValue("driver") == QUrlQuery(url).queryItemValue("driver") && oldUrl.path().right(oldUrl.path().length() - 1) == url.path().right(url.path().length() - 1)) { KMessageBox::sorry(this, i18n("Cannot save to current database.")); } else { try { rc = d->m_myMoneyView->saveAsDatabase(url); } catch (const MyMoneyException &e) { KMessageBox::sorry(this, i18n("Cannot save to current database: %1", e.what())); } } } delete dialog; if (rc) { //KRecentFilesAction *p = dynamic_cast(action("file_open_recent")); //if(p) d->m_recentFiles->addUrl(url); writeLastUsedFile(url.toDisplayString(QUrl::PreferLocalFile)); } d->m_autoSaveTimer->stop(); updateCaption(); return rc; } void KMyMoneyApp::slotFileCloseWindow() { KMSTATUS(i18n("Closing window...")); if (d->m_myMoneyView->dirty()) { int answer = askSaveOnClose(); if (answer == KMessageBox::Cancel) return; else if (answer == KMessageBox::Yes) slotFileSave(); } close(); } void KMyMoneyApp::slotFileClose() { bool okToSelect = true; // check if transaction editor is open and ask user what he wants to do slotTransactionsCancelOrEnter(okToSelect); if (!okToSelect) return; // no update status here, as we might delete the status too early. if (d->m_myMoneyView->dirty()) { int answer = askSaveOnClose(); if (answer == KMessageBox::Cancel) return; else if (answer == KMessageBox::Yes) slotFileSave(); } d->closeFile(); } void KMyMoneyApp::slotFileQuit() { // don't modify the status message here as this will prevent quit from working!! // See the beginning of queryClose() and isReady() why. Thomas Baumgart 2005-10-17 bool quitApplication = true; QList memberList = KMainWindow::memberList(); if (!memberList.isEmpty()) { QList::const_iterator w_it = memberList.constBegin(); for (; w_it != memberList.constEnd(); ++w_it) { // only close the window if the closeEvent is accepted. If the user presses Cancel on the saveModified() dialog, // the window and the application stay open. if (!(*w_it)->close()) { quitApplication = false; break; } } } // We will only quit if all windows were processed and not cancelled if (quitApplication) { QCoreApplication::quit(); } } void KMyMoneyApp::slotShowTransactionDetail() { } void KMyMoneyApp::slotHideReconciledTransactions() { KMyMoneyGlobalSettings::setHideReconciledTransactions(actionCollection()->action(s_Actions[Action::ViewHideReconciled])->isChecked()); d->m_myMoneyView->slotRefreshViews(); } void KMyMoneyApp::slotHideUnusedCategories() { KMyMoneyGlobalSettings::setHideUnusedCategory(actionCollection()->action(s_Actions[Action::ViewHideCategories])->isChecked()); d->m_myMoneyView->slotRefreshViews(); } void KMyMoneyApp::slotShowAllAccounts() { d->m_myMoneyView->slotRefreshViews(); } #ifdef KMM_DEBUG void KMyMoneyApp::slotToggleTraces() { MyMoneyTracer::onOff(actionCollection()->action(s_Actions[Action::DebugTraces])->isChecked() ? 1 : 0); } #endif void KMyMoneyApp::slotToggleTimers() { extern bool timersOn; // main.cpp timersOn = actionCollection()->action(s_Actions[Action::DebugTimers])->isChecked(); } QString KMyMoneyApp::slotStatusMsg(const QString &text) { /////////////////////////////////////////////////////////////////// // change status message permanently QString previousMessage = d->m_statusLabel->text(); d->m_applicationIsReady = false; QString currentMessage = text; if (currentMessage.isEmpty() || currentMessage == i18nc("Application is ready to use", "Ready.")) { d->m_applicationIsReady = true; currentMessage = i18nc("Application is ready to use", "Ready."); } statusBar()->clearMessage(); d->m_statusLabel->setText(currentMessage); return previousMessage; } void KMyMoneyApp::ready() { slotStatusMsg(QString()); } bool KMyMoneyApp::isReady() { return d->m_applicationIsReady; } void KMyMoneyApp::slotStatusProgressBar(int current, int total) { if (total == -1 && current == -1) { // reset if (d->m_progressTimer) { d->m_progressTimer->start(500); // remove from screen in 500 msec d->m_progressBar->setValue(d->m_progressBar->maximum()); } } else if (total != 0) { // init d->m_progressTimer->stop(); d->m_progressBar->setMaximum(total); d->m_progressBar->setValue(0); d->m_progressBar->show(); } else { // update QTime currentTime = QTime::currentTime(); // only process painting if last update is at least 250 ms ago if (abs(d->m_lastUpdate.msecsTo(currentTime)) > 250) { d->m_progressBar->setValue(current); d->m_lastUpdate = currentTime; } } } void KMyMoneyApp::slotStatusProgressDone() { d->m_progressTimer->stop(); d->m_progressBar->reset(); d->m_progressBar->hide(); d->m_progressBar->setValue(0); } void KMyMoneyApp::progressCallback(int current, int total, const QString& msg) { if (!msg.isEmpty()) kmymoney->slotStatusMsg(msg); kmymoney->slotStatusProgressBar(current, total); } void KMyMoneyApp::slotFileViewPersonal() { if (!d->m_myMoneyView->fileOpen()) { KMessageBox::information(this, i18n("No KMyMoneyFile open")); return; } KMSTATUS(i18n("Viewing personal data...")); MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyPayee user = file->user(); QPointer editPersonalDataDlg = new EditPersonalDataDlg(user.name(), user.address(), user.city(), user.state(), user.postcode(), user.telephone(), user.email(), this, i18n("Edit Personal Data")); if (editPersonalDataDlg->exec() == QDialog::Accepted && editPersonalDataDlg != 0) { user.setName(editPersonalDataDlg->userName()); user.setAddress(editPersonalDataDlg->userStreet()); user.setCity(editPersonalDataDlg->userTown()); user.setState(editPersonalDataDlg->userCountry()); user.setPostcode(editPersonalDataDlg->userPostcode()); user.setTelephone(editPersonalDataDlg->userTelephone()); user.setEmail(editPersonalDataDlg->userEmail()); MyMoneyFileTransaction ft; try { file->setUser(user); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Unable to store user information: %1", e.what())); } } delete editPersonalDataDlg; } void KMyMoneyApp::slotFileFileInfo() { if (!d->m_myMoneyView->fileOpen()) { KMessageBox::information(this, i18n("No KMyMoneyFile open")); return; } QFile g("kmymoney.dump"); g.open(QIODevice::WriteOnly); QDataStream st(&g); MyMoneyStorageDump dumper; dumper.writeStream(st, dynamic_cast(MyMoneyFile::instance()->storage())); g.close(); } void KMyMoneyApp::slotLoadAccountTemplates() { KMSTATUS(i18n("Importing account templates.")); int rc; QPointer dlg = new KLoadTemplateDlg(); if ((rc = dlg->exec()) == QDialog::Accepted && dlg != 0) { MyMoneyFileTransaction ft; try { // import the account templates QList templates = dlg->templates(); QList::iterator it_t; for (it_t = templates.begin(); it_t != templates.end(); ++it_t) { (*it_t).importTemplate(&progressCallback); } ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to import template(s): %1, thrown in %2:%3", e.what(), e.file(), e.line())); } } delete dlg; } void KMyMoneyApp::slotSaveAccountTemplates() { KMSTATUS(i18n("Exporting account templates.")); QString savePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/templates/" + QLocale().name(); QDir d(savePath); if (!d.exists()) d.mkpath(savePath); QString newName = QFileDialog::getSaveFileName(this, i18n("Save as..."), savePath, i18n("KMyMoney template files (*.kmt);;All files (*)")); // // If there is no file extension, then append a .kmt at the end of the file name. // If there is a file extension, make sure it is .kmt, delete any others. // if (!newName.isEmpty()) { // find last . delimiter int nLoc = newName.lastIndexOf('.'); if (nLoc != -1) { QString strExt, strTemp; strTemp = newName.left(nLoc + 1); strExt = newName.right(newName.length() - (nLoc + 1)); if ((strExt.indexOf("kmt", 0, Qt::CaseInsensitive) == -1)) { strTemp.append("kmt"); //append to make complete file name newName = strTemp; } } else { newName.append(".kmt"); } if (okToWriteFile(QUrl::fromLocalFile(newName))) { QPointer dlg = new KTemplateExportDlg(this); if (dlg->exec() == QDialog::Accepted && dlg) { MyMoneyTemplate templ; templ.setTitle(dlg->title()); templ.setShortDescription(dlg->shortDescription()); templ.setLongDescription(dlg->longDescription()); templ.exportTemplate(&progressCallback); templ.saveTemplate(QUrl::fromLocalFile(newName)); } delete dlg; } } } void KMyMoneyApp::slotGncImport() { if (d->m_myMoneyView->fileOpen()) { switch (KMessageBox::questionYesNoCancel(0, i18n("You cannot import GnuCash data into an existing file. Do you wish to save this file?"), PACKAGE)) { case KMessageBox::Yes: slotFileSave(); break; case KMessageBox::No: d->closeFile(); break; default: return; } } KMSTATUS(i18n("Importing a GnuCash file.")); QUrl fileToRead = QFileDialog::getOpenFileUrl(this, QString(), QUrl(), i18n("GnuCash files (*.gnucash *.xac *.gnc);;All files (*)")); if (!fileToRead.isEmpty()) { // call the importer if (d->m_myMoneyView->readFile(fileToRead)) { // imported files don't have a name d->m_fileName = QUrl(); updateCaption(); emit fileLoaded(d->m_fileName); } } } void KMyMoneyApp::slotAccountChart() { if (!d->m_selectedAccount.id().isEmpty()) { QPointer dlg = new KBalanceChartDlg(d->m_selectedAccount, this); dlg->exec(); delete dlg; } } // // KMyMoneyApp::slotStatementImport() is for testing only. The MyMoneyStatement // is not intended to be exposed to users in XML form. // void KMyMoneyApp::slotStatementImport() { bool result = false; KMSTATUS(i18n("Importing an XML Statement.")); QList files{QFileDialog::getOpenFileUrls(this, QString(), QUrl(), i18n("XML files (*.xml);;All files (*)"))}; if (!files.isEmpty()) { d->m_collectingStatements = (files.count() > 1); foreach (const QUrl &url, files) { qDebug("Processing '%s'", qPrintable(url.path())); result |= slotStatementImport(url.path()); } /* QFile f( dialog->selectedURL().path() ); f.open( QIODevice::ReadOnly ); QString error = "Unable to parse file"; QDomDocument* doc = new QDomDocument; if(doc->setContent(&f, FALSE)) { if ( doc->doctype().name() == "KMYMONEY-STATEMENT" ) { QDomElement rootElement = doc->documentElement(); if(!rootElement.isNull()) { QDomNode child = rootElement.firstChild(); if(!child.isNull() && child.isElement()) { MyMoneyStatement s; if ( s.read(child.toElement()) ) result = slotStatementImport(s); else error = "File does not contain any statements"; } } } else error = "File is not a KMyMoney Statement"; } delete doc; if ( !result ) { QMessageBox::critical( this, i18n("Critical Error"), i18n("Unable to read file %1: %2").arg( dialog->selectedURL().path()).arg(error), QMessageBox::Ok, 0 ); }*/ } if (!result) { // re-enable all standard widgets setEnabled(true); } } bool KMyMoneyApp::slotStatementImport(const QString& url) { bool result = false; MyMoneyStatement s; if (MyMoneyStatement::readXMLFile(s, url)) result = slotStatementImport(s); else KMessageBox::error(this, i18n("Error importing %1: This file is not a valid KMM statement file.", url), i18n("Invalid Statement")); return result; } bool KMyMoneyApp::slotStatementImport(const MyMoneyStatement& s, bool silent) { bool result = false; // keep a copy of the statement if (KMyMoneySettings::logImportedStatements()) { QString logFile = QString("%1/kmm-statement-%2.txt").arg(KMyMoneySettings::logPath()).arg(d->m_statementXMLindex++); MyMoneyStatement::writeXMLFile(s, logFile); } // we use an object on the heap here, so that we can check the presence // of it during slotUpdateActions() by looking at the pointer. d->m_smtReader = new MyMoneyStatementReader; d->m_smtReader->setAutoCreatePayee(true); d->m_smtReader->setProgressCallback(&progressCallback); // disable all standard widgets during the import setEnabled(false); QStringList messages; result = d->m_smtReader->import(s, messages); bool transactionAdded = d->m_smtReader->anyTransactionAdded(); // get rid of the statement reader and tell everyone else // about the destruction by setting the pointer to zero delete d->m_smtReader; d->m_smtReader = 0; slotStatusProgressBar(-1, -1); ready(); // re-enable all standard widgets setEnabled(true); if (!d->m_collectingStatements && !silent) KMessageBox::informationList(this, i18n("The statement has been processed with the following results:"), messages, i18n("Statement stats")); else if (transactionAdded) d->m_statementResults += messages; slotUpdateActions();// Re-enable menu items after import via plugin. return result; } bool KMyMoneyApp::okToWriteFile(const QUrl &url) { Q_UNUSED(url) // check if the file exists and warn the user bool reallySaveFile = true; // TODO: port KF5 (NetAccess) //if (KIO::NetAccess::exists(url, KIO::NetAccess::SourceSide, this)) { // if (KMessageBox::warningYesNo(this, QLatin1String("") + i18n("The file %1 already exists. Do you really want to overwrite it?", url.toDisplayString(QUrl::PreferLocalFile)) + QLatin1String(""), i18n("File already exists")) != KMessageBox::Yes) // reallySaveFile = false; //} return reallySaveFile; } void KMyMoneyApp::slotSettings() { // if we already have an instance of the settings dialog, then use it if (KConfigDialog::showDialog("KMyMoney-Settings")) return; // otherwise, we have to create it KConfigDialog* dlg = new KSettingsKMyMoney(this, "KMyMoney-Settings", KMyMoneyGlobalSettings::self()); connect(dlg, &KConfigDialog::settingsChanged, this, &KMyMoneyApp::slotUpdateConfiguration); dlg->show(); } void KMyMoneyApp::slotShowCredits() { KAboutData aboutData = initializeCreditsData(); KAboutApplicationDialog dlg(aboutData, this); dlg.exec(); } void KMyMoneyApp::slotUpdateConfiguration() { MyMoneyTransactionFilter::setFiscalYearStart(KMyMoneyGlobalSettings::firstFiscalMonth(), KMyMoneyGlobalSettings::firstFiscalDay()); LedgerSeperator::setFirstFiscalDate(KMyMoneyGlobalSettings::firstFiscalMonth(), KMyMoneyGlobalSettings::firstFiscalDay()); d->m_myMoneyView->updateViewType(); // update the sql storage module settings MyMoneyStorageSql::setStartDate(KMyMoneyGlobalSettings::startDate().date()); // update the report module settings MyMoneyReport::setLineWidth(KMyMoneyGlobalSettings::lineWidth()); // update the holiday region configuration setHolidayRegion(KMyMoneyGlobalSettings::holidayRegion()); d->m_myMoneyView->slotRefreshViews(); // re-read autosave configuration d->m_autoSaveEnabled = KMyMoneyGlobalSettings::autoSaveFile(); d->m_autoSavePeriod = KMyMoneyGlobalSettings::autoSavePeriod(); // stop timer if turned off but running if (d->m_autoSaveTimer->isActive() && !d->m_autoSaveEnabled) { d->m_autoSaveTimer->stop(); } // start timer if turned on and needed but not running if (!d->m_autoSaveTimer->isActive() && d->m_autoSaveEnabled && d->m_myMoneyView->dirty()) { d->m_autoSaveTimer->setSingleShot(true); d->m_autoSaveTimer->start(d->m_autoSavePeriod * 60 * 1000); } d->setThemedCSS(); // check if the recovery key is still valid or expires soon if (KMyMoneySettings::writeDataEncrypted() && KMyMoneySettings::encryptRecover()) { if (KGPGFile::GPGAvailable()) { KGPGFile file; QDateTime expirationDate = file.keyExpires(QLatin1String(recoveryKeyId)); if (expirationDate.isValid() && QDateTime::currentDateTime().daysTo(expirationDate) <= RECOVER_KEY_EXPIRATION_WARNING) { bool skipMessage = false; //get global config object for our app. KSharedConfigPtr kconfig = KSharedConfig::openConfig(); KConfigGroup grp; QDate lastWarned; if (kconfig) { grp = d->m_config->group("General Options"); lastWarned = grp.readEntry("LastRecoverKeyExpirationWarning", QDate()); if (QDate::currentDate() == lastWarned) { skipMessage = true; } } if (!skipMessage) { if (kconfig) { grp.writeEntry("LastRecoverKeyExpirationWarning", QDate::currentDate()); } KMessageBox::information(this, i18np("You have configured KMyMoney to use GPG to protect your data and to encrypt your data also with the KMyMoney recover key. This key is about to expire in %1 day. Please update the key from a keyserver using your GPG frontend (e.g. KGPG).", "You have configured KMyMoney to use GPG to protect your data and to encrypt your data also with the KMyMoney recover key. This key is about to expire in %1 days. Please update the key from a keyserver using your GPG frontend (e.g. KGPG).", QDateTime::currentDateTime().daysTo(expirationDate)), i18n("Recover key expires soon")); } } } } } void KMyMoneyApp::slotBackupFile() { // Save the file first so isLocalFile() works if (d->m_myMoneyView && d->m_myMoneyView->dirty()) { if (KMessageBox::questionYesNo(this, i18n("The file must be saved first " "before it can be backed up. Do you want to continue?")) == KMessageBox::No) { return; } slotFileSave(); } if (d->m_fileName.isEmpty()) return; if (!d->m_fileName.isLocalFile()) { KMessageBox::sorry(this, i18n("The current implementation of the backup functionality only supports local files as source files. Your current source file is '%1'.", d->m_fileName.url()), i18n("Local files only")); return; } QPointer backupDlg = new KBackupDlg(this); #ifdef Q_OS_WIN backupDlg->mountCheckBox->setEnabled(false); #endif int returncode = backupDlg->exec(); if (returncode == QDialog::Accepted && backupDlg != 0) { d->m_backupMount = backupDlg->mountCheckBox(); d->m_proc.clearProgram(); d->m_backupState = BACKUP_MOUNTING; d->m_mountpoint = backupDlg->mountPoint(); if (d->m_backupMount) { slotBackupMount(); } else { progressCallback(0, 300, ""); #ifdef Q_OS_WIN d->m_ignoreBackupExitCode = true; QTimer::singleShot(0, this, SLOT(slotBackupHandleEvents())); #else // If we don't have to mount a device, we just issue // a dummy command to start the copy operation d->m_proc.setProgram("true"); d->m_proc.start(); #endif } } delete backupDlg; } void KMyMoneyApp::slotBackupMount() { progressCallback(0, 300, i18n("Mounting %1", d->m_mountpoint)); d->m_proc.setProgram("mount"); d->m_proc << d->m_mountpoint; d->m_proc.start(); } bool KMyMoneyApp::slotBackupWriteFile() { QFileInfo fi(d->m_fileName.fileName()); QString today = QDate::currentDate().toString("-yyyy-MM-dd.") + fi.suffix(); QString backupfile = d->m_mountpoint + '/' + d->m_fileName.fileName(); KMyMoneyUtils::appendCorrectFileExt(backupfile, today); // check if file already exists and ask what to do QFile f(backupfile); if (f.exists()) { int answer = KMessageBox::warningContinueCancel(this, i18n("Backup file for today exists on that device. Replace?"), i18n("Backup"), KGuiItem(i18n("&Replace"))); if (answer == KMessageBox::Cancel) { return false; } } progressCallback(50, 0, i18n("Writing %1", backupfile)); d->m_proc.clearProgram(); #ifdef Q_OS_WIN d->m_proc << "cmd.exe" << "/c" << "copy" << "/b" << "/y"; d->m_proc << (QDir::toNativeSeparators(d->m_fileName.toLocalFile()) + "+ nul") << QDir::toNativeSeparators(backupfile); #else d->m_proc << "cp" << "-f"; d->m_proc << d->m_fileName.toLocalFile() << backupfile; #endif d->m_backupState = BACKUP_COPYING; d->m_proc.start(); return true; } void KMyMoneyApp::slotBackupUnmount() { progressCallback(250, 0, i18n("Unmounting %1", d->m_mountpoint)); d->m_proc.clearProgram(); d->m_proc.setProgram("umount"); d->m_proc << d->m_mountpoint; d->m_backupState = BACKUP_UNMOUNTING; d->m_proc.start(); } void KMyMoneyApp::slotBackupFinish() { d->m_backupState = BACKUP_IDLE; progressCallback(-1, -1, QString()); ready(); } void KMyMoneyApp::slotBackupHandleEvents() { switch (d->m_backupState) { case BACKUP_MOUNTING: if (d->m_ignoreBackupExitCode || (d->m_proc.exitStatus() == QProcess::NormalExit && d->m_proc.exitCode() == 0)) { d->m_ignoreBackupExitCode = false; d->m_backupResult = 0; if (!slotBackupWriteFile()) { d->m_backupResult = 1; if (d->m_backupMount) slotBackupUnmount(); else slotBackupFinish(); } } else { KMessageBox::information(this, i18n("Error mounting device"), i18n("Backup")); d->m_backupResult = 1; if (d->m_backupMount) slotBackupUnmount(); else slotBackupFinish(); } break; case BACKUP_COPYING: if (d->m_proc.exitStatus() == QProcess::NormalExit && d->m_proc.exitCode() == 0) { if (d->m_backupMount) { slotBackupUnmount(); } else { progressCallback(300, 0, i18nc("Backup done", "Done")); KMessageBox::information(this, i18n("File successfully backed up"), i18n("Backup")); slotBackupFinish(); } } else { qDebug("copy exit code is %d", d->m_proc.exitCode()); d->m_backupResult = 1; KMessageBox::information(this, i18n("Error copying file to device"), i18n("Backup")); if (d->m_backupMount) slotBackupUnmount(); else slotBackupFinish(); } break; case BACKUP_UNMOUNTING: if (d->m_proc.exitStatus() == QProcess::NormalExit && d->m_proc.exitCode() == 0) { progressCallback(300, 0, i18nc("Backup done", "Done")); if (d->m_backupResult == 0) KMessageBox::information(this, i18n("File successfully backed up"), i18n("Backup")); } else { KMessageBox::information(this, i18n("Error unmounting device"), i18n("Backup")); } slotBackupFinish(); break; default: qWarning("Unknown state for backup operation!"); progressCallback(-1, -1, QString()); ready(); break; } } void KMyMoneyApp::slotShowTipOfTheDay() { KTipDialog::showTip(d->m_myMoneyView, "", true); } void KMyMoneyApp::slotShowPreviousView() { } void KMyMoneyApp::slotShowNextView() { } void KMyMoneyApp::slotGenerateSql() { QPointer editor = new KGenerateSqlDlg(this); editor->setObjectName("Generate Database SQL"); editor->exec(); delete editor; } void KMyMoneyApp::slotToolsStartKCalc() { QString cmd = KMyMoneyGlobalSettings::externalCalculator(); // if none is present, we fall back to the default if (cmd.isEmpty()) { #if defined(Q_OS_WIN32) cmd = QLatin1String("calc"); #elif defined(Q_OS_MAC) cmd = QLatin1String("open -a Calculator"); #else cmd = QLatin1String("kcalc"); #endif } KRun::runCommand(cmd, this); } void KMyMoneyApp::slotFindTransaction() { if (d->m_searchDlg == 0) { d->m_searchDlg = new KFindTransactionDlg(this); connect(d->m_searchDlg, SIGNAL(destroyed()), this, SLOT(slotCloseSearchDialog())); connect(d->m_searchDlg, SIGNAL(transactionSelected(QString,QString)), d->m_myMoneyView, SLOT(slotLedgerSelected(QString,QString))); } d->m_searchDlg->show(); d->m_searchDlg->raise(); d->m_searchDlg->activateWindow(); } void KMyMoneyApp::slotCloseSearchDialog() { if (d->m_searchDlg) d->m_searchDlg->deleteLater(); d->m_searchDlg = 0; } void KMyMoneyApp::createInstitution(MyMoneyInstitution& institution) { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyFileTransaction ft; try { file->addInstitution(institution); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Cannot add institution: %1", e.what())); } } void KMyMoneyApp::slotInstitutionNew() { MyMoneyInstitution institution; slotInstitutionNew(institution); } void KMyMoneyApp::slotInstitutionNew(MyMoneyInstitution& institution) { institution.clearId(); QPointer dlg = new KNewBankDlg(institution); if (dlg->exec() == QDialog::Accepted && dlg != 0) { institution = dlg->institution(); createInstitution(institution); } delete dlg; } void KMyMoneyApp::slotInstitutionEditEmpty() { slotInstitutionEdit(MyMoneyInstitution()); } void KMyMoneyApp::slotInstitutionEdit(const MyMoneyObject& obj) { if (typeid(obj) != typeid(MyMoneyInstitution)) return; // make sure the selected object has an id if (d->m_selectedInstitution.id().isEmpty()) return; try { MyMoneyFile* file = MyMoneyFile::instance(); //grab a pointer to the view, regardless of it being a account or institution view. MyMoneyInstitution institution = file->institution(d->m_selectedInstitution.id()); // bankSuccess is not checked anymore because d->m_file->institution will throw anyway QPointer dlg = new KNewBankDlg(institution); if (dlg->exec() == QDialog::Accepted && dlg != 0) { MyMoneyFileTransaction ft; try { file->modifyInstitution(dlg->institution()); ft.commit(); slotSelectInstitution(file->institution(dlg->institution().id())); } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Unable to store institution: %1", e.what())); } } delete dlg; } catch (const MyMoneyException &e) { if (!obj.id().isEmpty()) KMessageBox::information(this, i18n("Unable to edit institution: %1", e.what())); } } void KMyMoneyApp::slotInstitutionDelete() { MyMoneyFile *file = MyMoneyFile::instance(); try { MyMoneyInstitution institution = file->institution(d->m_selectedInstitution.id()); if ((KMessageBox::questionYesNo(this, i18n("

Do you really want to delete the institution %1?

", institution.name()))) == KMessageBox::No) return; MyMoneyFileTransaction ft; try { file->removeInstitution(institution); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Unable to delete institution: %1", e.what())); } } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Unable to delete institution: %1", e.what())); } } void KMyMoneyApp::createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal) { MyMoneyFile *file = MyMoneyFile::instance(); try { const MyMoneySecurity& sec = file->security(newAccount.currencyId()); // Check the opening balance if (openingBal.isPositive() && newAccount.accountGroup() == eMyMoney::Account::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(this, message); if (ans == KMessageBox::Yes) { openingBal = -openingBal; } else if (ans == KMessageBox::Cancel) return; } file->createAccount(newAccount, parentAccount, brokerageAccount, openingBal); } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Unable to add account: %1", e.what())); } } void KMyMoneyApp::slotCategoryNew(const QString& name, QString& id) { MyMoneyAccount account; account.setName(name); slotCategoryNew(account, MyMoneyFile::instance()->expense()); id = account.id(); } void KMyMoneyApp::slotCategoryNew(MyMoneyAccount& account, const MyMoneyAccount& parent) { if (KMessageBox::questionYesNo(this, QString("%1").arg(i18n("

The category %1 currently does not exist. Do you want to create it?

The parent account will default to %2 but can be changed in the following dialog.

", account.name(), parent.name())), i18n("Create category"), KStandardGuiItem::yes(), KStandardGuiItem::no(), "CreateNewCategories") == KMessageBox::Yes) { createCategory(account, parent); } else { // we should not keep the 'no' setting because that can confuse people like // I have seen in some usability tests. So we just delete it right away. KSharedConfigPtr kconfig = KSharedConfig::openConfig(); if (kconfig) { kconfig->group(QLatin1String("Notification Messages")).deleteEntry(QLatin1String("CreateNewCategories")); } } } void KMyMoneyApp::slotCategoryNew(MyMoneyAccount& account) { slotCategoryNew(account, MyMoneyAccount()); } void KMyMoneyApp::slotCategoryNew() { MyMoneyAccount parent; MyMoneyAccount account; // Preselect the parent account by looking at the current selected account/category if (!d->m_selectedAccount.id().isEmpty() && d->m_selectedAccount.isIncomeExpense()) { MyMoneyFile* file = MyMoneyFile::instance(); try { parent = file->account(d->m_selectedAccount.id()); } catch (const MyMoneyException &) { } } createCategory(account, parent); } void KMyMoneyApp::createCategory(MyMoneyAccount& account, const MyMoneyAccount& parent) { if (!parent.id().isEmpty()) { try { // make sure parent account exists MyMoneyFile::instance()->account(parent.id()); account.setParentAccountId(parent.id()); account.setAccountType(parent.accountType()); } catch (const MyMoneyException &) { } } QPointer dialog = new KNewAccountDlg(account, false, true, 0, i18n("Create a new Category")); dialog->setOpeningBalanceShown(false); dialog->setOpeningDateShown(false); if (dialog->exec() == QDialog::Accepted && dialog != 0) { MyMoneyAccount parentAccount, brokerageAccount; account = dialog->account(); parentAccount = dialog->parentAccount(); MyMoneyFile::instance()->createAccount(account, parentAccount, brokerageAccount, MyMoneyMoney()); } delete dialog; } void KMyMoneyApp::slotAccountNew() { MyMoneyAccount acc; acc.setInstitutionId(d->m_selectedInstitution.id()); acc.setOpeningDate(KMyMoneyGlobalSettings::firstFiscalDate()); slotAccountNew(acc); } void KMyMoneyApp::slotAccountNew(MyMoneyAccount& account) { NewAccountWizard::Wizard* wizard = new NewAccountWizard::Wizard(); connect(wizard, SIGNAL(createInstitution(MyMoneyInstitution&)), this, SLOT(slotInstitutionNew(MyMoneyInstitution&))); connect(wizard, SIGNAL(createAccount(MyMoneyAccount&)), this, SLOT(slotAccountNew(MyMoneyAccount&))); connect(wizard, SIGNAL(createPayee(QString,QString&)), this, SLOT(slotPayeeNew(QString,QString&))); connect(wizard, SIGNAL(createCategory(MyMoneyAccount&,MyMoneyAccount)), this, SLOT(slotCategoryNew(MyMoneyAccount&,MyMoneyAccount))); wizard->setAccount(account); if (wizard->exec() == QDialog::Accepted) { MyMoneyAccount acc = wizard->account(); if (!(acc == MyMoneyAccount())) { MyMoneyFileTransaction ft; MyMoneyFile* file = MyMoneyFile::instance(); try { // create the account MyMoneyAccount parent = wizard->parentAccount(); file->addAccount(acc, parent); // tell the wizard about the account id which it // needs to create a possible schedule and transactions wizard->setAccount(acc); // store a possible conversion rate for the currency if (acc.currencyId() != file->baseCurrency().id()) { file->addPrice(wizard->conversionRate()); } // create the opening balance transaction if any file->createOpeningBalanceTransaction(acc, wizard->openingBalance()); // create the payout transaction for loans if any MyMoneyTransaction payoutTransaction = wizard->payoutTransaction(); if (payoutTransaction.splits().count() > 0) { file->addTransaction(payoutTransaction); } // create a brokerage account if selected MyMoneyAccount brokerageAccount = wizard->brokerageAccount(); if (!(brokerageAccount == MyMoneyAccount())) { file->addAccount(brokerageAccount, parent); } // create a possible schedule MyMoneySchedule sch = wizard->schedule(); if (!(sch == MyMoneySchedule())) { MyMoneyFile::instance()->addSchedule(sch); if (acc.isLoan()) { MyMoneyAccountLoan accLoan = MyMoneyFile::instance()->account(acc.id()); accLoan.setSchedule(sch.id()); acc = accLoan; MyMoneyFile::instance()->modifyAccount(acc); } } ft.commit(); account = acc; } catch (const MyMoneyException &e) { KMessageBox::error(this, i18n("Unable to create account: %1", e.what())); } } } delete wizard; } void KMyMoneyApp::slotInvestmentNew(MyMoneyAccount& account, const MyMoneyAccount& parent) { QString dontShowAgain = "CreateNewInvestments"; if (KMessageBox::questionYesNo(this, QString("") + i18n("The security %1 currently does not exist as sub-account of %2. " "Do you want to create it?", account.name(), parent.name()) + QString(""), i18n("Create security"), KStandardGuiItem::yes(), KStandardGuiItem::no(), dontShowAgain) == KMessageBox::Yes) { KNewInvestmentWizard dlg; dlg.setName(account.name()); if (dlg.exec() == QDialog::Accepted) { dlg.createObjects(parent.id()); account = dlg.account(); } } else { // in case the user said no but turned on the don't show again selection, we will enable // the message no matter what. Otherwise, the user is not able to use this feature // in the future anymore. KMessageBox::enableMessage(dontShowAgain); } } void KMyMoneyApp::slotInvestmentNew() { QPointer dlg = new KNewInvestmentWizard(this); if (dlg->exec() == QDialog::Accepted) dlg->createObjects(d->m_selectedAccount.id()); delete dlg; } void KMyMoneyApp::slotInvestmentEdit() { QPointer dlg = new KNewInvestmentWizard(d->m_selectedInvestment); if (dlg->exec() == QDialog::Accepted) dlg->createObjects(d->m_selectedAccount.id()); delete dlg; } void KMyMoneyApp::slotInvestmentDelete() { if (KMessageBox::questionYesNo(this, i18n("

Do you really want to delete the investment %1?

", d->m_selectedInvestment.name()), i18n("Delete investment"), KStandardGuiItem::yes(), KStandardGuiItem::no(), "DeleteInvestment") == KMessageBox::Yes) { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyFileTransaction ft; try { d->m_selectedAccount = MyMoneyAccount(); // CAUTION: deleting equity from investments view needs this, if ID of the equity to be deleted is the smallest from all file->removeAccount(d->m_selectedInvestment); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Unable to delete investment: %1", e.what())); } } else { // we should not keep the 'no' setting because that can confuse people like // I have seen in some usability tests. So we just delete it right away. KSharedConfigPtr kconfig = KSharedConfig::openConfig(); if (kconfig) { kconfig->group(QLatin1String("Notification Messages")).deleteEntry(QLatin1String("DeleteInvestment")); } } } void KMyMoneyApp::slotOnlinePriceUpdate() { if (!d->m_selectedInvestment.id().isEmpty()) { QPointer dlg = new KEquityPriceUpdateDlg(0, d->m_selectedInvestment.currencyId()); if (dlg->exec() == QDialog::Accepted && dlg != 0) { dlg->storePrices(); } delete dlg; } } void KMyMoneyApp::slotManualPriceUpdate() { if (!d->m_selectedInvestment.id().isEmpty()) { try { MyMoneySecurity security = MyMoneyFile::instance()->security(d->m_selectedInvestment.currencyId()); MyMoneySecurity currency = MyMoneyFile::instance()->security(security.tradingCurrency()); const MyMoneyPrice &price = MyMoneyFile::instance()->price(security.id(), currency.id()); QPointer calc = new KCurrencyCalculator(security, currency, MyMoneyMoney::ONE, price.rate(currency.id()), price.date(), MyMoneyMoney::precToDenom(security.pricePrecision())); calc->setupPriceEditor(); // The dialog takes care of adding the price if necessary calc->exec(); delete calc; } catch (const MyMoneyException &e) { qDebug("Error in price update: %s", qPrintable(e.what())); } } } void KMyMoneyApp::createSchedule(MyMoneySchedule newSchedule, MyMoneyAccount& newAccount) { MyMoneyFile* file = MyMoneyFile::instance(); // Add the schedule only if one exists // // Remember to modify the first split to reference the newly created account if (!newSchedule.name().isEmpty()) { try { // We assume at least 2 splits in the transaction MyMoneyTransaction t = newSchedule.transaction(); if (t.splitCount() < 2) { throw MYMONEYEXCEPTION("Transaction for schedule has less than 2 splits!"); } MyMoneyFileTransaction ft; try { file->addSchedule(newSchedule); // in case of a loan account, we keep a reference to this // schedule in the account if (newAccount.accountType() == eMyMoney::Account::Loan || newAccount.accountType() == eMyMoney::Account::AssetLoan) { newAccount.setValue("schedule", newSchedule.id()); file->modifyAccount(newAccount); } ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Unable to add scheduled transaction: %1", e.what())); } } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Unable to add scheduled transaction: %1", e.what())); } } } void KMyMoneyApp::slotAccountDelete() { if (d->m_selectedAccount.id().isEmpty()) return; // need an account ID MyMoneyFile* file = MyMoneyFile::instance(); // can't delete standard accounts or account which still have transactions assigned if (file->isStandardAccount(d->m_selectedAccount.id())) return; // check if the account is referenced by a transaction or schedule QBitArray skip((int)eStorage::Reference::Count); skip.fill(false); skip.setBit((int)eStorage::Reference::Account); skip.setBit((int)eStorage::Reference::Institution); skip.setBit((int)eStorage::Reference::Payee); skip.setBit((int)eStorage::Reference::Tag); skip.setBit((int)eStorage::Reference::Security); skip.setBit((int)eStorage::Reference::Currency); skip.setBit((int)eStorage::Reference::Price); bool hasReference = file->isReferenced(d->m_selectedAccount, skip); // make sure we only allow transactions in a 'category' (income/expense account) switch (d->m_selectedAccount.accountType()) { case eMyMoney::Account::Income: case eMyMoney::Account::Expense: break; default: // if the account is still referenced if (hasReference) { return; } break; } // if we get here and still have transactions referencing the account, we // need to check with the user to possibly re-assign them to a different account bool needAskUser = true; bool exit = false; MyMoneyFileTransaction ft; if (hasReference) { // show transaction reassignment dialog needAskUser = false; KCategoryReassignDlg* dlg = new KCategoryReassignDlg(this); QString categoryId = dlg->show(d->m_selectedAccount); delete dlg; // and kill the dialog if (categoryId.isEmpty()) return; // the user aborted the dialog, so let's abort as well MyMoneyAccount newCategory = file->account(categoryId); try { { KMSTATUS(i18n("Adjusting transactions...")); /* d->m_selectedAccount.id() is the old id, categoryId the new one Now search all transactions and schedules that reference d->m_selectedAccount.id() and replace that with categoryId. */ // get the list of all transactions that reference the old account MyMoneyTransactionFilter filter(d->m_selectedAccount.id()); filter.setReportAllSplits(false); QList tlist; QList::iterator it_t; file->transactionList(tlist, filter); slotStatusProgressBar(0, tlist.count()); int cnt = 0; for (it_t = tlist.begin(); it_t != tlist.end(); ++it_t) { slotStatusProgressBar(++cnt, 0); MyMoneyTransaction t = (*it_t); if (t.replaceId(categoryId, d->m_selectedAccount.id())) file->modifyTransaction(t); } slotStatusProgressBar(tlist.count(), 0); } // now fix all schedules { KMSTATUS(i18n("Adjusting scheduled transactions...")); QList slist = file->scheduleList(d->m_selectedAccount.id()); QList::iterator it_s; int cnt = 0; slotStatusProgressBar(0, slist.count()); for (it_s = slist.begin(); it_s != slist.end(); ++it_s) { slotStatusProgressBar(++cnt, 0); MyMoneySchedule sch = (*it_s); if (sch.replaceId(categoryId, d->m_selectedAccount.id())) { file->modifySchedule(sch); } } slotStatusProgressBar(slist.count(), 0); } // now fix all budgets { KMSTATUS(i18n("Adjusting budgets...")); QList blist = file->budgetList(); QList::const_iterator it_b; for (it_b = blist.constBegin(); it_b != blist.constEnd(); ++it_b) { if ((*it_b).hasReferenceTo(d->m_selectedAccount.id())) { MyMoneyBudget b = (*it_b); MyMoneyBudget::AccountGroup fromBudget = b.account(d->m_selectedAccount.id()); MyMoneyBudget::AccountGroup toBudget = b.account(categoryId); toBudget += fromBudget; b.setAccount(toBudget, categoryId); b.removeReference(d->m_selectedAccount.id()); file->modifyBudget(b); } } slotStatusProgressBar(blist.count(), 0); } } catch (MyMoneyException &e) { KMessageBox::error(this, i18n("Unable to exchange category %1 with category %2. Reason: %3", d->m_selectedAccount.name(), newCategory.name(), e.what())); exit = true; } slotStatusProgressBar(-1, -1); } if (exit) return; // retain the account name for a possible later usage in the error message box // since the account removal notifies the views the selected account can be changed // so we make sure by doing this that we display the correct name in the error message QString selectedAccountName = d->m_selectedAccount.name(); // at this point, we must not have a reference to the account // to be deleted anymore switch (d->m_selectedAccount.accountGroup()) { // special handling for categories to allow deleting of empty subcategories case eMyMoney::Account::Income: case eMyMoney::Account::Expense: { // open a compound statement here to be able to declare variables // which would otherwise not work within a case label. // case A - only a single, unused category without subcats selected if (d->m_selectedAccount.accountList().isEmpty()) { if (!needAskUser || (KMessageBox::questionYesNo(this, QString("") + i18n("Do you really want to delete category %1?", selectedAccountName) + QString("")) == KMessageBox::Yes)) { try { file->removeAccount(d->m_selectedAccount); d->m_selectedAccount.clearId(); slotUpdateActions(); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::error(this, QString("") + i18n("Unable to delete category %1. Cause: %2", selectedAccountName, e.what()) + QString("")); } } return; } // case B - we have some subcategories, maybe the user does not want to // delete them all, but just the category itself? MyMoneyAccount parentAccount = file->account(d->m_selectedAccount.parentAccountId()); QStringList accountsToReparent; int result = KMessageBox::questionYesNoCancel(this, QString("") + i18n("Do you want to delete category %1 with all its sub-categories or only " "the category itself? If you only delete the category itself, all its sub-categories " "will be made sub-categories of %2.", selectedAccountName, parentAccount.name()) + QString(""), QString(), KGuiItem(i18n("Delete all")), KGuiItem(i18n("Just the category"))); if (result == KMessageBox::Cancel) return; // cancel pressed? ok, no delete then... // "No" means "Just the category" and that means we need to reparent all subaccounts bool need_confirmation = false; // case C - User only wants to delete the category itself if (result == KMessageBox::No) accountsToReparent = d->m_selectedAccount.accountList(); else { // case D - User wants to delete all subcategories, now check all subcats of // d->m_selectedAccount and remember all that cannot be deleted and // must be "reparented" foreach (const auto accountID, d->m_selectedAccount.accountList()) { // reparent account if a transaction is assigned if (file->transactionCount(accountID) != 0) accountsToReparent.push_back(accountID); else if (!file->account(accountID).accountList().isEmpty()) { // or if we have at least one sub-account that is used for transactions if (!file->hasOnlyUnusedAccounts(file->account(accountID).accountList())) { accountsToReparent.push_back(accountID); //qDebug() << "subaccount not empty"; } } } if (!accountsToReparent.isEmpty()) need_confirmation = true; } if (!accountsToReparent.isEmpty() && need_confirmation) { if (KMessageBox::questionYesNo(this, i18n("

Some sub-categories of category %1 cannot " "be deleted, because they are still used. They will be made sub-categories of %2. Proceed?

", selectedAccountName, parentAccount.name())) != KMessageBox::Yes) { return; // user gets wet feet... } } // all good, now first reparent selected sub-categories try { MyMoneyAccount parent = file->account(d->m_selectedAccount.parentAccountId()); for (QStringList::const_iterator it = accountsToReparent.constBegin(); it != accountsToReparent.constEnd(); ++it) { MyMoneyAccount child = file->account(*it); file->reparentAccount(child, parent); } // reload the account because the sub-account list might have changed d->m_selectedAccount = file->account(d->m_selectedAccount.id()); // now recursively delete remaining sub-categories file->removeAccountList(d->m_selectedAccount.accountList()); // don't forget to update d->m_selectedAccount, because we still have a copy of // the old account list, which is no longer valid d->m_selectedAccount = file->account(d->m_selectedAccount.id()); } catch (const MyMoneyException &e) { KMessageBox::error(this, QString("") + i18n("Unable to delete a sub-category of category %1. Reason: %2", selectedAccountName, e.what()) + QString("")); return; } } break; // the category/account is deleted after the switch default: if (!d->m_selectedAccount.accountList().isEmpty()) return; // can't delete accounts which still have subaccounts if (KMessageBox::questionYesNo(this, i18n("

Do you really want to " "delete account %1?

", selectedAccountName)) != KMessageBox::Yes) { return; // ok, you don't want to? why did you click then, hmm? } } // switch; try { file->removeAccount(d->m_selectedAccount); d->m_selectedAccount.clearId(); slotUpdateActions(); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::error(this, i18n("Unable to delete account '%1'. Cause: %2", selectedAccountName, e.what())); } } void KMyMoneyApp::slotAccountEdit() { MyMoneyFile* file = MyMoneyFile::instance(); if (!d->m_selectedAccount.id().isEmpty()) { if (!file->isStandardAccount(d->m_selectedAccount.id())) { if (d->m_selectedAccount.accountType() != eMyMoney::Account::Loan && d->m_selectedAccount.accountType() != eMyMoney::Account::AssetLoan) { QString caption; bool category = false; switch (d->m_selectedAccount.accountGroup()) { default: caption = i18n("Edit account '%1'", d->m_selectedAccount.name()); break; case eMyMoney::Account::Expense: case eMyMoney::Account::Income: caption = i18n("Edit category '%1'", d->m_selectedAccount.name()); category = true; break; } // set a status message so that the application can't be closed until the editing is done slotStatusMsg(caption); QString tid = file->openingBalanceTransaction(d->m_selectedAccount); MyMoneyTransaction t; MyMoneySplit s0, s1; QPointer dlg = new KNewAccountDlg(d->m_selectedAccount, true, category, 0, caption); if (category) { dlg->setOpeningBalanceShown(false); dlg->setOpeningDateShown(false); tid.clear(); } else { if (!tid.isEmpty()) { try { t = file->transaction(tid); s0 = t.splitByAccount(d->m_selectedAccount.id()); s1 = t.splitByAccount(d->m_selectedAccount.id(), false); dlg->setOpeningBalance(s0.shares()); if (d->m_selectedAccount.accountGroup() == eMyMoney::Account::Liability) { dlg->setOpeningBalance(-s0.shares()); } } catch (const MyMoneyException &e) { qDebug() << "Error retrieving opening balance transaction " << tid << ": " << e.what() << "\n"; tid.clear(); } } } // check for online modules QMap::const_iterator it_plugin = d->m_onlinePlugins.constEnd(); const MyMoneyKeyValueContainer& kvp = d->m_selectedAccount.onlineBankingSettings(); if (!kvp["provider"].isEmpty()) { // if we have an online provider for this account, we need to check // that we have the corresponding plugin. If that exists, we ask it // to provide an additional tab for the account editor. it_plugin = d->m_onlinePlugins.constFind(kvp["provider"]); if (it_plugin != d->m_onlinePlugins.constEnd()) { QString name; QWidget *w = (*it_plugin)->accountConfigTab(d->m_selectedAccount, name); dlg->addTab(w, name); } } if (dlg != 0 && dlg->exec() == QDialog::Accepted) { try { MyMoneyFileTransaction ft; MyMoneyAccount account = dlg->account(); MyMoneyAccount parent = dlg->parentAccount(); if (it_plugin != d->m_onlinePlugins.constEnd()) { account.setOnlineBankingSettings((*it_plugin)->onlineBankingSettings(account.onlineBankingSettings())); } MyMoneyMoney bal = dlg->openingBalance(); if (d->m_selectedAccount.accountGroup() == eMyMoney::Account::Liability) { bal = -bal; } // we need to modify first, as reparent would override all other changes file->modifyAccount(account); if (account.parentAccountId() != parent.id()) { file->reparentAccount(account, parent); } if (!tid.isEmpty() && dlg->openingBalance().isZero()) { file->removeTransaction(t); } else if (!tid.isEmpty() && !dlg->openingBalance().isZero()) { s0.setShares(bal); s0.setValue(bal); t.modifySplit(s0); s1.setShares(-bal); s1.setValue(-bal); t.modifySplit(s1); t.setPostDate(account.openingDate()); file->modifyTransaction(t); } else if (tid.isEmpty() && !dlg->openingBalance().isZero()) { file->createOpeningBalanceTransaction(d->m_selectedAccount, bal); } ft.commit(); // reload the account object as it might have changed in the meantime slotSelectAccount(file->account(account.id())); } catch (const MyMoneyException &e) { KMessageBox::error(this, i18n("Unable to modify account '%1'. Cause: %2", d->m_selectedAccount.name(), e.what())); } } delete dlg; ready(); } else { QPointer wizard = new KEditLoanWizard(d->m_selectedAccount); connect(wizard, SIGNAL(newCategory(MyMoneyAccount&)), this, SLOT(slotCategoryNew(MyMoneyAccount&))); connect(wizard, SIGNAL(createPayee(QString,QString&)), this, SLOT(slotPayeeNew(QString,QString&))); if (wizard->exec() == QDialog::Accepted && wizard != 0) { MyMoneySchedule sch; try { MyMoneySchedule sch = file->schedule(d->m_selectedAccount.value("schedule").toLatin1()); } catch (const MyMoneyException &e) { qDebug() << "schedule" << d->m_selectedAccount.value("schedule").toLatin1() << "not found"; } if (!(d->m_selectedAccount == wizard->account()) || !(sch == wizard->schedule())) { MyMoneyFileTransaction ft; try { file->modifyAccount(wizard->account()); if (!sch.id().isEmpty()) { sch = wizard->schedule(); } try { file->schedule(sch.id()); file->modifySchedule(sch); ft.commit(); } catch (const MyMoneyException &) { try { if(sch.transaction().splitCount() >= 2) { file->addSchedule(sch); } ft.commit(); } catch (const MyMoneyException &e) { qDebug("Cannot add schedule: '%s'", qPrintable(e.what())); } } } catch (const MyMoneyException &e) { qDebug("Unable to modify account %s: '%s'", qPrintable(d->m_selectedAccount.name()), qPrintable(e.what())); } } } delete wizard; } } } } QList > KMyMoneyApp::Private::automaticReconciliation(const MyMoneyAccount &account, const QList > &transactions, const MyMoneyMoney &amount) { static const int NR_OF_STEPS_LIMIT = 300000; static const int PROGRESSBAR_STEPS = 1000; QList > result = transactions; KMSTATUS(i18n("Running automatic reconciliation")); int progressBarIndex = 0; kmymoney->slotStatusProgressBar(progressBarIndex, NR_OF_STEPS_LIMIT / PROGRESSBAR_STEPS); // optimize the most common case - all transactions should be cleared QListIterator > itTransactionSplitResult(result); MyMoneyMoney transactionsBalance; while (itTransactionSplitResult.hasNext()) { const QPair &transactionSplit = itTransactionSplitResult.next(); transactionsBalance += transactionSplit.second.shares(); } if (amount == transactionsBalance) { result = transactions; return result; } kmymoney->slotStatusProgressBar(progressBarIndex++, 0); // only one transaction is uncleared itTransactionSplitResult.toFront(); int index = 0; while (itTransactionSplitResult.hasNext()) { const QPair &transactionSplit = itTransactionSplitResult.next(); if (transactionsBalance - transactionSplit.second.shares() == amount) { result.removeAt(index); return result; } index++; } kmymoney->slotStatusProgressBar(progressBarIndex++, 0); // more than one transaction is uncleared - apply the algorithm result.clear(); const MyMoneySecurity &security = MyMoneyFile::instance()->security(account.currencyId()); double precision = 0.1 / account.fraction(security); QList sumList; sumList << MyMoneyMoney(); QMap > > sumToComponentsMap; // compute the possible matches QListIterator > itTransactionSplit(transactions); while (itTransactionSplit.hasNext()) { const QPair &transactionSplit = itTransactionSplit.next(); QListIterator itSum(sumList); QList tempList; while (itSum.hasNext()) { const MyMoneyMoney &sum = itSum.next(); QList > splitIds; splitIds << qMakePair(transactionSplit.first.id(), transactionSplit.second.id()); if (sumToComponentsMap.contains(sum)) { if (sumToComponentsMap.value(sum).contains(qMakePair(transactionSplit.first.id(), transactionSplit.second.id()))) { continue; } splitIds.append(sumToComponentsMap.value(sum)); } tempList << transactionSplit.second.shares() + sum; sumToComponentsMap[transactionSplit.second.shares() + sum] = splitIds; int size = sumToComponentsMap.size(); if (size % PROGRESSBAR_STEPS == 0) { kmymoney->slotStatusProgressBar(progressBarIndex++, 0); } if (size > NR_OF_STEPS_LIMIT) { return result; // it's taking too much resources abort the algorithm } } QList unionList; unionList.append(tempList); unionList.append(sumList); qSort(unionList); sumList.clear(); MyMoneyMoney smallestSumFromUnion = unionList.first(); sumList.append(smallestSumFromUnion); QListIterator itUnion(unionList); while (itUnion.hasNext()) { MyMoneyMoney sumFromUnion = itUnion.next(); if (smallestSumFromUnion < MyMoneyMoney(1 - precision / transactions.size())*sumFromUnion) { smallestSumFromUnion = sumFromUnion; sumList.append(sumFromUnion); } } } kmymoney->slotStatusProgressBar(NR_OF_STEPS_LIMIT / PROGRESSBAR_STEPS, 0); if (sumToComponentsMap.contains(amount)) { QListIterator > itTransactionSplit(transactions); while (itTransactionSplit.hasNext()) { const QPair &transactionSplit = itTransactionSplit.next(); const QList > &splitIds = sumToComponentsMap.value(amount); if (splitIds.contains(qMakePair(transactionSplit.first.id(), transactionSplit.second.id()))) { result.append(transactionSplit); } } } #ifdef KMM_DEBUG qDebug("For the amount %s a number of %d possible sums where computed from the set of %d transactions: ", qPrintable(MyMoneyUtils::formatMoney(amount, security)), sumToComponentsMap.size(), transactions.size()); #endif kmymoney->slotStatusProgressBar(-1, -1); return result; } void KMyMoneyApp::slotAccountReconcileStart() { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyAccount account; // we cannot reconcile standard accounts if (!file->isStandardAccount(d->m_selectedAccount.id())) { // check if we can reconcile this account // it make's sense for asset and liability accounts try { // check if we have overdue schedules for this account QList schedules = file->scheduleList(d->m_selectedAccount.id(), eMyMoney::Schedule::Type::Any, eMyMoney::Schedule::Occurrence::Any, eMyMoney::Schedule::PaymentType::Any, QDate(), QDate(), true); if (schedules.count() > 0) { if (KMessageBox::questionYesNo(this, i18n("KMyMoney has detected some overdue scheduled transactions for this account. Do you want to enter those scheduled transactions now?"), i18n("Scheduled transactions found")) == KMessageBox::Yes) { QMap skipMap; bool processedOne; eDialogs::ScheduleResultCode rc = eDialogs::ScheduleResultCode::Enter; do { processedOne = false; QList::const_iterator it_sch; for (it_sch = schedules.constBegin(); (rc != eDialogs::ScheduleResultCode::Cancel) && (it_sch != schedules.constEnd()); ++it_sch) { MyMoneySchedule sch(*(it_sch)); // and enter it if it is not on the skip list if (skipMap.find((*it_sch).id()) == skipMap.end()) { rc = enterSchedule(sch, false, true); if (rc == eDialogs::ScheduleResultCode::Ignore) { skipMap[(*it_sch).id()] = true; } } } // reload list (maybe this schedule needs to be added again) schedules = file->scheduleList(d->m_selectedAccount.id(), eMyMoney::Schedule::Type::Any, eMyMoney::Schedule::Occurrence::Any, eMyMoney::Schedule::PaymentType::Any, QDate(), QDate(), true); } while (processedOne); } } account = file->account(d->m_selectedAccount.id()); // get rid of previous run. delete d->m_endingBalanceDlg; d->m_endingBalanceDlg = new KEndingBalanceDlg(account, this); if (account.isAssetLiability()) { connect(d->m_endingBalanceDlg, SIGNAL(createPayee(QString,QString&)), this, SLOT(slotPayeeNew(QString,QString&))); connect(d->m_endingBalanceDlg, SIGNAL(createCategory(MyMoneyAccount&,MyMoneyAccount)), this, SLOT(slotCategoryNew(MyMoneyAccount&,MyMoneyAccount))); if (d->m_endingBalanceDlg->exec() == QDialog::Accepted) { if (KMyMoneyGlobalSettings::autoReconciliation()) { MyMoneyMoney startBalance = d->m_endingBalanceDlg->previousBalance(); MyMoneyMoney endBalance = d->m_endingBalanceDlg->endingBalance(); QDate endDate = d->m_endingBalanceDlg->statementDate(); QList > transactionList; MyMoneyTransactionFilter filter(account.id()); filter.addState((int)eMyMoney::TransactionFilter::State::Cleared); filter.addState((int)eMyMoney::TransactionFilter::State::NotReconciled); filter.setDateFilter(QDate(), endDate); filter.setConsiderCategory(false); filter.setReportAllSplits(true); file->transactionList(transactionList, filter); QList > result = d->automaticReconciliation(account, transactionList, endBalance - startBalance); if (!result.empty()) { QString message = i18n("KMyMoney has detected transactions matching your reconciliation data.\nWould you like KMyMoney to clear these transactions for you?"); if (KMessageBox::questionYesNo(this, message, i18n("Automatic reconciliation"), KStandardGuiItem::yes(), KStandardGuiItem::no(), "AcceptAutomaticReconciliation") == KMessageBox::Yes) { // mark the transactions cleared KMyMoneyRegister::SelectedTransactions oldSelection = d->m_selectedTransactions; d->m_selectedTransactions.clear(); QListIterator > itTransactionSplitResult(result); while (itTransactionSplitResult.hasNext()) { const QPair &transactionSplit = itTransactionSplitResult.next(); d->m_selectedTransactions.append(KMyMoneyRegister::SelectedTransaction(transactionSplit.first, transactionSplit.second, QString())); } // mark all transactions in d->m_selectedTransactions as 'Cleared' markTransaction(eMyMoney::Split::State::Cleared); d->m_selectedTransactions = oldSelection; } } } if (d->m_myMoneyView->startReconciliation(account, d->m_endingBalanceDlg->statementDate(), d->m_endingBalanceDlg->endingBalance())) { // check if the user requests us to create interest // or charge transactions. MyMoneyTransaction ti = d->m_endingBalanceDlg->interestTransaction(); MyMoneyTransaction tc = d->m_endingBalanceDlg->chargeTransaction(); MyMoneyFileTransaction ft; try { if (ti != MyMoneyTransaction()) { MyMoneyFile::instance()->addTransaction(ti); } if (tc != MyMoneyTransaction()) { MyMoneyFile::instance()->addTransaction(tc); } ft.commit(); } catch (const MyMoneyException &e) { qWarning("interest transaction not stored: '%s'", qPrintable(e.what())); } // reload the account object as it might have changed in the meantime d->m_reconciliationAccount = file->account(account.id()); slotUpdateActions(); } } } } catch (const MyMoneyException &) { } } } void KMyMoneyApp::slotAccountReconcileFinish() { MyMoneyFile* file = MyMoneyFile::instance(); if (!d->m_reconciliationAccount.id().isEmpty()) { // retrieve list of all transactions that are not reconciled or cleared QList > transactionList; MyMoneyTransactionFilter filter(d->m_reconciliationAccount.id()); filter.addState((int)eMyMoney::TransactionFilter::State::Cleared); filter.addState((int)eMyMoney::TransactionFilter::State::NotReconciled); filter.setDateFilter(QDate(), d->m_endingBalanceDlg->statementDate()); filter.setConsiderCategory(false); filter.setReportAllSplits(true); file->transactionList(transactionList, filter); MyMoneyMoney balance = MyMoneyFile::instance()->balance(d->m_reconciliationAccount.id(), d->m_endingBalanceDlg->statementDate()); MyMoneyMoney actBalance, clearedBalance; actBalance = clearedBalance = balance; // walk the list of transactions to figure out the balance(s) QList >::const_iterator it; for (it = transactionList.constBegin(); it != transactionList.constEnd(); ++it) { if ((*it).second.reconcileFlag() == eMyMoney::Split::State::NotReconciled) { clearedBalance -= (*it).second.shares(); } } if (d->m_endingBalanceDlg->endingBalance() != clearedBalance) { QString message = i18n("You are about to finish the reconciliation of this account with a difference between your bank statement and the transactions marked as cleared.\n" "Are you sure you want to finish the reconciliation?"); if (KMessageBox::questionYesNo(this, message, i18n("Confirm end of reconciliation"), KStandardGuiItem::yes(), KStandardGuiItem::no()) == KMessageBox::No) return; } MyMoneyFileTransaction ft; // refresh object d->m_reconciliationAccount = file->account(d->m_reconciliationAccount.id()); // Turn off reconciliation mode d->m_myMoneyView->finishReconciliation(d->m_reconciliationAccount); // only update the last statement balance here, if we haven't a newer one due // to download of online statements. if (d->m_reconciliationAccount.value("lastImportedTransactionDate").isEmpty() || QDate::fromString(d->m_reconciliationAccount.value("lastImportedTransactionDate"), Qt::ISODate) < d->m_endingBalanceDlg->statementDate()) { d->m_reconciliationAccount.setValue("lastStatementBalance", d->m_endingBalanceDlg->endingBalance().toString()); // in case we override the last statement balance here, we have to make sure // that we don't show the online balance anymore, as it might be different d->m_reconciliationAccount.deletePair("lastImportedTransactionDate"); } d->m_reconciliationAccount.setLastReconciliationDate(d->m_endingBalanceDlg->statementDate()); // keep a record of this reconciliation d->m_reconciliationAccount.addReconciliation(d->m_endingBalanceDlg->statementDate(), d->m_endingBalanceDlg->endingBalance()); d->m_reconciliationAccount.deletePair("lastReconciledBalance"); d->m_reconciliationAccount.deletePair("statementBalance"); d->m_reconciliationAccount.deletePair("statementDate"); try { // update the account data file->modifyAccount(d->m_reconciliationAccount); /* // collect the list of cleared splits for this account filter.clear(); filter.addAccount(d->m_reconciliationAccount.id()); filter.addState(eMyMoney::TransactionFilter::Cleared); filter.setConsiderCategory(false); filter.setReportAllSplits(true); file->transactionList(transactionList, filter); */ // walk the list of transactions/splits and mark the cleared ones as reconciled QList >::iterator it; for (it = transactionList.begin(); it != transactionList.end(); ++it) { MyMoneySplit sp = (*it).second; // skip the ones that are not marked cleared if (sp.reconcileFlag() != eMyMoney::Split::State::Cleared) continue; // always retrieve a fresh copy of the transaction because we // might have changed it already with another split MyMoneyTransaction t = file->transaction((*it).first.id()); sp.setReconcileFlag(eMyMoney::Split::State::Reconciled); sp.setReconcileDate(d->m_endingBalanceDlg->statementDate()); t.modifySplit(sp); // update the engine ... file->modifyTransaction(t); // ... and the list (*it) = qMakePair(t, sp); } ft.commit(); // reload account data from engine as the data might have changed in the meantime d->m_reconciliationAccount = file->account(d->m_reconciliationAccount.id()); emit accountReconciled(d->m_reconciliationAccount, d->m_endingBalanceDlg->statementDate(), d->m_endingBalanceDlg->previousBalance(), d->m_endingBalanceDlg->endingBalance(), transactionList); } catch (const MyMoneyException &) { qDebug("Unexpected exception when setting cleared to reconcile"); } } // Turn off reconciliation mode d->m_reconciliationAccount = MyMoneyAccount(); slotUpdateActions(); } void KMyMoneyApp::slotAccountReconcilePostpone() { MyMoneyFileTransaction ft; MyMoneyFile* file = MyMoneyFile::instance(); if (!d->m_reconciliationAccount.id().isEmpty()) { // refresh object d->m_reconciliationAccount = file->account(d->m_reconciliationAccount.id()); // Turn off reconciliation mode d->m_myMoneyView->finishReconciliation(d->m_reconciliationAccount); d->m_reconciliationAccount.setValue("lastReconciledBalance", d->m_endingBalanceDlg->previousBalance().toString()); d->m_reconciliationAccount.setValue("statementBalance", d->m_endingBalanceDlg->endingBalance().toString()); d->m_reconciliationAccount.setValue("statementDate", d->m_endingBalanceDlg->statementDate().toString(Qt::ISODate)); try { file->modifyAccount(d->m_reconciliationAccount); ft.commit(); d->m_reconciliationAccount = MyMoneyAccount(); slotUpdateActions(); } catch (const MyMoneyException &) { qDebug("Unexpected exception when setting last reconcile info into account"); ft.rollback(); d->m_reconciliationAccount = file->account(d->m_reconciliationAccount.id()); } } } void KMyMoneyApp::slotAccountOpenEmpty() { slotAccountOpen(MyMoneyAccount()); } void KMyMoneyApp::slotAccountOpen(const MyMoneyObject& obj) { if (typeid(obj) != typeid(MyMoneyAccount)) return; MyMoneyFile* file = MyMoneyFile::instance(); QString id = d->m_selectedAccount.id(); // if the caller passed a non-empty object, we need to select that if (!obj.id().isEmpty()) { id = obj.id(); } // we cannot reconcile standard accounts if (!file->isStandardAccount(id)) { // check if we can open this account // currently it make's sense for asset and liability accounts try { MyMoneyAccount account = file->account(id); d->m_myMoneyView->slotLedgerSelected(account.id()); } catch (const MyMoneyException &) { } } } void KMyMoneyApp::enableCloseAccountAction(const MyMoneyAccount& acc) { QAction *a = actionCollection()->action(s_Actions[Action::AccountClose]); switch (canCloseAccount(acc)) { case KMyMoneyUtils::AccountCanClose: { a->setEnabled(true); break; } case KMyMoneyUtils::AccountBalanceNonZero: { a->setEnabled(false); a->setToolTip(i18n("The balance of the account must be zero before the account can be closed")); break; } case KMyMoneyUtils::AccountChildrenOpen: { a->setEnabled(false); a->setToolTip(i18n("All subaccounts must be closed before the account can be closed")); break; } case KMyMoneyUtils::AccountScheduleReference: { a->setEnabled(false); a->setToolTip(i18n("This account is still included in an active schedule")); break; } } } KMyMoneyUtils::CanCloseAccountCodeE KMyMoneyApp::canCloseAccount(const MyMoneyAccount& acc) const { // balance must be zero if (!acc.balance().isZero()) return KMyMoneyUtils::AccountBalanceNonZero; // all children must be already closed QStringList::const_iterator it_a; for (it_a = acc.accountList().constBegin(); it_a != acc.accountList().constEnd(); ++it_a) { MyMoneyAccount a = MyMoneyFile::instance()->account(*it_a); if (!a.isClosed()) { return KMyMoneyUtils::AccountChildrenOpen; } } // there must be no unfinished schedule referencing the account QList list = MyMoneyFile::instance()->scheduleList(); QList::const_iterator it_l; for (it_l = list.constBegin(); it_l != list.constEnd(); ++it_l) { if ((*it_l).isFinished()) continue; if ((*it_l).hasReferenceTo(acc.id())) return KMyMoneyUtils::AccountScheduleReference; } return KMyMoneyUtils::AccountCanClose; } void KMyMoneyApp::slotAccountClose() { MyMoneyAccount a; if (!d->m_selectedInvestment.id().isEmpty()) a = d->m_selectedInvestment; else if (!d->m_selectedAccount.id().isEmpty()) a = d->m_selectedAccount; if (a.id().isEmpty()) return; // need an account ID MyMoneyFileTransaction ft; try { a.setClosed(true); MyMoneyFile::instance()->modifyAccount(a); ft.commit(); if (KMyMoneyGlobalSettings::hideClosedAccounts()) { KMessageBox::information(this, QString("") + i18n("You have closed this account. It remains in the system because you have transactions which still refer to it, but it is not shown in the views. You can make it visible again by going to the View menu and selecting Show all accounts or by deselecting the Do not show closed accounts setting.") + QString(""), i18n("Information"), "CloseAccountInfo"); } } catch (const MyMoneyException &) { } } void KMyMoneyApp::slotAccountReopen() { MyMoneyAccount a; if (!d->m_selectedInvestment.id().isEmpty()) a = d->m_selectedInvestment; else if (!d->m_selectedAccount.id().isEmpty()) a = d->m_selectedAccount; if (a.id().isEmpty()) return; // need an account ID MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyFileTransaction ft; try { while (a.isClosed()) { a.setClosed(false); file->modifyAccount(a); a = file->account(a.parentAccountId()); } ft.commit(); } catch (const MyMoneyException &) { } } void KMyMoneyApp::slotReparentAccount(const MyMoneyAccount& _src, const MyMoneyInstitution& _dst) { MyMoneyAccount src(_src); src.setInstitutionId(_dst.id()); MyMoneyFileTransaction ft; try { MyMoneyFile::instance()->modifyAccount(src); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::sorry(this, i18n("

%1 cannot be moved to institution %2. Reason: %3

", src.name(), _dst.name(), e.what())); } } void KMyMoneyApp::slotReparentAccount(const MyMoneyAccount& _src, const MyMoneyAccount& _dst) { MyMoneyAccount src(_src); MyMoneyAccount dst(_dst); MyMoneyFileTransaction ft; try { MyMoneyFile::instance()->reparentAccount(src, dst); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::sorry(this, i18n("

%1 cannot be moved to %2. Reason: %3

", src.name(), dst.name(), e.what())); } } void KMyMoneyApp::slotAccountTransactionReport() { // Generate a transaction report that contains transactions for only the // currently selected account. if (!d->m_selectedAccount.id().isEmpty()) { MyMoneyReport report( MyMoneyReport::eAccount, MyMoneyReport::eQCnumber | MyMoneyReport::eQCpayee | MyMoneyReport::eQCcategory, eMyMoney::TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("%1 YTD Account Transactions", d->m_selectedAccount.name()), i18n("Generated Report") ); report.setGroup(i18n("Transactions")); report.addAccount(d->m_selectedAccount.id()); d->m_myMoneyView->slotShowReport(report); } } void KMyMoneyApp::slotScheduleNew() { slotScheduleNew(MyMoneyTransaction()); } void KMyMoneyApp::slotScheduleNew(const MyMoneyTransaction& _t, eMyMoney::Schedule::Occurrence occurrence) { MyMoneySchedule schedule; schedule.setOccurrence(occurrence); // if the schedule is based on an existing transaction, // we take the post date and project it to the next // schedule in a month. if (_t != MyMoneyTransaction()) { MyMoneyTransaction t(_t); schedule.setTransaction(t); if (occurrence != eMyMoney::Schedule::Occurrence::Once) schedule.setNextDueDate(schedule.nextPayment(t.postDate())); } QPointer dlg = new KEditScheduleDlg(schedule, this); TransactionEditor* transactionEditor = dlg->startEdit(); if (transactionEditor) { KMyMoneyMVCCombo::setSubstringSearchForChildren(dlg, !KMyMoneySettings::stringMatchFromStart()); if (dlg->exec() == QDialog::Accepted && dlg != 0) { MyMoneyFileTransaction ft; try { schedule = dlg->schedule(); MyMoneyFile::instance()->addSchedule(schedule); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::error(this, i18n("Unable to add scheduled transaction: %1", e.what()), i18n("Add scheduled transaction")); } } } delete transactionEditor; delete dlg; } void KMyMoneyApp::slotScheduleEdit() { if (!d->m_selectedSchedule.id().isEmpty()) { try { MyMoneySchedule schedule = MyMoneyFile::instance()->schedule(d->m_selectedSchedule.id()); KEditScheduleDlg* sched_dlg = 0; KEditLoanWizard* loan_wiz = 0; switch (schedule.type()) { case eMyMoney::Schedule::Type::Bill: case eMyMoney::Schedule::Type::Deposit: case eMyMoney::Schedule::Type::Transfer: sched_dlg = new KEditScheduleDlg(schedule, this); d->m_transactionEditor = sched_dlg->startEdit(); if (d->m_transactionEditor) { KMyMoneyMVCCombo::setSubstringSearchForChildren(sched_dlg, !KMyMoneySettings::stringMatchFromStart()); if (sched_dlg->exec() == QDialog::Accepted) { MyMoneyFileTransaction ft; try { MyMoneySchedule sched = sched_dlg->schedule(); // Check whether the new Schedule Date // is at or before the lastPaymentDate // If it is, ask the user whether to clear the // lastPaymentDate const QDate& next = sched.nextDueDate(); const QDate& last = sched.lastPayment(); if (next.isValid() && last.isValid() && next <= last) { // Entered a date effectively no later // than previous payment. Date would be // updated automatically so we probably // want to clear it. Let's ask the user. if (KMessageBox::questionYesNo(this, QString("") + i18n("You have entered a scheduled transaction date of %1. Because the scheduled transaction was last paid on %2, KMyMoney will automatically adjust the scheduled transaction date to the next date unless the last payment date is reset. Do you want to reset the last payment date?", QLocale().toString(next, QLocale::ShortFormat), QLocale().toString(last, QLocale::ShortFormat)) + QString(""), i18n("Reset Last Payment Date"), KStandardGuiItem::yes(), KStandardGuiItem::no()) == KMessageBox::Yes) { sched.setLastPayment(QDate()); } } MyMoneyFile::instance()->modifySchedule(sched); // delete the editor before we emit the dataChanged() signal from the // engine. Calling this twice in a row does not hurt. deleteTransactionEditor(); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unable to modify scheduled transaction '%1'", d->m_selectedSchedule.name()), e.what()); } } deleteTransactionEditor(); } delete sched_dlg; break; case eMyMoney::Schedule::Type::LoanPayment: loan_wiz = new KEditLoanWizard(schedule.account(2)); connect(loan_wiz, SIGNAL(newCategory(MyMoneyAccount&)), this, SLOT(slotCategoryNew(MyMoneyAccount&))); connect(loan_wiz, SIGNAL(createPayee(QString,QString&)), this, SLOT(slotPayeeNew(QString,QString&))); if (loan_wiz->exec() == QDialog::Accepted) { MyMoneyFileTransaction ft; try { MyMoneyFile::instance()->modifySchedule(loan_wiz->schedule()); MyMoneyFile::instance()->modifyAccount(loan_wiz->account()); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unable to modify scheduled transaction '%1'", d->m_selectedSchedule.name()), e.what()); } } delete loan_wiz; break; case eMyMoney::Schedule::Type::Any: break; } } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unable to modify scheduled transaction '%1'", d->m_selectedSchedule.name()), e.what()); } } } void KMyMoneyApp::slotScheduleDelete() { if (!d->m_selectedSchedule.id().isEmpty()) { MyMoneyFileTransaction ft; try { MyMoneySchedule sched = MyMoneyFile::instance()->schedule(d->m_selectedSchedule.id()); QString msg = i18n("

Are you sure you want to delete the scheduled transaction %1?

", d->m_selectedSchedule.name()); if (sched.type() == eMyMoney::Schedule::Type::LoanPayment) { msg += QString(" "); msg += i18n("In case of loan payments it is currently not possible to recreate the scheduled transaction."); } if (KMessageBox::questionYesNo(this, msg) == KMessageBox::No) return; MyMoneyFile::instance()->removeSchedule(sched); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unable to remove scheduled transaction '%1'", d->m_selectedSchedule.name()), e.what()); } } } void KMyMoneyApp::slotScheduleDuplicate() { // since we may jump here via code, we have to make sure to react only // if the action is enabled if (kmymoney->actionCollection()->action(s_Actions[Action::ScheduleDuplicate])->isEnabled()) { MyMoneySchedule sch = d->m_selectedSchedule; sch.clearId(); sch.setLastPayment(QDate()); sch.setName(i18nc("Copy of scheduled transaction name", "Copy of %1", sch.name())); // make sure that we set a valid next due date if the original next due date is invalid if (!sch.nextDueDate().isValid()) sch.setNextDueDate(QDate::currentDate()); MyMoneyFileTransaction ft; try { MyMoneyFile::instance()->addSchedule(sch); ft.commit(); // select the new schedule in the view if (!d->m_selectedSchedule.id().isEmpty()) d->m_myMoneyView->slotScheduleSelected(sch.id()); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Unable to duplicate scheduled transaction: '%1'", d->m_selectedSchedule.name()), e.what()); } } } void KMyMoneyApp::slotScheduleSkip() { if (!d->m_selectedSchedule.id().isEmpty()) { try { MyMoneySchedule schedule = MyMoneyFile::instance()->schedule(d->m_selectedSchedule.id()); skipSchedule(schedule); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unknown scheduled transaction '%1'", d->m_selectedSchedule.name()), e.what()); } } } void KMyMoneyApp::skipSchedule(MyMoneySchedule& schedule) { if (!schedule.id().isEmpty()) { try { schedule = MyMoneyFile::instance()->schedule(schedule.id()); if (!schedule.isFinished()) { if (schedule.occurrence() != eMyMoney::Schedule::Occurrence::Once) { QDate next = schedule.nextDueDate(); if (!schedule.isFinished() && (KMessageBox::questionYesNo(this, QString("") + i18n("Do you really want to skip the %1 transaction scheduled for %2?", schedule.name(), QLocale().toString(next, QLocale::ShortFormat)) + QString(""))) == KMessageBox::Yes) { MyMoneyFileTransaction ft; schedule.setLastPayment(next); schedule.setNextDueDate(schedule.nextPayment(next)); MyMoneyFile::instance()->modifySchedule(schedule); ft.commit(); } } } } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, QString("") + i18n("Unable to skip scheduled transaction %1.", schedule.name()) + QString(""), e.what()); } } } void KMyMoneyApp::slotScheduleEnter() { if (!d->m_selectedSchedule.id().isEmpty()) { try { MyMoneySchedule schedule = MyMoneyFile::instance()->schedule(d->m_selectedSchedule.id()); enterSchedule(schedule); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unknown scheduled transaction '%1'", d->m_selectedSchedule.name()), e.what()); } } } eDialogs::ScheduleResultCode KMyMoneyApp::enterSchedule(MyMoneySchedule& schedule, bool autoEnter, bool extendedKeys) { eDialogs::ScheduleResultCode rc = eDialogs::ScheduleResultCode::Cancel; if (!schedule.id().isEmpty()) { try { schedule = MyMoneyFile::instance()->schedule(schedule.id()); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unable to enter scheduled transaction '%1'", schedule.name()), e.what()); return rc; } QPointer dlg = new KEnterScheduleDlg(this, schedule); try { QDate origDueDate = schedule.nextDueDate(); dlg->showExtendedKeys(extendedKeys); d->m_transactionEditor = dlg->startEdit(); if (d->m_transactionEditor) { KMyMoneyMVCCombo::setSubstringSearchForChildren(dlg, !KMyMoneySettings::stringMatchFromStart()); MyMoneyTransaction torig, taccepted; d->m_transactionEditor->createTransaction(torig, dlg->transaction(), schedule.transaction().splits().isEmpty() ? MyMoneySplit() : schedule.transaction().splits().front(), true); // force actions to be available no matter what (will be updated according to the state during // slotTransactionsEnter or slotTransactionsCancel) kmymoney->actionCollection()->action(s_Actions[Action::TransactionCancel])->setEnabled(true); kmymoney->actionCollection()->action(s_Actions[Action::TransactionEnter])->setEnabled(true); KConfirmManualEnterDlg::Action action = KConfirmManualEnterDlg::ModifyOnce; if (!autoEnter || !schedule.isFixed()) { for (; dlg != 0;) { rc = eDialogs::ScheduleResultCode::Cancel; if (dlg->exec() == QDialog::Accepted && dlg != 0) { rc = dlg->resultCode(); if (rc == eDialogs::ScheduleResultCode::Enter) { d->m_transactionEditor->createTransaction(taccepted, torig, torig.splits().isEmpty() ? MyMoneySplit() : torig.splits().front(), true); // make sure to suppress comparison of some data: postDate torig.setPostDate(taccepted.postDate()); if (torig != taccepted) { QPointer cdlg = new KConfirmManualEnterDlg(schedule, this); cdlg->loadTransactions(torig, taccepted); if (cdlg->exec() == QDialog::Accepted) { action = cdlg->action(); delete cdlg; break; } delete cdlg; // the user has chosen 'cancel' during confirmation, // we go back to the editor continue; } } else if (rc == eDialogs::ScheduleResultCode::Skip) { slotTransactionsCancel(); skipSchedule(schedule); } else { slotTransactionsCancel(); } } else { if (autoEnter) { if (KMessageBox::warningYesNo(this, i18n("Are you sure you wish to stop this scheduled transaction from being entered into the register?\n\nKMyMoney will prompt you again next time it starts unless you manually enter it later.")) == KMessageBox::No) { // the user has chosen 'No' for the above question, // we go back to the editor continue; } } slotTransactionsCancel(); } break; } } // if we still have the editor around here, the user did not cancel if ((d->m_transactionEditor != 0) && (dlg != 0)) { MyMoneyFileTransaction ft; try { MyMoneyTransaction t; // add the new transaction switch (action) { case KConfirmManualEnterDlg::UseOriginal: // setup widgets with original transaction data d->m_transactionEditor->setTransaction(dlg->transaction(), dlg->transaction().splits().isEmpty() ? MyMoneySplit() : dlg->transaction().splits().front()); // and create a transaction based on that data taccepted = MyMoneyTransaction(); d->m_transactionEditor->createTransaction(taccepted, dlg->transaction(), dlg->transaction().splits().isEmpty() ? MyMoneySplit() : dlg->transaction().splits().front(), true); break; case KConfirmManualEnterDlg::ModifyAlways: torig = taccepted; torig.setPostDate(origDueDate); schedule.setTransaction(torig); break; case KConfirmManualEnterDlg::ModifyOnce: break; } QString newId; connect(d->m_transactionEditor, SIGNAL(balanceWarning(QWidget*,MyMoneyAccount,QString)), d->m_balanceWarning, SLOT(slotShowMessage(QWidget*,MyMoneyAccount,QString))); if (d->m_transactionEditor->enterTransactions(newId, false)) { if (!newId.isEmpty()) { MyMoneyTransaction t = MyMoneyFile::instance()->transaction(newId); schedule.setLastPayment(t.postDate()); } // in case the next due date is invalid, the schedule is finished // we mark it as such by setting the next due date to one day past the end QDate nextDueDate = schedule.nextPayment(origDueDate); if (!nextDueDate.isValid()) { schedule.setNextDueDate(schedule.endDate().addDays(1)); } else { schedule.setNextDueDate(nextDueDate); } MyMoneyFile::instance()->modifySchedule(schedule); rc = eDialogs::ScheduleResultCode::Enter; // delete the editor before we emit the dataChanged() signal from the // engine. Calling this twice in a row does not hurt. deleteTransactionEditor(); ft.commit(); } } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unable to enter scheduled transaction '%1'", schedule.name()), e.what()); } deleteTransactionEditor(); } } } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unable to enter scheduled transaction '%1'", schedule.name()), e.what()); } delete dlg; } return rc; } void KMyMoneyApp::slotPayeeNew(const QString& newnameBase, QString& id) { createPayeeNew(newnameBase, id); } bool KMyMoneyApp::createPayeeNew(const QString& newnameBase, QString& id) { bool doit = true; if (newnameBase != i18n("New Payee")) { // Ask the user if that is what he intended to do? QString msg = QLatin1String("") + i18n("Do you want to add %1 as payer/receiver?", newnameBase) + QLatin1String(""); if (KMessageBox::questionYesNo(this, msg, i18n("New payee/receiver"), KStandardGuiItem::yes(), KStandardGuiItem::no(), "NewPayee") == KMessageBox::No) { doit = false; // we should not keep the 'no' setting because that can confuse people like // I have seen in some usability tests. So we just delete it right away. KSharedConfigPtr kconfig = KSharedConfig::openConfig(); if (kconfig) { kconfig->group(QLatin1String("Notification Messages")).deleteEntry(QLatin1String("NewPayee")); } } } if (doit) { MyMoneyFileTransaction ft; try { QString newname(newnameBase); // adjust name until a unique name has been created int count = 0; for (;;) { try { MyMoneyFile::instance()->payeeByName(newname); newname = QString("%1 [%2]").arg(newnameBase).arg(++count); } catch (const MyMoneyException &) { break; } } MyMoneyPayee p; p.setName(newname); MyMoneyFile::instance()->addPayee(p); id = p.id(); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unable to add payee"), i18n("%1 thrown in %2:%3", e.what(), e.file(), e.line())); doit = false; } } return doit; } void KMyMoneyApp::slotPayeeNew() { QString id; slotPayeeNew(i18n("New Payee"), id); // the callbacks should have made sure, that the payees view has been // updated already. So we search for the id in the list of items // and select it. emit payeeCreated(id); } bool KMyMoneyApp::payeeInList(const QList& list, const QString& id) const { bool rc = false; QList::const_iterator it_p = list.begin(); while (it_p != list.end()) { if ((*it_p).id() == id) { rc = true; break; } ++it_p; } return rc; } void KMyMoneyApp::slotPayeeDelete() { if (d->m_selectedPayees.isEmpty()) return; // shouldn't happen // get confirmation from user QString prompt; if (d->m_selectedPayees.size() == 1) prompt = i18n("

Do you really want to remove the payee %1?

", d->m_selectedPayees.front().name()); else prompt = i18n("Do you really want to remove all selected payees?"); if (KMessageBox::questionYesNo(this, prompt, i18n("Remove Payee")) == KMessageBox::No) return; payeeReassign(KPayeeReassignDlg::TypeDelete); } void KMyMoneyApp::slotPayeeMerge() { if (d->m_selectedPayees.size() < 1) return; // shouldn't happen if (KMessageBox::questionYesNo(this, i18n("

Do you really want to merge the selected payees?"), i18n("Merge Payees")) == KMessageBox::No) return; if (payeeReassign(KPayeeReassignDlg::TypeMerge)) // clean selection since we just deleted the selected payees slotSelectPayees(QList()); } bool KMyMoneyApp::payeeReassign(int type) { if (!(type >= 0 && type < KPayeeReassignDlg::TypeCount)) return false; MyMoneyFile * file = MyMoneyFile::instance(); MyMoneyFileTransaction ft; try { // create a transaction filter that contains all payees selected for removal MyMoneyTransactionFilter f = MyMoneyTransactionFilter(); for (QList::const_iterator it = d->m_selectedPayees.constBegin(); it != d->m_selectedPayees.constEnd(); ++it) { f.addPayee((*it).id()); } // request a list of all transactions that still use the payees in question QList translist = file->transactionList(f); // qDebug() << "[KPayeesView::slotDeletePayee] " << translist.count() << " transaction still assigned to payees"; // now get a list of all schedules that make use of one of the payees QList all_schedules = file->scheduleList(); QList used_schedules; for (QList::ConstIterator it = all_schedules.constBegin(); it != all_schedules.constEnd(); ++it) { // loop over all splits in the transaction of the schedule for (QList::ConstIterator s_it = (*it).transaction().splits().constBegin(); s_it != (*it).transaction().splits().constEnd(); ++s_it) { // is the payee in the split to be deleted? if (payeeInList(d->m_selectedPayees, (*s_it).payeeId())) { used_schedules.push_back(*it); // remember this schedule break; } } } // qDebug() << "[KPayeesView::slotDeletePayee] " << used_schedules.count() << " schedules use one of the selected payees"; // and a list of all loan accounts that references one of the payees QList allAccounts; QList usedAccounts; file->accountList(allAccounts); foreach (const MyMoneyAccount &account, allAccounts) { if (account.isLoan()) { MyMoneyAccountLoan loanAccount(account); foreach (const MyMoneyPayee &payee, d->m_selectedPayees) { if (loanAccount.hasReferenceTo(payee.id())) { usedAccounts.append(account); } } } } MyMoneyPayee newPayee; bool addToMatchList = false; // if at least one payee is still referenced, we need to reassign its transactions first if (!translist.isEmpty() || !used_schedules.isEmpty() || !usedAccounts.isEmpty()) { // first create list with all non-selected payees QList remainingPayees; if (type == KPayeeReassignDlg::TypeMerge) { remainingPayees = d->m_selectedPayees; } else { remainingPayees = file->payeeList(); QList::iterator it_p; for (it_p = remainingPayees.begin(); it_p != remainingPayees.end();) { if (d->m_selectedPayees.contains(*it_p)) { it_p = remainingPayees.erase(it_p); } else { ++it_p; } } } // show error message if no payees remain if (remainingPayees.isEmpty()) { KMessageBox::sorry(this, i18n("At least one transaction/scheduled transaction or loan account is still referenced by a payee. " "Currently you have all payees selected. However, at least one payee must remain so " "that the transaction/scheduled transaction or loan account can be reassigned.")); return false; } // show transaction reassignment dialog KPayeeReassignDlg * dlg = new KPayeeReassignDlg(static_cast(type), this); KMyMoneyMVCCombo::setSubstringSearchForChildren(dlg, !KMyMoneySettings::stringMatchFromStart()); QString payee_id = dlg->show(remainingPayees); addToMatchList = dlg->addToMatchList(); delete dlg; // and kill the dialog if (payee_id.isEmpty()) return false; // the user aborted the dialog, so let's abort as well // try to get selected payee. If not possible and we are merging payees, // then we create a new one try { newPayee = file->payee(payee_id); } catch (const MyMoneyException &e) { if (type == KPayeeReassignDlg::TypeMerge) { // it's ok to use payee_id for both arguments since the first is const, // so it's garantee not to change its content if (!createPayeeNew(payee_id, payee_id)) return false; // the user aborted the dialog, so let's abort as well newPayee = file->payee(payee_id); } else { return false; } } // TODO : check if we have a report that explicitively uses one of our payees // and issue an appropriate warning try { QList::iterator s_it; // now loop over all transactions and reassign payee for (QList::iterator it = translist.begin(); it != translist.end(); ++it) { // create a copy of the splits list in the transaction QList splits = (*it).splits(); // loop over all splits for (s_it = splits.begin(); s_it != splits.end(); ++s_it) { // if the split is assigned to one of the selected payees, we need to modify it if (payeeInList(d->m_selectedPayees, (*s_it).payeeId())) { (*s_it).setPayeeId(payee_id); // first modify payee in current split // then modify the split in our local copy of the transaction list (*it).modifySplit(*s_it); // this does not modify the list object 'splits'! } } // for - Splits file->modifyTransaction(*it); // modify the transaction in the MyMoney object } // for - Transactions // now loop over all schedules and reassign payees for (QList::iterator it = used_schedules.begin(); it != used_schedules.end(); ++it) { // create copy of transaction in current schedule MyMoneyTransaction trans = (*it).transaction(); // create copy of lists of splits QList splits = trans.splits(); for (s_it = splits.begin(); s_it != splits.end(); ++s_it) { if (payeeInList(d->m_selectedPayees, (*s_it).payeeId())) { (*s_it).setPayeeId(payee_id); trans.modifySplit(*s_it); // does not modify the list object 'splits'! } } // for - Splits // store transaction in current schedule (*it).setTransaction(trans); file->modifySchedule(*it); // modify the schedule in the MyMoney engine } // for - Schedules // reassign the payees in the loans that reference the deleted payees foreach (const MyMoneyAccount &account, usedAccounts) { MyMoneyAccountLoan loanAccount(account); loanAccount.setPayee(payee_id); file->modifyAccount(loanAccount); } } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Unable to reassign payee of transaction/split"), i18n("%1 thrown in %2:%3", e.what(), e.file(), e.line())); } } else { // if !translist.isEmpty() if (type == KPayeeReassignDlg::TypeMerge) { KMessageBox::sorry(this, i18n("Nothing to merge."), i18n("Merge Payees")); return false; } } bool ignorecase; QStringList payeeNames; MyMoneyPayee::payeeMatchType matchType = newPayee.matchData(ignorecase, payeeNames); QStringList deletedPayeeNames; // now loop over all selected payees and remove them for (QList::iterator it = d->m_selectedPayees.begin(); it != d->m_selectedPayees.end(); ++it) { if (newPayee.id() != (*it).id()) { if (addToMatchList) { deletedPayeeNames << (*it).name(); } file->removePayee(*it); } } // if we initially have no matching turned on, we just ignore the case (default) if (matchType == MyMoneyPayee::matchDisabled) ignorecase = true; // update the destination payee if this was requested by the user if (addToMatchList && deletedPayeeNames.count() > 0) { // add new names to the list // TODO: it would be cool to somehow shrink the list to make better use // of regular expressions at this point. For now, we leave this task // to the user himeself. QStringList::const_iterator it_n; for (it_n = deletedPayeeNames.constBegin(); it_n != deletedPayeeNames.constEnd(); ++it_n) { if (matchType == MyMoneyPayee::matchKey) { // make sure we really need it and it is not caught by an existing regexp QStringList::const_iterator it_k; for (it_k = payeeNames.constBegin(); it_k != payeeNames.constEnd(); ++it_k) { QRegExp exp(*it_k, ignorecase ? Qt::CaseInsensitive : Qt::CaseSensitive); if (exp.indexIn(*it_n) != -1) break; } if (it_k == payeeNames.constEnd()) payeeNames << QRegExp::escape(*it_n); } else if (payeeNames.contains(*it_n) == 0) payeeNames << QRegExp::escape(*it_n); } // and update the payee in the engine context // make sure to turn on matching for this payee in the right mode newPayee.setMatchData(MyMoneyPayee::matchKey, ignorecase, payeeNames); file->modifyPayee(newPayee); } ft.commit(); // If we just deleted the payees, they sure don't exist anymore slotSelectPayees(QList()); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Unable to remove payee(s)"), i18n("%1 thrown in %2:%3", e.what(), e.file(), e.line())); } return true; } void KMyMoneyApp::slotTagNew(const QString& newnameBase, QString& id) { bool doit = true; if (newnameBase != i18n("New Tag")) { // Ask the user if that is what he intended to do? QString msg = QString("") + i18n("Do you want to add %1 as tag?", newnameBase) + QString(""); if (KMessageBox::questionYesNo(this, msg, i18n("New tag"), KStandardGuiItem::yes(), KStandardGuiItem::no(), "NewTag") == KMessageBox::No) { doit = false; // we should not keep the 'no' setting because that can confuse people like // I have seen in some usability tests. So we just delete it right away. KSharedConfigPtr kconfig = KSharedConfig::openConfig(); if (kconfig) { kconfig->group(QLatin1String("Notification Messages")).deleteEntry(QLatin1String("NewTag")); } } } if (doit) { MyMoneyFileTransaction ft; try { QString newname(newnameBase); // adjust name until a unique name has been created int count = 0; for (;;) { try { MyMoneyFile::instance()->tagByName(newname); newname = QString("%1 [%2]").arg(newnameBase).arg(++count); } catch (const MyMoneyException &) { break; } } MyMoneyTag ta; ta.setName(newname); MyMoneyFile::instance()->addTag(ta); id = ta.id(); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(this, i18n("Unable to add tag"), i18n("%1 thrown in %2:%3", e.what(), e.file(), e.line())); } } } void KMyMoneyApp::slotTagNew() { QString id; slotTagNew(i18n("New Tag"), id); // the callbacks should have made sure, that the tags view has been // updated already. So we search for the id in the list of items // and select it. emit tagCreated(id); } bool KMyMoneyApp::tagInList(const QList& list, const QString& id) const { bool rc = false; QList::const_iterator it_p = list.begin(); while (it_p != list.end()) { if ((*it_p).id() == id) { rc = true; break; } ++it_p; } return rc; } void KMyMoneyApp::slotTagDelete() { if (d->m_selectedTags.isEmpty()) return; // shouldn't happen MyMoneyFile * file = MyMoneyFile::instance(); // first create list with all non-selected tags QList remainingTags = file->tagList(); QList::iterator it_ta; for (it_ta = remainingTags.begin(); it_ta != remainingTags.end();) { if (d->m_selectedTags.contains(*it_ta)) { it_ta = remainingTags.erase(it_ta); } else { ++it_ta; } } // get confirmation from user QString prompt; if (d->m_selectedTags.size() == 1) prompt = i18n("

Do you really want to remove the tag %1?

", d->m_selectedTags.front().name()); else prompt = i18n("Do you really want to remove all selected tags?"); if (KMessageBox::questionYesNo(this, prompt, i18n("Remove Tag")) == KMessageBox::No) return; MyMoneyFileTransaction ft; try { // create a transaction filter that contains all tags selected for removal MyMoneyTransactionFilter f = MyMoneyTransactionFilter(); for (QList::const_iterator it = d->m_selectedTags.constBegin(); it != d->m_selectedTags.constEnd(); ++it) { f.addTag((*it).id()); } // request a list of all transactions that still use the tags in question QList translist = file->transactionList(f); // qDebug() << "[KTagsView::slotDeleteTag] " << translist.count() << " transaction still assigned to tags"; // now get a list of all schedules that make use of one of the tags QList all_schedules = file->scheduleList(); QList used_schedules; for (QList::ConstIterator it = all_schedules.constBegin(); it != all_schedules.constEnd(); ++it) { // loop over all splits in the transaction of the schedule for (QList::ConstIterator s_it = (*it).transaction().splits().constBegin(); s_it != (*it).transaction().splits().constEnd(); ++s_it) { for (int i = 0; i < (*s_it).tagIdList().size(); i++) { // is the tag in the split to be deleted? if (tagInList(d->m_selectedTags, (*s_it).tagIdList()[i])) { used_schedules.push_back(*it); // remember this schedule break; } } } } // qDebug() << "[KTagsView::slotDeleteTag] " << used_schedules.count() << " schedules use one of the selected tags"; MyMoneyTag newTag; // if at least one tag is still referenced, we need to reassign its transactions first if (!translist.isEmpty() || !used_schedules.isEmpty()) { // show error message if no tags remain //FIXME-ALEX Tags are optional so we can delete all of them and simply delete every tagId from every transaction if (remainingTags.isEmpty()) { KMessageBox::sorry(this, i18n("At least one transaction/scheduled transaction is still referenced by a tag. " "Currently you have all tags selected. However, at least one tag must remain so " "that the transaction/scheduled transaction can be reassigned.")); return; } // show transaction reassignment dialog KTagReassignDlg * dlg = new KTagReassignDlg(this); KMyMoneyMVCCombo::setSubstringSearchForChildren(dlg, !KMyMoneySettings::stringMatchFromStart()); QString tag_id = dlg->show(remainingTags); delete dlg; // and kill the dialog if (tag_id.isEmpty()) //FIXME-ALEX Let the user choose to not reassign a to-be deleted tag to another one. return; // the user aborted the dialog, so let's abort as well newTag = file->tag(tag_id); // TODO : check if we have a report that explicitively uses one of our tags // and issue an appropriate warning try { QList::iterator s_it; // now loop over all transactions and reassign tag for (QList::iterator it = translist.begin(); it != translist.end(); ++it) { // create a copy of the splits list in the transaction QList splits = (*it).splits(); // loop over all splits for (s_it = splits.begin(); s_it != splits.end(); ++s_it) { QList tagIdList = (*s_it).tagIdList(); for (int i = 0; i < tagIdList.size(); i++) { // if the split is assigned to one of the selected tags, we need to modify it if (tagInList(d->m_selectedTags, tagIdList[i])) { tagIdList.removeAt(i); if (tagIdList.indexOf(tag_id) == -1) tagIdList.append(tag_id); i = -1; // restart from the first element } } (*s_it).setTagIdList(tagIdList); // first modify tag list in current split // then modify the split in our local copy of the transaction list (*it).modifySplit(*s_it); // this does not modify the list object 'splits'! } // for - Splits file->modifyTransaction(*it); // modify the transaction in the MyMoney object } // for - Transactions // now loop over all schedules and reassign tags for (QList::iterator it = used_schedules.begin(); it != used_schedules.end(); ++it) { // create copy of transaction in current schedule MyMoneyTransaction trans = (*it).transaction(); // create copy of lists of splits QList splits = trans.splits(); for (s_it = splits.begin(); s_it != splits.end(); ++s_it) { QList tagIdList = (*s_it).tagIdList(); for (int i = 0; i < tagIdList.size(); i++) { if (tagInList(d->m_selectedTags, tagIdList[i])) { tagIdList.removeAt(i); if (tagIdList.indexOf(tag_id) == -1) tagIdList.append(tag_id); i = -1; // restart from the first element } } (*s_it).setTagIdList(tagIdList); trans.modifySplit(*s_it); // does not modify the list object 'splits'! } // for - Splits // store transaction in current schedule (*it).setTransaction(trans); file->modifySchedule(*it); // modify the schedule in the MyMoney engine } // for - Schedules } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Unable to reassign tag of transaction/split"), i18n("%1 thrown in %2:%3", e.what(), e.file(), e.line())); } } // if !translist.isEmpty() // now loop over all selected tags and remove them for (QList::iterator it = d->m_selectedTags.begin(); it != d->m_selectedTags.end(); ++it) { file->removeTag(*it); } ft.commit(); // If we just deleted the tags, they sure don't exist anymore slotSelectTags(QList()); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Unable to remove tag(s)"), i18n("%1 thrown in %2:%3", e.what(), e.file(), e.line())); } } void KMyMoneyApp::slotCurrencyNew() { QString sid = QInputDialog::getText(0, i18n("New currency"), i18n("Enter ISO 4217 code for the new currency")); if (!sid.isEmpty()) { QString id(sid); MyMoneySecurity currency(id, i18n("New currency")); MyMoneyFileTransaction ft; try { MyMoneyFile::instance()->addCurrency(currency); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::sorry(this, i18n("Cannot create new currency. %1", e.what()), i18n("New currency")); } emit currencyCreated(id); } } void KMyMoneyApp::slotCurrencyUpdate(const QString ¤cyId, const QString& currencyName, const QString& currencyTradingSymbol) { MyMoneyFile* file = MyMoneyFile::instance(); try { if (currencyName != d->m_selectedCurrency.name() || currencyTradingSymbol != d->m_selectedCurrency.tradingSymbol()) { MyMoneySecurity currency = file->currency(currencyId); currency.setName(currencyName); currency.setTradingSymbol(currencyTradingSymbol); MyMoneyFileTransaction ft; try { file->modifyCurrency(currency); d->m_selectedCurrency = currency; ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::sorry(this, i18n("Cannot update currency. %1", e.what()), i18n("Update currency")); } } } catch (const MyMoneyException &e) { KMessageBox::sorry(this, i18n("Cannot update currency. %1", e.what()), i18n("Update currency")); } } void KMyMoneyApp::slotCurrencyDelete() { if (!d->m_selectedCurrency.id().isEmpty()) { MyMoneyFileTransaction ft; try { MyMoneyFile::instance()->removeCurrency(d->m_selectedCurrency); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::sorry(this, i18n("Cannot delete currency %1. %2", d->m_selectedCurrency.name(), e.what()), i18n("Delete currency")); } } } void KMyMoneyApp::slotCurrencySetBase() { if (!d->m_selectedCurrency.id().isEmpty()) { if (d->m_selectedCurrency.id() != MyMoneyFile::instance()->baseCurrency().id()) { MyMoneyFileTransaction ft; try { MyMoneyFile::instance()->setBaseCurrency(d->m_selectedCurrency); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::sorry(this, i18n("Cannot set %1 as base currency: %2", d->m_selectedCurrency.name(), e.what()), i18n("Set base currency")); } } } } void KMyMoneyApp::slotBudgetNew() { QDate date = QDate::currentDate(); date.setDate(date.year(), KMyMoneyGlobalSettings::firstFiscalMonth(), KMyMoneyGlobalSettings::firstFiscalDay()); QString newname = i18n("Budget %1", date.year()); MyMoneyBudget budget; // make sure we have a unique name try { int i = 1; // Exception thrown when the name is not found while (1) { MyMoneyFile::instance()->budgetByName(newname); newname = i18n("Budget %1 %2", date.year(), i++); } } catch (const MyMoneyException &) { // all ok, the name is unique } MyMoneyFileTransaction ft; try { budget.setName(newname); budget.setBudgetStart(date); MyMoneyFile::instance()->addBudget(budget); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to add budget: %1, thrown in %2:%3", e.what(), e.file(), e.line())); } } void KMyMoneyApp::slotBudgetDelete() { if (d->m_selectedBudgets.isEmpty()) return; // shouldn't happen MyMoneyFile * file = MyMoneyFile::instance(); // get confirmation from user QString prompt; if (d->m_selectedBudgets.size() == 1) prompt = i18n("

Do you really want to remove the budget %1?

", d->m_selectedBudgets.front().name()); else prompt = i18n("Do you really want to remove all selected budgets?"); if (KMessageBox::questionYesNo(this, prompt, i18n("Remove Budget")) == KMessageBox::No) return; MyMoneyFileTransaction ft; try { // now loop over all selected budgets and remove them for (QList::iterator it = d->m_selectedBudgets.begin(); it != d->m_selectedBudgets.end(); ++it) { file->removeBudget(*it); } ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to remove budget: %1, thrown in %2:%3", e.what(), e.file(), e.line())); } } void KMyMoneyApp::slotBudgetCopy() { if (d->m_selectedBudgets.size() == 1) { MyMoneyFileTransaction ft; try { MyMoneyBudget budget = d->m_selectedBudgets.first(); budget.clearId(); budget.setName(i18n("Copy of %1", budget.name())); MyMoneyFile::instance()->addBudget(budget); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to add budget: %1, thrown in %2:%3", e.what(), e.file(), e.line())); } } } void KMyMoneyApp::slotBudgetChangeYear() { if (d->m_selectedBudgets.size() == 1) { QStringList years; int current = 0; bool haveCurrent = false; MyMoneyBudget budget = *(d->m_selectedBudgets.begin()); for (int i = (QDate::currentDate().year() - 3); i < (QDate::currentDate().year() + 5); ++i) { years << QString("%1").arg(i); if (i == budget.budgetStart().year()) { haveCurrent = true; } if (!haveCurrent) ++current; } if (!haveCurrent) current = 0; bool ok = false; QString yearString = QInputDialog::getItem(this, i18n("Select year"), i18n("Budget year"), years, current, false, &ok); if (ok) { int year = yearString.toInt(0, 0); QDate newYear = QDate(year, budget.budgetStart().month(), budget.budgetStart().day()); if (newYear != budget.budgetStart()) { MyMoneyFileTransaction ft; try { budget.setBudgetStart(newYear); MyMoneyFile::instance()->modifyBudget(budget); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to modify budget: %1, thrown in %2:%3", e.what(), e.file(), e.line())); } } } } } void KMyMoneyApp::slotBudgetForecast() { if (d->m_selectedBudgets.size() == 1) { MyMoneyFileTransaction ft; try { MyMoneyBudget budget = d->m_selectedBudgets.first(); bool calcBudget = budget.getaccounts().count() == 0; if (!calcBudget) { if (KMessageBox::warningContinueCancel(0, i18n("The current budget already contains data. Continuing will replace all current values of this budget."), i18nc("Warning message box", "Warning")) == KMessageBox::Continue) calcBudget = true; } if (calcBudget) { QDate historyStart; QDate historyEnd; QDate budgetStart; QDate budgetEnd; budgetStart = budget.budgetStart(); budgetEnd = budgetStart.addYears(1).addDays(-1); historyStart = budgetStart.addYears(-1); historyEnd = budgetEnd.addYears(-1); MyMoneyForecast forecast = KMyMoneyGlobalSettings::forecast(); forecast.createBudget(budget, historyStart, historyEnd, budgetStart, budgetEnd, true); MyMoneyFile::instance()->modifyBudget(budget); ft.commit(); } } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to modify budget: %1, thrown in %2:%3", e.what(), e.file(), e.line())); } } } void KMyMoneyApp::slotNewFeature() { } void KMyMoneyApp::slotTransactionsDelete() { // since we may jump here via code, we have to make sure to react only // if the action is enabled if (!kmymoney->actionCollection()->action(s_Actions[Action::TransactionDelete])->isEnabled()) return; if (d->m_selectedTransactions.isEmpty()) return; if (d->m_selectedTransactions.warnLevel() == 1) { if (KMessageBox::warningContinueCancel(0, i18n("At least one split of the selected transactions has been reconciled. " "Do you wish to delete the transactions anyway?"), i18n("Transaction already reconciled")) == KMessageBox::Cancel) return; } QString msg = i18np("Do you really want to delete the selected transaction?", "Do you really want to delete all %1 selected transactions?", d->m_selectedTransactions.count()); if (KMessageBox::questionYesNo(this, msg, i18n("Delete transaction")) == KMessageBox::Yes) { KMSTATUS(i18n("Deleting transactions")); doDeleteTransactions(); } } void KMyMoneyApp::slotTransactionDuplicate() { // since we may jump here via code, we have to make sure to react only // if the action is enabled if (kmymoney->actionCollection()->action(s_Actions[Action::TransactionDuplicate])->isEnabled()) { KMyMoneyRegister::SelectedTransactions list = d->m_selectedTransactions; KMyMoneyRegister::SelectedTransactions::iterator it_t; int i = 0; int cnt = d->m_selectedTransactions.count(); KMSTATUS(i18n("Duplicating transactions")); slotStatusProgressBar(0, cnt); MyMoneyFileTransaction ft; MyMoneyTransaction lt; try { for (it_t = list.begin(); it_t != list.end(); ++it_t) { MyMoneyTransaction t = (*it_t).transaction(); QList::iterator it_s; // wipe out any reconciliation information for (it_s = t.splits().begin(); it_s != t.splits().end(); ++it_s) { (*it_s).setReconcileFlag(eMyMoney::Split::State::NotReconciled); (*it_s).setReconcileDate(QDate()); (*it_s).setBankID(QString()); } // clear invalid data t.setEntryDate(QDate()); t.clearId(); // and set the post date to today t.setPostDate(QDate::currentDate()); MyMoneyFile::instance()->addTransaction(t); lt = t; slotStatusProgressBar(i++, 0); } ft.commit(); // select the new transaction in the ledger if (!d->m_selectedAccount.id().isEmpty()) d->m_myMoneyView->slotLedgerSelected(d->m_selectedAccount.id(), lt.id()); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to duplicate transaction(s): %1, thrown in %2:%3", e.what(), e.file(), e.line())); } // switch off the progress bar slotStatusProgressBar(-1, -1); } } void KMyMoneyApp::doDeleteTransactions() { KMyMoneyRegister::SelectedTransactions list = d->m_selectedTransactions; KMyMoneyRegister::SelectedTransactions::iterator it_t; int cnt = list.count(); int i = 0; slotStatusProgressBar(0, cnt); MyMoneyFileTransaction ft; MyMoneyFile* file = MyMoneyFile::instance(); try { it_t = list.begin(); while (it_t != list.end()) { // only remove those transactions that do not reference a closed account if (!file->referencesClosedAccount((*it_t).transaction())) { file->removeTransaction((*it_t).transaction()); // remove all those references in the list of selected transactions // that refer to the same transaction we just removed so that we // will not be caught by an exception later on (see bko #285310) KMyMoneyRegister::SelectedTransactions::iterator it_td = it_t; ++it_td; while (it_td != list.end()) { if ((*it_t).transaction().id() == (*it_td).transaction().id()) { it_td = list.erase(it_td); i++; // bump count of deleted transactions } else { ++it_td; } } } // need to ensure "nextCheckNumber" is still correct MyMoneyAccount acc = file->account((*it_t).split().accountId()); // the "lastNumberUsed" might have been the txn number deleted // so adjust it QString deletedNum = (*it_t).split().number(); // decrement deletedNum and set new "lastNumberUsed" QString num = KMyMoneyUtils::getAdjacentNumber(deletedNum, -1); acc.setValue("lastNumberUsed", num); file->modifyAccount(acc); list.erase(it_t); it_t = list.begin(); slotStatusProgressBar(i++, 0); } ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to delete transaction(s): %1, thrown in %2:%3", e.what(), e.file(), e.line())); } slotStatusProgressBar(-1, -1); } void KMyMoneyApp::slotTransactionsNew() { // since we jump here via code, we have to make sure to react only // if the action is enabled if (kmymoney->actionCollection()->action(s_Actions[Action::TransactionNew])->isEnabled()) { if (d->m_myMoneyView->createNewTransaction()) { d->m_transactionEditor = d->m_myMoneyView->startEdit(d->m_selectedTransactions); if (d->m_transactionEditor) { KMyMoneyMVCCombo::setSubstringSearchForChildren(d->m_myMoneyView, !KMyMoneySettings::stringMatchFromStart()); KMyMoneyPayeeCombo* payeeEdit = dynamic_cast(d->m_transactionEditor->haveWidget("payee")); if (payeeEdit && !d->m_lastPayeeEnteredId.isEmpty()) { // in case we entered a new transaction before and used a payee, // we reuse it here. Save the text to the edit widget, select it // so that hitting any character will start entering another payee. payeeEdit->setSelectedItem(d->m_lastPayeeEnteredId); payeeEdit->lineEdit()->selectAll(); } if (d->m_transactionEditor) { connect(d->m_transactionEditor, SIGNAL(statusProgress(int,int)), this, SLOT(slotStatusProgressBar(int,int))); connect(d->m_transactionEditor, SIGNAL(statusMsg(QString)), this, SLOT(slotStatusMsg(QString))); connect(d->m_transactionEditor, SIGNAL(scheduleTransaction(MyMoneyTransaction,eMyMoney::Schedule::Occurrence)), this, SLOT(slotScheduleNew(MyMoneyTransaction,eMyMoney::Schedule::Occurrence))); } slotUpdateActions(); } } } } void KMyMoneyApp::slotTransactionsEdit() { // qDebug("KMyMoneyApp::slotTransactionsEdit()"); // since we jump here via code, we have to make sure to react only // if the action is enabled if (kmymoney->actionCollection()->action(s_Actions[Action::TransactionEdit])->isEnabled()) { // as soon as we edit a transaction, we don't remember the last payee entered d->m_lastPayeeEnteredId.clear(); d->m_transactionEditor = d->m_myMoneyView->startEdit(d->m_selectedTransactions); KMyMoneyMVCCombo::setSubstringSearchForChildren(d->m_myMoneyView, !KMyMoneySettings::stringMatchFromStart()); slotUpdateActions(); } } void KMyMoneyApp::deleteTransactionEditor() { // make sure, we don't use the transaction editor pointer // anymore from now on TransactionEditor* p = d->m_transactionEditor; d->m_transactionEditor = 0; delete p; } void KMyMoneyApp::slotTransactionsEditSplits() { // since we jump here via code, we have to make sure to react only // if the action is enabled if (kmymoney->actionCollection()->action(s_Actions[Action::TransactionEditSplits])->isEnabled()) { // as soon as we edit a transaction, we don't remember the last payee entered d->m_lastPayeeEnteredId.clear(); d->m_transactionEditor = d->m_myMoneyView->startEdit(d->m_selectedTransactions); slotUpdateActions(); if (d->m_transactionEditor) { KMyMoneyMVCCombo::setSubstringSearchForChildren(d->m_myMoneyView, !KMyMoneySettings::stringMatchFromStart()); if (d->m_transactionEditor->slotEditSplits() == QDialog::Accepted) { MyMoneyFileTransaction ft; try { QString id; connect(d->m_transactionEditor, SIGNAL(balanceWarning(QWidget*,MyMoneyAccount,QString)), d->m_balanceWarning, SLOT(slotShowMessage(QWidget*,MyMoneyAccount,QString))); d->m_transactionEditor->enterTransactions(id); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to modify transaction: %1, thrown in %2:%3", e.what(), e.file(), e.line())); } } } deleteTransactionEditor(); slotUpdateActions(); } } void KMyMoneyApp::slotTransactionsCancel() { // since we jump here via code, we have to make sure to react only // if the action is enabled if (kmymoney->actionCollection()->action(s_Actions[Action::TransactionCancel])->isEnabled()) { // make sure, we block the enter function actionCollection()->action(s_Actions[Action::TransactionEnter])->setEnabled(false); // qDebug("KMyMoneyApp::slotTransactionsCancel"); deleteTransactionEditor(); slotUpdateActions(); } } void KMyMoneyApp::slotTransactionsEnter() { // since we jump here via code, we have to make sure to react only // if the action is enabled if (kmymoney->actionCollection()->action(s_Actions[Action::TransactionEnter])->isEnabled()) { // disable the action while we process it to make sure it's processed only once since // d->m_transactionEditor->enterTransactions(newId) will run QCoreApplication::processEvents // we could end up here twice which will cause a crash slotUpdateActions() will enable the action again kmymoney->actionCollection()->action(s_Actions[Action::TransactionEnter])->setEnabled(false); if (d->m_transactionEditor) { QString accountId = d->m_selectedAccount.id(); QString newId; connect(d->m_transactionEditor, SIGNAL(balanceWarning(QWidget*,MyMoneyAccount,QString)), d->m_balanceWarning, SLOT(slotShowMessage(QWidget*,MyMoneyAccount,QString))); if (d->m_transactionEditor->enterTransactions(newId)) { KMyMoneyPayeeCombo* payeeEdit = dynamic_cast(d->m_transactionEditor->haveWidget("payee")); if (payeeEdit && !newId.isEmpty()) { d->m_lastPayeeEnteredId = payeeEdit->selectedItem(); } deleteTransactionEditor(); } if (!newId.isEmpty()) { d->m_myMoneyView->slotLedgerSelected(accountId, newId); } } slotUpdateActions(); } } void KMyMoneyApp::slotTransactionsCancelOrEnter(bool& okToSelect) { static bool oneTime = false; if (!oneTime) { oneTime = true; QString dontShowAgain = "CancelOrEditTransaction"; // qDebug("KMyMoneyApp::slotCancelOrEndEdit"); if (d->m_transactionEditor) { if (KMyMoneyGlobalSettings::focusChangeIsEnter() && kmymoney->actionCollection()->action(s_Actions[Action::TransactionEnter])->isEnabled()) { slotTransactionsEnter(); if (d->m_transactionEditor) { // if at this stage the editor is still there that means that entering the transaction was cancelled // for example by pressing cancel on the exchange rate editor so we must stay in edit mode okToSelect = false; } } else { // okToSelect is preset to true if a cancel of the dialog is useful and false if it is not int rc; KGuiItem noGuiItem = KStandardGuiItem::save(); KGuiItem yesGuiItem = KStandardGuiItem::discard(); KGuiItem cancelGuiItem = KStandardGuiItem::cont(); // if the transaction can't be entered make sure that it can't be entered by pressing no either if (!kmymoney->actionCollection()->action(s_Actions[Action::TransactionEnter])->isEnabled()) { noGuiItem.setEnabled(false); noGuiItem.setToolTip(kmymoney->actionCollection()->action(s_Actions[Action::TransactionEnter])->toolTip()); } if (okToSelect == true) { rc = KMessageBox::warningYesNoCancel(0, i18n("

Please select what you want to do: discard the changes, save the changes or continue to edit the transaction.

You can also set an option to save the transaction automatically when e.g. selecting another transaction.

"), i18n("End transaction edit"), yesGuiItem, noGuiItem, cancelGuiItem, dontShowAgain); } else { rc = KMessageBox::warningYesNo(0, i18n("

Please select what you want to do: discard the changes, save the changes or continue to edit the transaction.

You can also set an option to save the transaction automatically when e.g. selecting another transaction.

"), i18n("End transaction edit"), yesGuiItem, noGuiItem, dontShowAgain); } switch (rc) { case KMessageBox::Yes: slotTransactionsCancel(); break; case KMessageBox::No: slotTransactionsEnter(); // make sure that we'll see this message the next time no matter // if the user has chosen the 'Don't show again' checkbox KMessageBox::enableMessage(dontShowAgain); if (d->m_transactionEditor) { // if at this stage the editor is still there that means that entering the transaction was cancelled // for example by pressing cancel on the exchange rate editor so we must stay in edit mode okToSelect = false; } break; case KMessageBox::Cancel: // make sure that we'll see this message the next time no matter // if the user has chosen the 'Don't show again' checkbox KMessageBox::enableMessage(dontShowAgain); okToSelect = false; break; } } } oneTime = false; } } void KMyMoneyApp::slotToggleReconciliationFlag() { markTransaction(eMyMoney::Split::State::Unknown); } void KMyMoneyApp::slotMarkTransactionCleared() { markTransaction(eMyMoney::Split::State::Cleared); } void KMyMoneyApp::slotMarkTransactionReconciled() { markTransaction(eMyMoney::Split::State::Reconciled); } void KMyMoneyApp::slotMarkTransactionNotReconciled() { markTransaction(eMyMoney::Split::State::NotReconciled); } void KMyMoneyApp::markTransaction(eMyMoney::Split::State flag) { KMyMoneyRegister::SelectedTransactions list = d->m_selectedTransactions; KMyMoneyRegister::SelectedTransactions::const_iterator it_t; int cnt = list.count(); int i = 0; slotStatusProgressBar(0, cnt); MyMoneyFileTransaction ft; try { for (it_t = list.constBegin(); it_t != list.constEnd(); ++it_t) { // turn on signals before we modify the last entry in the list cnt--; MyMoneyFile::instance()->blockSignals(cnt != 0); // get a fresh copy MyMoneyTransaction t = MyMoneyFile::instance()->transaction((*it_t).transaction().id()); MyMoneySplit sp = t.splitById((*it_t).split().id()); if (sp.reconcileFlag() != flag) { if (flag == eMyMoney::Split::State::Unknown) { if (d->m_reconciliationAccount.id().isEmpty()) { // in normal mode we cycle through all states switch (sp.reconcileFlag()) { case eMyMoney::Split::State::NotReconciled: sp.setReconcileFlag(eMyMoney::Split::State::Cleared); break; case eMyMoney::Split::State::Cleared: sp.setReconcileFlag(eMyMoney::Split::State::Reconciled); break; case eMyMoney::Split::State::Reconciled: sp.setReconcileFlag(eMyMoney::Split::State::NotReconciled); break; default: break; } } else { // in reconciliation mode we skip the reconciled state switch (sp.reconcileFlag()) { case eMyMoney::Split::State::NotReconciled: sp.setReconcileFlag(eMyMoney::Split::State::Cleared); break; case eMyMoney::Split::State::Cleared: sp.setReconcileFlag(eMyMoney::Split::State::NotReconciled); break; default: break; } } } else { sp.setReconcileFlag(flag); } t.modifySplit(sp); MyMoneyFile::instance()->modifyTransaction(t); } slotStatusProgressBar(i++, 0); } slotStatusProgressBar(-1, -1); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to modify transaction: %1, thrown in %2:%3", e.what(), e.file(), e.line())); } } void KMyMoneyApp::slotTransactionsAccept() { KMyMoneyRegister::SelectedTransactions list = d->m_selectedTransactions; KMyMoneyRegister::SelectedTransactions::const_iterator it_t; int cnt = list.count(); int i = 0; slotStatusProgressBar(0, cnt); MyMoneyFileTransaction ft; try { for (it_t = list.constBegin(); it_t != list.constEnd(); ++it_t) { // reload transaction in case it got changed during the course of this loop MyMoneyTransaction t = MyMoneyFile::instance()->transaction((*it_t).transaction().id()); if (t.isImported()) { t.setImported(false); if (!d->m_selectedAccount.id().isEmpty()) { QList list = t.splits(); QList::const_iterator it_s; for (it_s = list.constBegin(); it_s != list.constEnd(); ++it_s) { if ((*it_s).accountId() == d->m_selectedAccount.id()) { if ((*it_s).reconcileFlag() == eMyMoney::Split::State::NotReconciled) { MyMoneySplit s = (*it_s); s.setReconcileFlag(eMyMoney::Split::State::Cleared); t.modifySplit(s); } } } } MyMoneyFile::instance()->modifyTransaction(t); } if ((*it_t).split().isMatched()) { // reload split in case it got changed during the course of this loop MyMoneySplit s = t.splitById((*it_t).split().id()); TransactionMatcher matcher(d->m_selectedAccount); matcher.accept(t, s); } slotStatusProgressBar(i++, 0); } slotStatusProgressBar(-1, -1); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Error"), i18n("Unable to accept transaction: %1, thrown in %2:%3", e.what(), e.file(), e.line())); } } void KMyMoneyApp::slotTransactionGotoAccount() { if (!d->m_accountGoto.isEmpty()) { try { QString transactionId; if (d->m_selectedTransactions.count() == 1) { transactionId = d->m_selectedTransactions[0].transaction().id(); } // make sure to pass a copy, as d->myMoneyView->slotLedgerSelected() overrides // d->m_accountGoto while calling slotUpdateActions() QString accountId = d->m_accountGoto; d->m_myMoneyView->slotLedgerSelected(accountId, transactionId); } catch (const MyMoneyException &) { } } } void KMyMoneyApp::slotTransactionGotoPayee() { if (!d->m_payeeGoto.isEmpty()) { try { QString transactionId; if (d->m_selectedTransactions.count() == 1) { transactionId = d->m_selectedTransactions[0].transaction().id(); } // make sure to pass copies, as d->myMoneyView->slotPayeeSelected() overrides // d->m_payeeGoto and d->m_selectedAccount while calling slotUpdateActions() QString payeeId = d->m_payeeGoto; QString accountId = d->m_selectedAccount.id(); d->m_myMoneyView->slotPayeeSelected(payeeId, accountId, transactionId); } catch (const MyMoneyException &) { } } } void KMyMoneyApp::slotTransactionCreateSchedule() { if (d->m_selectedTransactions.count() == 1) { // make sure to have the current selected split as first split in the schedule MyMoneyTransaction t = d->m_selectedTransactions[0].transaction(); MyMoneySplit s = d->m_selectedTransactions[0].split(); QString splitId = s.id(); s.clearId(); s.setReconcileFlag(eMyMoney::Split::State::NotReconciled); s.setReconcileDate(QDate()); t.removeSplits(); t.addSplit(s); const QList& splits = d->m_selectedTransactions[0].transaction().splits(); QList::const_iterator it_s; for (it_s = splits.begin(); it_s != splits.end(); ++it_s) { if ((*it_s).id() != splitId) { MyMoneySplit s0 = (*it_s); s0.clearId(); s0.setReconcileFlag(eMyMoney::Split::State::NotReconciled); s0.setReconcileDate(QDate()); t.addSplit(s0); } } slotScheduleNew(t); } } void KMyMoneyApp::slotTransactionAssignNumber() { if (d->m_transactionEditor) d->m_transactionEditor->assignNextNumber(); } void KMyMoneyApp::slotTransactionCombine() { qDebug("slotTransactionCombine() not implemented yet"); } void KMyMoneyApp::slotTransactionCopySplits() { MyMoneyFile* file = MyMoneyFile::instance(); if (d->m_selectedTransactions.count() >= 2) { int singleSplitTransactions = 0; int multipleSplitTransactions = 0; KMyMoneyRegister::SelectedTransaction selectedSourceTransaction; foreach (const KMyMoneyRegister::SelectedTransaction& st, d->m_selectedTransactions) { switch (st.transaction().splitCount()) { case 0: break; case 1: singleSplitTransactions++; break; default: selectedSourceTransaction = st; multipleSplitTransactions++; break; } } if (singleSplitTransactions > 0 && multipleSplitTransactions == 1) { MyMoneyFileTransaction ft; try { const MyMoneyTransaction& sourceTransaction = selectedSourceTransaction.transaction(); const MyMoneySplit& sourceSplit = selectedSourceTransaction.split(); foreach (const KMyMoneyRegister::SelectedTransaction& st, d->m_selectedTransactions) { MyMoneyTransaction t = st.transaction(); // don't process the source transaction if (sourceTransaction.id() == t.id()) { continue; } const MyMoneySplit& baseSplit = st.split(); if (t.splitCount() == 1) { foreach (const MyMoneySplit& split, sourceTransaction.splits()) { // Don't copy the source split, as we already have that // as part of the destination transaction if (split.id() == sourceSplit.id()) { continue; } MyMoneySplit sp(split); // clear the ID and reconciliation state sp.clearId(); sp.setReconcileFlag(eMyMoney::Split::State::NotReconciled); sp.setReconcileDate(QDate()); // in case it is a simple transaction consisting of two splits, // we can adjust the share and value part of the second split we // just created. We need to keep a possible price in mind in case // of different currencies if (sourceTransaction.splitCount() == 2) { sp.setValue(-baseSplit.value()); sp.setShares(-(baseSplit.shares() * baseSplit.price())); } t.addSplit(sp); } file->modifyTransaction(t); } } ft.commit(); } catch (const MyMoneyException &) { qDebug() << "transactionCopySplits() failed"; } } } } void KMyMoneyApp::slotMoveToAccount(const QString& id) { // close the menu, if it is still open QWidget* w = factory()->container("transaction_context_menu", this); if (w && w->isVisible()) { w->close(); } if (!d->m_selectedTransactions.isEmpty()) { MyMoneyFileTransaction ft; try { KMyMoneyRegister::SelectedTransactions::const_iterator it_t; for (it_t = d->m_selectedTransactions.constBegin(); it_t != d->m_selectedTransactions.constEnd(); ++it_t) { if (d->m_selectedAccount.accountType() == eMyMoney::Account::Investment) { d->moveInvestmentTransaction(d->m_selectedAccount.id(), id, (*it_t).transaction()); } else { QList::const_iterator it_s; bool changed = false; MyMoneyTransaction t = (*it_t).transaction(); for (it_s = (*it_t).transaction().splits().constBegin(); it_s != (*it_t).transaction().splits().constEnd(); ++it_s) { if ((*it_s).accountId() == d->m_selectedAccount.id()) { MyMoneySplit s = (*it_s); s.setAccountId(id); t.modifySplit(s); changed = true; } } if (changed) { MyMoneyFile::instance()->modifyTransaction(t); } } } ft.commit(); } catch (const MyMoneyException &) { } } } // move a stock transaction from one investment account to another void KMyMoneyApp::Private::moveInvestmentTransaction(const QString& /*fromId*/, const QString& toId, const MyMoneyTransaction& tx) { MyMoneyAccount toInvAcc = MyMoneyFile::instance()->account(toId); MyMoneyTransaction t(tx); // first determine which stock we are dealing with. // fortunately, investment transactions have only one stock involved QString stockAccountId; QString stockSecurityId; MyMoneySplit s; for (QList::const_iterator it_s = t.splits().constBegin(); it_s != t.splits().constEnd(); ++it_s) { stockAccountId = (*it_s).accountId(); stockSecurityId = MyMoneyFile::instance()->account(stockAccountId).currencyId(); if (!MyMoneyFile::instance()->security(stockSecurityId).isCurrency()) { s = *it_s; break; } } // Now check the target investment account to see if it // contains a stock with this id QString newStockAccountId; QStringList accountList = toInvAcc.accountList(); for (QStringList::const_iterator it_a = accountList.constBegin(); it_a != accountList.constEnd(); ++it_a) { if (MyMoneyFile::instance()->account((*it_a)).currencyId() == stockSecurityId) { newStockAccountId = (*it_a); break; } } // if it doesn't exist, we need to add it as a copy of the old one // no 'copyAccount()' function?? if (newStockAccountId.isEmpty()) { MyMoneyAccount stockAccount = MyMoneyFile::instance()->account(stockAccountId); MyMoneyAccount newStock; newStock.setName(stockAccount.name()); newStock.setNumber(stockAccount.number()); newStock.setDescription(stockAccount.description()); newStock.setInstitutionId(stockAccount.institutionId()); newStock.setOpeningDate(stockAccount.openingDate()); newStock.setAccountType(stockAccount.accountType()); newStock.setCurrencyId(stockAccount.currencyId()); newStock.setClosed(stockAccount.isClosed()); MyMoneyFile::instance()->addAccount(newStock, toInvAcc); newStockAccountId = newStock.id(); } // now update the split and the transaction s.setAccountId(newStockAccountId); t.modifySplit(s); MyMoneyFile::instance()->modifyTransaction(t); } void KMyMoneyApp::slotUpdateMoveToAccountMenu() { createTransactionMoveMenu(); // in case we were not able to create the selector, we // better get out of here. Anything else would cause // a crash later on (accountSet.load) if (!d->m_moveToAccountSelector) return; if (!d->m_selectedAccount.id().isEmpty()) { AccountSet accountSet; if (d->m_selectedAccount.accountType() == eMyMoney::Account::Investment) { accountSet.addAccountType(eMyMoney::Account::Investment); } else if (d->m_selectedAccount.isAssetLiability()) { accountSet.addAccountType(eMyMoney::Account::Checkings); accountSet.addAccountType(eMyMoney::Account::Savings); accountSet.addAccountType(eMyMoney::Account::Cash); accountSet.addAccountType(eMyMoney::Account::AssetLoan); accountSet.addAccountType(eMyMoney::Account::CertificateDep); accountSet.addAccountType(eMyMoney::Account::MoneyMarket); accountSet.addAccountType(eMyMoney::Account::Asset); accountSet.addAccountType(eMyMoney::Account::Currency); accountSet.addAccountType(eMyMoney::Account::CreditCard); accountSet.addAccountType(eMyMoney::Account::Loan); accountSet.addAccountType(eMyMoney::Account::Liability); } else if (d->m_selectedAccount.isIncomeExpense()) { accountSet.addAccountType(eMyMoney::Account::Income); accountSet.addAccountType(eMyMoney::Account::Expense); } accountSet.load(d->m_moveToAccountSelector); // remove those accounts that we currently reference KMyMoneyRegister::SelectedTransactions::const_iterator it_t; for (it_t = d->m_selectedTransactions.constBegin(); it_t != d->m_selectedTransactions.constEnd(); ++it_t) { QList::const_iterator it_s; for (it_s = (*it_t).transaction().splits().constBegin(); it_s != (*it_t).transaction().splits().constEnd(); ++it_s) { d->m_moveToAccountSelector->removeItem((*it_s).accountId()); } } // remove those accounts from the list that are denominated // in a different currency QStringList list = d->m_moveToAccountSelector->accountList(); QList::const_iterator it_a; for (it_a = list.constBegin(); it_a != list.constEnd(); ++it_a) { MyMoneyAccount acc = MyMoneyFile::instance()->account(*it_a); if (acc.currencyId() != d->m_selectedAccount.currencyId()) d->m_moveToAccountSelector->removeItem((*it_a)); } } } void KMyMoneyApp::slotTransactionMatch() { // if the menu action is retrieved it can contain an '&' character for the accelerator causing the comparison to fail if not removed QString transactionActionText = actionCollection()->action(s_Actions[Action::TransactionMatch])->text(); transactionActionText.remove('&'); if (transactionActionText == i18nc("Button text for match transaction", "Match")) transactionMatch(); else transactionUnmatch(); } void KMyMoneyApp::transactionUnmatch() { KMyMoneyRegister::SelectedTransactions::const_iterator it; MyMoneyFileTransaction ft; try { for (it = d->m_selectedTransactions.constBegin(); it != d->m_selectedTransactions.constEnd(); ++it) { if ((*it).split().isMatched()) { TransactionMatcher matcher(d->m_selectedAccount); matcher.unmatch((*it).transaction(), (*it).split()); } } ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Unable to unmatch the selected transactions"), e.what()); } } void KMyMoneyApp::transactionMatch() { if (d->m_selectedTransactions.count() != 2) return; MyMoneyTransaction startMatchTransaction; MyMoneyTransaction endMatchTransaction; MyMoneySplit startSplit; MyMoneySplit endSplit; KMyMoneyRegister::SelectedTransactions::const_iterator it; KMyMoneyRegister::SelectedTransactions toBeDeleted; for (it = d->m_selectedTransactions.constBegin(); it != d->m_selectedTransactions.constEnd(); ++it) { if ((*it).transaction().isImported()) { if (endMatchTransaction.id().isEmpty()) { endMatchTransaction = (*it).transaction(); endSplit = (*it).split(); toBeDeleted << *it; } else { //This is a second imported transaction, we still want to merge startMatchTransaction = (*it).transaction(); startSplit = (*it).split(); } } else if (!(*it).split().isMatched()) { if (startMatchTransaction.id().isEmpty()) { startMatchTransaction = (*it).transaction(); startSplit = (*it).split(); } else { endMatchTransaction = (*it).transaction(); endSplit = (*it).split(); toBeDeleted << *it; } } } #if 0 KMergeTransactionsDlg dlg(d->m_selectedAccount); dlg.addTransaction(startMatchTransaction); dlg.addTransaction(endMatchTransaction); if (dlg.exec() == QDialog::Accepted) #endif { MyMoneyFileTransaction ft; try { if (startMatchTransaction.id().isEmpty()) throw MYMONEYEXCEPTION(i18n("No manually entered transaction selected for matching")); if (endMatchTransaction.id().isEmpty()) throw MYMONEYEXCEPTION(i18n("No imported transaction selected for matching")); TransactionMatcher matcher(d->m_selectedAccount); matcher.match(startMatchTransaction, startSplit, endMatchTransaction, endSplit, true); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Unable to match the selected transactions"), e.what()); } } } void KMyMoneyApp::showContextMenu(const QString& containerName) { QWidget* w = factory()->container(containerName, this); QMenu *menu = dynamic_cast(w); if (menu) menu->exec(QCursor::pos()); else qDebug("menu '%s' not found: w = %p, menu = %p", qPrintable(containerName), w, menu); } void KMyMoneyApp::slotShowTransactionContextMenu() { if (d->m_selectedTransactions.isEmpty() && d->m_selectedSchedule != MyMoneySchedule()) { showContextMenu("schedule_context_menu"); } else { showContextMenu("transaction_context_menu"); } } void KMyMoneyApp::slotShowInvestmentContextMenu() { showContextMenu("investment_context_menu"); } void KMyMoneyApp::slotShowScheduleContextMenu() { showContextMenu("schedule_context_menu"); } void KMyMoneyApp::slotShowAccountContextMenu(const MyMoneyObject& obj) { // qDebug("KMyMoneyApp::slotShowAccountContextMenu"); if (typeid(obj) != typeid(MyMoneyAccount)) return; const MyMoneyAccount& acc = dynamic_cast(obj); // if the selected account is actually a stock account, we // call the right slot instead if (acc.isInvest()) { showContextMenu("investment_context_menu"); } else if (acc.isIncomeExpense()) { showContextMenu("category_context_menu"); } else { showContextMenu("account_context_menu"); } } void KMyMoneyApp::slotShowInstitutionContextMenu(const MyMoneyObject& obj) { if (typeid(obj) != typeid(MyMoneyInstitution)) return; showContextMenu("institution_context_menu"); } void KMyMoneyApp::slotShowPayeeContextMenu() { showContextMenu("payee_context_menu"); } void KMyMoneyApp::slotShowTagContextMenu() { showContextMenu("tag_context_menu"); } void KMyMoneyApp::slotShowBudgetContextMenu() { showContextMenu("budget_context_menu"); } void KMyMoneyApp::slotShowCurrencyContextMenu() { showContextMenu("currency_context_menu"); } void KMyMoneyApp::slotShowPriceContextMenu() { showContextMenu("price_context_menu"); } void KMyMoneyApp::slotShowOnlineJobContextMenu() { showContextMenu("onlinejob_context_menu"); } void KMyMoneyApp::slotPrintView() { d->m_myMoneyView->slotPrintView(); } void KMyMoneyApp::updateCaption(bool skipActions) { QString caption; caption = d->m_fileName.fileName(); if (caption.isEmpty() && d->m_myMoneyView && d->m_myMoneyView->fileOpen()) caption = i18n("Untitled"); // MyMoneyFile::instance()->dirty() throws an exception, if // there's no storage object available. In this case, we // assume that the storage object is not changed. Actually, // this can only happen if we are newly created early on. bool modified; try { modified = MyMoneyFile::instance()->dirty(); } catch (const MyMoneyException &) { modified = false; skipActions = true; } #ifdef KMM_DEBUG caption += QString(" (%1 x %2)").arg(width()).arg(height()); #endif setCaption(caption, modified); if (!skipActions) { d->m_myMoneyView->enableViewsIfFileOpen(); slotUpdateActions(); } } void KMyMoneyApp::slotUpdateActions() { MyMoneyFile* file = MyMoneyFile::instance(); const bool fileOpen = d->m_myMoneyView->fileOpen(); const bool modified = file->dirty(); const bool importRunning = (d->m_smtReader != 0); QWidget* w; KActionCollection *aC = actionCollection(); // ************* // Disabling actions to be disabled at this point // ************* { static const QVector disabledActions { Action::AccountStartReconciliation, Action::AccountFinishReconciliation, Action::AccountPostponeReconciliation, Action::AccountEdit, Action::AccountDelete, Action::AccountOpen, Action::AccountClose, Action::AccountReopen, Action::AccountTransactionReport, Action::AccountOnlineMap, Action::AccountOnlineUnmap, Action::AccountUpdate, Action::AccountUpdateAll, Action::AccountBalanceChart, Action::CategoryEdit, Action::CategoryDelete, Action::InstitutionEdit, Action::InstitutionDelete, Action::InvestmentEdit, Action::InvestmentNew, Action::InvestmentDelete, Action::InvestmentOnlinePrice, Action::InvestmentManualPrice, Action::ScheduleEdit, Action::ScheduleDelete, Action::ScheduleEnter, Action::ScheduleSkip, Action::PayeeDelete, Action::PayeeRename, Action::PayeeMerge, Action::TagDelete, Action::TagRename, Action::BudgetDelete, Action::BudgetRename, Action::BudgetChangeYear, Action::BudgetNew, Action::BudgetCopy, Action::BudgetForecast, Action::TransactionEdit, Action::TransactionEditSplits, Action::TransactionEnter, Action::TransactionCancel, Action::TransactionDelete, Action::TransactionMatch, Action::TransactionAccept, Action::TransactionDuplicate, Action::TransactionToggleReconciled, Action::TransactionToggleCleared, Action::TransactionGoToAccount, Action::TransactionGoToPayee, Action::TransactionAssignNumber, Action::TransactionCreateSchedule, Action::TransactionCombine, Action::TransactionSelectAll, Action::TransactionCopySplits, Action::ScheduleEdit, Action::ScheduleDelete, Action::ScheduleDuplicate, Action::ScheduleEnter, Action::ScheduleSkip, Action::CurrencyRename, Action::CurrencyDelete, Action::CurrencySetBase, Action::PriceEdit, Action::PriceDelete, Action::PriceUpdate }; foreach (const auto a, disabledActions) aC->action(s_Actions.value(a))->setEnabled(false); } // ************* // Disabling actions based on conditions // ************* { QString tooltip = i18n("Create a new transaction"); const QVector> actionStates { {qMakePair(Action::FileOpenDatabase, true)}, {qMakePair(Action::FileSaveAsDatabase, fileOpen)}, {qMakePair(Action::FilePersonalData, fileOpen)}, {qMakePair(Action::FileBackup, (fileOpen && !d->m_myMoneyView->isDatabase()))}, {qMakePair(Action::FileInformation, fileOpen)}, {qMakePair(Action::FileImportGNC, !importRunning)}, {qMakePair(Action::FileImportTemplate, fileOpen && !importRunning)}, {qMakePair(Action::FileExportTemplate, fileOpen && !importRunning)}, #ifdef KMM_DEBUG {qMakePair(Action::FileDump, fileOpen)}, #endif {qMakePair(Action::EditFindTransaction, fileOpen)}, {qMakePair(Action::ToolCurrencies, fileOpen)}, {qMakePair(Action::ToolPrices, fileOpen)}, {qMakePair(Action::ToolUpdatePrices, fileOpen)}, {qMakePair(Action::ToolConsistency, fileOpen)}, {qMakePair(Action::AccountNew, fileOpen)}, {qMakePair(Action::AccountCreditTransfer, onlineJobAdministration::instance()->canSendCreditTransfer())}, {qMakePair(Action::CategoryDelete, fileOpen)}, {qMakePair(Action::InstitutionNew, fileOpen)}, {qMakePair(Action::TransactionNew, (fileOpen && d->m_myMoneyView->canCreateTransactions(KMyMoneyRegister::SelectedTransactions(), tooltip)))}, {qMakePair(Action::ScheduleNew, fileOpen)}, {qMakePair(Action::CurrencyNew, fileOpen)}, {qMakePair(Action::PriceNew, fileOpen)}, }; foreach (const auto a, actionStates) aC->action(s_Actions.value(a.first))->setEnabled(a.second); } // ************* // Disabling standard actions based on conditions // ************* aC->action(QString::fromLatin1(KStandardAction::name(KStandardAction::Save)))->setEnabled(modified && !d->m_myMoneyView->isDatabase()); aC->action(QString::fromLatin1(KStandardAction::name(KStandardAction::SaveAs)))->setEnabled(fileOpen); aC->action(QString::fromLatin1(KStandardAction::name(KStandardAction::Close)))->setEnabled(fileOpen); aC->action(QString::fromLatin1(KStandardAction::name(KStandardAction::Print)))->setEnabled(fileOpen && d->m_myMoneyView->canPrint()); aC->action(s_Actions[Action::TransactionMatch])->setText(i18nc("Button text for match transaction", "Match")); aC->action(s_Actions[Action::TransactionNew])->setToolTip(i18n("Create a new transaction")); w = factory()->container(s_Actions[Action::TransactionMoveMenu], this); if (w) w->setEnabled(false); w = factory()->container(s_Actions[Action::TransactionMarkMenu], this); if (w) w->setEnabled(false); w = factory()->container(s_Actions[Action::TransactionContextMarkMenu], this); if (w) w->setEnabled(false); // ************* // Enabling actions based on conditions // ************* // FIXME for now it's always on, but we should only allow it, if we // can select at least a single transaction aC->action(s_Actions[Action::TransactionSelectAll])->setEnabled(true); if (!d->m_selectedTransactions.isEmpty()) { // enable 'delete transaction' only if at least one of the // selected transactions does not reference a closed account bool enable = false; KMyMoneyRegister::SelectedTransactions::const_iterator it_t; for (it_t = d->m_selectedTransactions.constBegin(); (enable == false) && (it_t != d->m_selectedTransactions.constEnd()); ++it_t) { enable = !(*it_t).transaction().id().isEmpty() && !file->referencesClosedAccount((*it_t).transaction()); } aC->action(s_Actions[Action::TransactionDelete])->setEnabled(enable); if (!d->m_transactionEditor) { QString tooltip = i18n("Duplicate the current selected transactions"); aC->action(s_Actions[Action::TransactionDuplicate])->setEnabled(d->m_myMoneyView->canDuplicateTransactions(d->m_selectedTransactions, tooltip) && !d->m_selectedTransactions[0].transaction().id().isEmpty()); aC->action(s_Actions[Action::TransactionDuplicate])->setToolTip(tooltip); if (d->m_myMoneyView->canEditTransactions(d->m_selectedTransactions, tooltip)) { aC->action(s_Actions[Action::TransactionEdit])->setEnabled(true); // editing splits is allowed only if we have one transaction selected if (d->m_selectedTransactions.count() == 1) { aC->action(s_Actions[Action::TransactionEditSplits])->setEnabled(true); } if (d->m_selectedAccount.isAssetLiability() && d->m_selectedAccount.accountType() != eMyMoney::Account::Investment) { aC->action(s_Actions[Action::TransactionCreateSchedule])->setEnabled(d->m_selectedTransactions.count() == 1); } } aC->action(s_Actions[Action::TransactionEdit])->setToolTip(tooltip); if (!d->m_selectedAccount.isClosed()) { w = factory()->container(s_Actions[Action::TransactionMoveMenu], this); if (w) w->setEnabled(true); } w = factory()->container(s_Actions[Action::TransactionMarkMenu], this); if (w) w->setEnabled(true); w = factory()->container(s_Actions[Action::TransactionContextMarkMenu], this); if (w) w->setEnabled(true); // Allow marking the transaction if at least one is selected aC->action(s_Actions[Action::TransactionToggleCleared])->setEnabled(true); aC->action(s_Actions[Action::TransactionReconciled])->setEnabled(true); aC->action(s_Actions[Action::TransactionNotReconciled])->setEnabled(true); aC->action(s_Actions[Action::TransactionToggleReconciled])->setEnabled(true); if (!d->m_accountGoto.isEmpty()) aC->action(s_Actions[Action::TransactionGoToAccount])->setEnabled(true); if (!d->m_payeeGoto.isEmpty()) aC->action(s_Actions[Action::TransactionGoToPayee])->setEnabled(true); // Matching is enabled as soon as one regular and one imported transaction is selected int matchedCount = 0; int importedCount = 0; KMyMoneyRegister::SelectedTransactions::const_iterator it; for (it = d->m_selectedTransactions.constBegin(); it != d->m_selectedTransactions.constEnd(); ++it) { if ((*it).transaction().isImported()) ++importedCount; if ((*it).split().isMatched()) ++matchedCount; } if (d->m_selectedTransactions.count() == 2 /* && aC->action(s_Actions[Action::TransactionEdit])->isEnabled() */) { aC->action(s_Actions[Action::TransactionMatch])->setEnabled(true); } if (importedCount != 0 || matchedCount != 0) aC->action(s_Actions[Action::TransactionAccept])->setEnabled(true); if (matchedCount != 0) { aC->action(s_Actions[Action::TransactionMatch])->setEnabled(true); aC->action(s_Actions[Action::TransactionMatch])->setText(i18nc("Button text for unmatch transaction", "Unmatch")); aC->action(s_Actions[Action::TransactionMatch])->setIcon(QIcon("process-stop")); } if (d->m_selectedTransactions.count() > 1) { aC->action(s_Actions[Action::TransactionCombine])->setEnabled(true); } if (d->m_selectedTransactions.count() >= 2) { int singleSplitTransactions = 0; int multipleSplitTransactions = 0; foreach (const KMyMoneyRegister::SelectedTransaction& st, d->m_selectedTransactions) { switch (st.transaction().splitCount()) { case 0: break; case 1: singleSplitTransactions++; break; default: multipleSplitTransactions++; break; } } if (singleSplitTransactions > 0 && multipleSplitTransactions == 1) { aC->action(s_Actions[Action::TransactionCopySplits])->setEnabled(true); } } if (d->m_selectedTransactions.count() >= 2) { int singleSplitTransactions = 0; int multipleSplitTransactions = 0; foreach(const KMyMoneyRegister::SelectedTransaction& st, d->m_selectedTransactions) { switch(st.transaction().splitCount()) { case 0: break; case 1: singleSplitTransactions++; break; default: multipleSplitTransactions++; break; } } if(singleSplitTransactions > 0 && multipleSplitTransactions == 1) { aC->action(s_Actions[Action::TransactionCopySplits])->setEnabled(true); } } } else { aC->action(s_Actions[Action::TransactionAssignNumber])->setEnabled(d->m_transactionEditor->canAssignNumber()); aC->action(s_Actions[Action::TransactionNew])->setEnabled(false); aC->action(s_Actions[Action::TransactionDelete])->setEnabled(false); QString reason; aC->action(s_Actions[Action::TransactionEnter])->setEnabled(d->m_transactionEditor->isComplete(reason)); //FIXME: Port to KDE4 // the next line somehow worked in KDE3 but does not have // any influence under KDE4 /// Works for me when 'reason' is set. Allan aC->action(s_Actions[Action::TransactionEnter])->setToolTip(reason); aC->action(s_Actions[Action::TransactionCancel])->setEnabled(true); } } QList accList; file->accountList(accList); QList::const_iterator it_a; QMap::const_iterator it_p = d->m_onlinePlugins.constEnd(); for (it_a = accList.constBegin(); (it_p == d->m_onlinePlugins.constEnd()) && (it_a != accList.constEnd()); ++it_a) { if (!(*it_a).onlineBankingSettings().value("provider").isEmpty()) { // check if provider is available it_p = d->m_onlinePlugins.constFind((*it_a).onlineBankingSettings().value("provider")); if (it_p != d->m_onlinePlugins.constEnd()) { QStringList protocols; (*it_p)->protocols(protocols); if (protocols.count() > 0) { aC->action(s_Actions[Action::AccountUpdateAll])->setEnabled(true); aC->action(s_Actions[Action::AccountUpdateMenu])->setEnabled(true); } } } } QBitArray skip((int)eStorage::Reference::Count); if (!d->m_selectedAccount.id().isEmpty()) { if (!file->isStandardAccount(d->m_selectedAccount.id())) { switch (d->m_selectedAccount.accountGroup()) { case eMyMoney::Account::Asset: case eMyMoney::Account::Liability: case eMyMoney::Account::Equity: aC->action(s_Actions[Action::AccountTransactionReport])->setEnabled(true); aC->action(s_Actions[Action::AccountEdit])->setEnabled(true); aC->action(s_Actions[Action::AccountDelete])->setEnabled(!file->isReferenced(d->m_selectedAccount)); aC->action(s_Actions[Action::AccountOpen])->setEnabled(true); if (d->m_selectedAccount.accountGroup() != eMyMoney::Account::Equity) { if (d->m_reconciliationAccount.id().isEmpty()) { aC->action(s_Actions[Action::AccountStartReconciliation])->setEnabled(true); aC->action(s_Actions[Action::AccountStartReconciliation])->setToolTip(i18n("Reconcile")); } else { QString tip; tip = i18n("Reconcile - disabled because you are currently reconciling %1", d->m_reconciliationAccount.name()); aC->action(s_Actions[Action::AccountStartReconciliation])->setToolTip(tip); if (!d->m_transactionEditor) { aC->action(s_Actions[Action::AccountFinishReconciliation])->setEnabled(d->m_selectedAccount.id() == d->m_reconciliationAccount.id()); aC->action(s_Actions[Action::AccountPostponeReconciliation])->setEnabled(d->m_selectedAccount.id() == d->m_reconciliationAccount.id()); } } } if (d->m_selectedAccount.accountType() == eMyMoney::Account::Investment) aC->action(s_Actions[Action::InvestmentNew])->setEnabled(true); if (d->m_selectedAccount.isClosed()) aC->action(s_Actions[Action::AccountReopen])->setEnabled(true); else enableCloseAccountAction(d->m_selectedAccount); if (!d->m_selectedAccount.onlineBankingSettings().value("provider").isEmpty()) { aC->action(s_Actions[Action::AccountOnlineUnmap])->setEnabled(true); // check if provider is available QMap::const_iterator it_p; it_p = d->m_onlinePlugins.constFind(d->m_selectedAccount.onlineBankingSettings().value("provider")); if (it_p != d->m_onlinePlugins.constEnd()) { QStringList protocols; (*it_p)->protocols(protocols); if (protocols.count() > 0) { aC->action(s_Actions[Action::AccountUpdate])->setEnabled(true); aC->action(s_Actions[Action::AccountUpdateMenu])->setEnabled(true); } } } else { aC->action(s_Actions[Action::AccountOnlineMap])->setEnabled(d->m_onlinePlugins.count() > 0); } aC->action(s_Actions[Action::AccountBalanceChart])->setEnabled(true); break; case eMyMoney::Account::Income : case eMyMoney::Account::Expense : aC->action(s_Actions[Action::CategoryEdit])->setEnabled(true); // enable delete action, if category/account itself is not referenced // by any object except accounts, because we want to allow // deleting of sub-categories. Also, we allow transactions, schedules and budgets // to be present because we can re-assign them during the delete process skip.fill(false); skip.setBit((int)eStorage::Reference::Transaction); skip.setBit((int)eStorage::Reference::Account); skip.setBit((int)eStorage::Reference::Schedule); skip.setBit((int)eStorage::Reference::Budget); aC->action(s_Actions[Action::CategoryDelete])->setEnabled(!file->isReferenced(d->m_selectedAccount, skip)); aC->action(s_Actions[Action::AccountOpen])->setEnabled(true); break; default: break; } } } if (!d->m_selectedInstitution.id().isEmpty()) { aC->action(s_Actions[Action::InstitutionEdit])->setEnabled(true); aC->action(s_Actions[Action::InstitutionDelete])->setEnabled(!file->isReferenced(d->m_selectedInstitution)); } if (!d->m_selectedInvestment.id().isEmpty()) { aC->action(s_Actions[Action::InvestmentEdit])->setEnabled(true); aC->action(s_Actions[Action::InvestmentDelete])->setEnabled(!file->isReferenced(d->m_selectedInvestment)); aC->action(s_Actions[Action::InvestmentManualPrice])->setEnabled(true); try { MyMoneySecurity security = MyMoneyFile::instance()->security(d->m_selectedInvestment.currencyId()); if (!security.value("kmm-online-source").isEmpty()) aC->action(s_Actions[Action::InvestmentOnlinePrice])->setEnabled(true); } catch (const MyMoneyException &e) { qDebug("Error retrieving security for investment %s: %s", qPrintable(d->m_selectedInvestment.name()), qPrintable(e.what())); } if (d->m_selectedInvestment.isClosed()) aC->action(s_Actions[Action::AccountReopen])->setEnabled(true); else enableCloseAccountAction(d->m_selectedInvestment); } if (!d->m_selectedSchedule.id().isEmpty()) { aC->action(s_Actions[Action::ScheduleEdit])->setEnabled(true); aC->action(s_Actions[Action::ScheduleDuplicate])->setEnabled(true); aC->action(s_Actions[Action::ScheduleDelete])->setEnabled(!file->isReferenced(d->m_selectedSchedule)); if (!d->m_selectedSchedule.isFinished()) { aC->action(s_Actions[Action::ScheduleEnter])->setEnabled(true); // a schedule with a single occurrence cannot be skipped if (d->m_selectedSchedule.occurrence() != eMyMoney::Schedule::Occurrence::Once) { aC->action(s_Actions[Action::ScheduleSkip])->setEnabled(true); } } } if (d->m_selectedPayees.count() >= 1) { aC->action(s_Actions[Action::PayeeRename])->setEnabled(d->m_selectedPayees.count() == 1); aC->action(s_Actions[Action::PayeeMerge])->setEnabled(d->m_selectedPayees.count() > 1); aC->action(s_Actions[Action::PayeeDelete])->setEnabled(true); } if (d->m_selectedTags.count() >= 1) { aC->action(s_Actions[Action::TagRename])->setEnabled(d->m_selectedTags.count() == 1); aC->action(s_Actions[Action::TagDelete])->setEnabled(true); } aC->action(s_Actions[Action::BudgetNew])->setEnabled(true); if (d->m_selectedBudgets.count() >= 1) { aC->action(s_Actions[Action::BudgetDelete])->setEnabled(true); if (d->m_selectedBudgets.count() == 1) { aC->action(s_Actions[Action::BudgetChangeYear])->setEnabled(true); aC->action(s_Actions[Action::BudgetCopy])->setEnabled(true); aC->action(s_Actions[Action::BudgetRename])->setEnabled(true); aC->action(s_Actions[Action::BudgetForecast])->setEnabled(true); } } if (!d->m_selectedCurrency.id().isEmpty()) { aC->action(s_Actions[Action::CurrencyRename])->setEnabled(true); // no need to check each transaction. accounts are enough in this case skip.fill(false); skip.setBit((int)eStorage::Reference::Transaction); aC->action(s_Actions[Action::CurrencyDelete])->setEnabled(!file->isReferenced(d->m_selectedCurrency, skip)); if (d->m_selectedCurrency.id() != file->baseCurrency().id()) aC->action(s_Actions[Action::CurrencySetBase])->setEnabled(true); } if (!d->m_selectedPrice.from().isEmpty() && d->m_selectedPrice.source() != QLatin1String("KMyMoney")) { aC->action(s_Actions[Action::PriceEdit])->setEnabled(true); aC->action(s_Actions[Action::PriceDelete])->setEnabled(true); //enable online update if it is a currency MyMoneySecurity security = MyMoneyFile::instance()->security(d->m_selectedPrice.from()); aC->action(s_Actions[Action::PriceUpdate])->setEnabled(security.isCurrency()); } } void KMyMoneyApp::slotResetSelections() { slotSelectAccount(MyMoneyAccount()); slotSelectInstitution(MyMoneyInstitution()); slotSelectInvestment(MyMoneyAccount()); slotSelectSchedule(); slotSelectCurrency(); slotSelectPrice(); slotSelectPayees(QList()); slotSelectTags(QList()); slotSelectBudget(QList()); slotSelectTransactions(KMyMoneyRegister::SelectedTransactions()); slotUpdateActions(); } void KMyMoneyApp::slotSelectCurrency() { slotSelectCurrency(MyMoneySecurity()); } void KMyMoneyApp::slotSelectCurrency(const MyMoneySecurity& currency) { d->m_selectedCurrency = currency; slotUpdateActions(); emit currencySelected(d->m_selectedCurrency); } void KMyMoneyApp::slotSelectPrice() { slotSelectPrice(MyMoneyPrice()); } void KMyMoneyApp::slotSelectPrice(const MyMoneyPrice& price) { d->m_selectedPrice = price; slotUpdateActions(); emit priceSelected(d->m_selectedPrice); } void KMyMoneyApp::slotSelectBudget(const QList& list) { d->m_selectedBudgets = list; slotUpdateActions(); emit budgetSelected(d->m_selectedBudgets); } void KMyMoneyApp::slotSelectPayees(const QList& list) { d->m_selectedPayees = list; slotUpdateActions(); emit payeesSelected(d->m_selectedPayees); } void KMyMoneyApp::slotSelectTags(const QList& list) { d->m_selectedTags = list; slotUpdateActions(); emit tagsSelected(d->m_selectedTags); } void KMyMoneyApp::slotSelectTransactions(const KMyMoneyRegister::SelectedTransactions& list) { // list can either contain a list of transactions or a single selected scheduled transaction // in the latter case, the transaction id is actually the one of the schedule. In order // to differentiate between the two, we just ask for the schedule. If we don't find one - because // we passed the id of a real transaction - then we know that fact. We use the schedule here, // because the list of schedules is kept in a cache by MyMoneyFile. This way, we save some trips // to the backend which we would have to do if we check for the transaction. d->m_selectedTransactions.clear(); d->m_selectedSchedule = MyMoneySchedule(); d->m_accountGoto.clear(); d->m_payeeGoto.clear(); if (!list.isEmpty() && !list.first().isScheduled()) { d->m_selectedTransactions = list; if (list.count() == 1) { const MyMoneySplit& sp = d->m_selectedTransactions[0].split(); if (!sp.payeeId().isEmpty()) { try { MyMoneyPayee payee = MyMoneyFile::instance()->payee(sp.payeeId()); if (!payee.name().isEmpty()) { d->m_payeeGoto = payee.id(); QString name = payee.name(); name.replace(QRegExp("&(?!&)"), "&&"); actionCollection()->action(s_Actions[Action::TransactionGoToPayee])->setText(i18n("Go to '%1'", name)); } } catch (const MyMoneyException &) { } } try { QList::const_iterator it_s; const MyMoneyTransaction& t = d->m_selectedTransactions[0].transaction(); // search the first non-income/non-expense accunt and use it for the 'goto account' const MyMoneySplit& sp = d->m_selectedTransactions[0].split(); for (it_s = t.splits().begin(); it_s != t.splits().end(); ++it_s) { if ((*it_s).id() != sp.id()) { MyMoneyAccount acc = MyMoneyFile::instance()->account((*it_s).accountId()); if (!acc.isIncomeExpense()) { // for stock accounts we show the portfolio account if (acc.isInvest()) { acc = MyMoneyFile::instance()->account(acc.parentAccountId()); } d->m_accountGoto = acc.id(); QString name = acc.name(); name.replace(QRegExp("&(?!&)"), "&&"); actionCollection()->action(s_Actions[Action::TransactionGoToAccount])->setText(i18n("Go to '%1'", name)); break; } } } } catch (const MyMoneyException &) { } } slotUpdateActions(); emit transactionsSelected(d->m_selectedTransactions); } else if (!list.isEmpty()) { slotSelectSchedule(MyMoneyFile::instance()->schedule(list.first().scheduleId())); } else { slotUpdateActions(); } // make sure, we show some neutral menu entry if we don't have an object if (d->m_payeeGoto.isEmpty()) actionCollection()->action(s_Actions[Action::TransactionGoToPayee])->setText(i18n("Go to payee")); if (d->m_accountGoto.isEmpty()) actionCollection()->action(s_Actions[Action::TransactionGoToAccount])->setText(i18n("Go to account")); } void KMyMoneyApp::slotSelectInstitution(const MyMoneyObject& institution) { if (typeid(institution) != typeid(MyMoneyInstitution)) return; d->m_selectedInstitution = dynamic_cast(institution); // qDebug("slotSelectInstitution('%s')", d->m_selectedInstitution.name().data()); slotUpdateActions(); emit institutionSelected(d->m_selectedInstitution); } void KMyMoneyApp::slotSelectAccount(const MyMoneyObject& obj) { if (typeid(obj) != typeid(MyMoneyAccount)) return; d->m_selectedAccount = MyMoneyAccount(); const MyMoneyAccount& acc = dynamic_cast(obj); if (!acc.isInvest()) d->m_selectedAccount = acc; // qDebug("slotSelectAccount('%s')", d->m_selectedAccount.name().data()); slotUpdateActions(); emit accountSelected(d->m_selectedAccount); } void KMyMoneyApp::slotSelectInvestment(const MyMoneyObject& obj) { if (typeid(obj) != typeid(MyMoneyAccount)) return; // qDebug("slotSelectInvestment('%s')", account.name().data()); d->m_selectedInvestment = MyMoneyAccount(); const MyMoneyAccount& acc = dynamic_cast(obj); if (acc.isInvest()) d->m_selectedInvestment = acc; slotUpdateActions(); emit investmentSelected(d->m_selectedInvestment); } void KMyMoneyApp::slotSelectSchedule() { slotSelectSchedule(MyMoneySchedule()); } void KMyMoneyApp::slotSelectSchedule(const MyMoneySchedule& schedule) { // qDebug("slotSelectSchedule('%s')", schedule.name().data()); d->m_selectedSchedule = schedule; slotUpdateActions(); emit scheduleSelected(d->m_selectedSchedule); } void KMyMoneyApp::slotDataChanged() { // As this method is called every time the MyMoneyFile instance // notifies a modification, it's the perfect place to start the timer if needed if (d->m_autoSaveEnabled && !d->m_autoSaveTimer->isActive()) { d->m_autoSaveTimer->setSingleShot(true); d->m_autoSaveTimer->start(d->m_autoSavePeriod * 60 * 1000); //miliseconds } updateCaption(); } void KMyMoneyApp::slotCurrencyDialog() { QPointer dlg = new KCurrencyEditDlg(this); connect(dlg, SIGNAL(selectObject(MyMoneySecurity)), this, SLOT(slotSelectCurrency(MyMoneySecurity))); connect(dlg, SIGNAL(openContextMenu(MyMoneySecurity)), this, SLOT(slotShowCurrencyContextMenu())); connect(this, SIGNAL(currencyRename()), dlg, SLOT(slotStartRename())); connect(dlg, SIGNAL(updateCurrency(QString,QString,QString)), this, SLOT(slotCurrencyUpdate(QString,QString,QString))); connect(this, SIGNAL(currencyCreated(QString)), dlg, SLOT(slotSelectCurrency(QString))); connect(dlg, SIGNAL(selectBaseCurrency(MyMoneySecurity)), this, SLOT(slotCurrencySetBase())); dlg->exec(); delete dlg; slotSelectCurrency(MyMoneySecurity()); } void KMyMoneyApp::slotPriceDialog() { QPointer dlg = new KMyMoneyPriceDlg(this); connect(dlg, SIGNAL(selectObject(MyMoneyPrice)), this, SLOT(slotSelectPrice(MyMoneyPrice))); connect(dlg, SIGNAL(openContextMenu(MyMoneyPrice)), this, SLOT(slotShowPriceContextMenu())); connect(this, SIGNAL(priceNew()), dlg, SLOT(slotNewPrice())); connect(this, SIGNAL(priceEdit()), dlg, SLOT(slotEditPrice())); connect(this, SIGNAL(priceDelete()), dlg, SLOT(slotDeletePrice())); connect(this, SIGNAL(priceOnlineUpdate()), dlg, SLOT(slotOnlinePriceUpdate())); dlg->exec(); } void KMyMoneyApp::slotFileConsistencyCheck() { d->consistencyCheck(true); updateCaption(); } void KMyMoneyApp::Private::consistencyCheck(bool alwaysDisplayResult) { KMSTATUS(i18n("Running consistency check...")); MyMoneyFileTransaction ft; try { m_consistencyCheckResult = MyMoneyFile::instance()->consistencyCheck(); ft.commit(); } catch (const MyMoneyException &e) { m_consistencyCheckResult.append(i18n("Consistency check failed: %1", e.what())); // always display the result if the check failed alwaysDisplayResult = true; } // in case the consistency check was OK, we get a single line as result // in all errneous cases, we get more than one line and force the // display of them. if (alwaysDisplayResult || m_consistencyCheckResult.size() > 1) { QString msg = i18n("The consistency check has found no issues in your data. Details are presented below."); if (m_consistencyCheckResult.size() > 1) msg = i18n("The consistency check has found some issues in your data. Details are presented below. Those issues that could not be corrected automatically need to be solved by the user."); // install a context menu for the list after the dialog is displayed QTimer::singleShot(500, q, SLOT(slotInstallConsistencyCheckContextMenu())); KMessageBox::informationList(0, msg, m_consistencyCheckResult, i18n("Consistency check result")); } // this data is no longer needed m_consistencyCheckResult.clear(); } void KMyMoneyApp::Private::copyConsistencyCheckResults() { QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(m_consistencyCheckResult.join(QLatin1String("\n"))); } void KMyMoneyApp::Private::saveConsistencyCheckResults() { QUrl fileUrl = QFileDialog::getSaveFileUrl(q); if (!fileUrl.isEmpty()) { QFile file(fileUrl.toLocalFile()); if (file.open(QFile::WriteOnly | QFile::Append | QFile::Text)) { QTextStream out(&file); out << m_consistencyCheckResult.join(QLatin1String("\n")); file.close(); } } } void KMyMoneyApp::Private::setThemedCSS() { const QStringList CSSnames {QStringLiteral("kmymoney.css"), QStringLiteral("welcome.css")}; const QString rcDir("/html/"); const QStringList defaultCSSDirs = QStandardPaths::locateAll(QStandardPaths::AppDataLocation, rcDir, QStandardPaths::LocateDirectory); // scan the list of directories to find the ones that really // contains all files we look for QString defaultCSSDir; foreach (const auto dir, defaultCSSDirs) { defaultCSSDir = dir; foreach (const auto CSSname, CSSnames) { QFileInfo fileInfo(defaultCSSDir + CSSname); if (!fileInfo.exists()) { defaultCSSDir.clear(); break; } } if (!defaultCSSDir.isEmpty()) { break; } } // make sure we have the local directory where the themed version is stored const QString themedCSSDir = QStandardPaths::standardLocations(QStandardPaths::AppConfigLocation).first() + rcDir; QDir().mkpath(themedCSSDir); foreach (const auto CSSname, CSSnames) { const QString defaultCSSFilename = defaultCSSDir + CSSname; QFileInfo fileInfo(defaultCSSFilename); if (fileInfo.exists()) { const QString themedCSSFilename = themedCSSDir + CSSname; QFile::remove(themedCSSFilename); if (QFile::copy(defaultCSSFilename, themedCSSFilename)) { QFile cssFile (themedCSSFilename); if (cssFile.open(QIODevice::ReadWrite)) { QTextStream cssStream(&cssFile); auto cssText = cssStream.readAll(); cssText.replace(QLatin1String("./"), defaultCSSDir, Qt::CaseSensitive); cssText.replace(QLatin1String("WindowText"), KMyMoneyGlobalSettings::schemeColor(SchemeColor::WindowText).name(), Qt::CaseSensitive); cssText.replace(QLatin1String("Window"), KMyMoneyGlobalSettings::schemeColor(SchemeColor::WindowBackground).name(), Qt::CaseSensitive); cssText.replace(QLatin1String("HighlightText"), KMyMoneyGlobalSettings::schemeColor(SchemeColor::ListHighlightText).name(), Qt::CaseSensitive); cssText.replace(QLatin1String("Highlight"), KMyMoneyGlobalSettings::schemeColor(SchemeColor::ListHighlight).name(), Qt::CaseSensitive); cssText.replace(QLatin1String("black"), KMyMoneyGlobalSettings::schemeColor(SchemeColor::ListGrid).name(), Qt::CaseSensitive); cssStream.seek(0); cssStream << cssText; cssFile.close(); } } } } } void KMyMoneyApp::slotCheckSchedules() { if (KMyMoneyGlobalSettings::checkSchedule() == true) { KMSTATUS(i18n("Checking for overdue scheduled transactions...")); MyMoneyFile *file = MyMoneyFile::instance(); QDate checkDate = QDate::currentDate().addDays(KMyMoneyGlobalSettings::checkSchedulePreview()); QList scheduleList = file->scheduleList(); QList::Iterator it; eDialogs::ScheduleResultCode rc = eDialogs::ScheduleResultCode::Enter; for (it = scheduleList.begin(); (it != scheduleList.end()) && (rc != eDialogs::ScheduleResultCode::Cancel); ++it) { // Get the copy in the file because it might be modified by commitTransaction MyMoneySchedule schedule = file->schedule((*it).id()); if (schedule.autoEnter()) { try { while (!schedule.isFinished() && (schedule.adjustedNextDueDate() <= checkDate) && rc != eDialogs::ScheduleResultCode::Ignore && rc != eDialogs::ScheduleResultCode::Cancel) { rc = enterSchedule(schedule, true, true); schedule = file->schedule((*it).id()); // get a copy of the modified schedule } } catch (const MyMoneyException &) { } } if (rc == eDialogs::ScheduleResultCode::Ignore) { // if the current schedule was ignored then we must make sure that the user can still enter the next scheduled transaction rc = eDialogs::ScheduleResultCode::Enter; } } updateCaption(); } } void KMyMoneyApp::writeLastUsedDir(const QString& directory) { //get global config object for our app. KSharedConfigPtr kconfig = KSharedConfig::openConfig(); if (kconfig) { KConfigGroup grp = kconfig->group("General Options"); //write path entry, no error handling since its void. grp.writeEntry("LastUsedDirectory", directory); } } void KMyMoneyApp::writeLastUsedFile(const QString& fileName) { //get global config object for our app. KSharedConfigPtr kconfig = KSharedConfig::openConfig(); if (kconfig) { KConfigGroup grp = d->m_config->group("General Options"); // write path entry, no error handling since its void. // use a standard string, as fileName could contain a protocol // e.g. file:/home/thb/.... grp.writeEntry("LastUsedFile", fileName); } } QString KMyMoneyApp::readLastUsedDir() const { QString str; //get global config object for our app. KSharedConfigPtr kconfig = KSharedConfig::openConfig(); if (kconfig) { KConfigGroup grp = d->m_config->group("General Options"); //read path entry. Second parameter is the default if the setting is not found, which will be the default document path. str = grp.readEntry("LastUsedDirectory", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); // if the path stored is empty, we use the default nevertheless if (str.isEmpty()) str = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); } return str; } QString KMyMoneyApp::readLastUsedFile() const { QString str; // get global config object for our app. KSharedConfigPtr kconfig = KSharedConfig::openConfig(); if (kconfig) { KConfigGroup grp = d->m_config->group("General Options"); // read filename entry. str = grp.readEntry("LastUsedFile", ""); } return str; } QString KMyMoneyApp::filename() const { return d->m_fileName.url(); } WebConnect* KMyMoneyApp::webConnect() const { return d->m_webConnect; } QList KMyMoneyApp::instanceList() const { QList list; #ifdef KMM_DBUS QDBusReply reply = QDBusConnection::sessionBus().interface()->registeredServiceNames(); if (reply.isValid()) { QStringList apps = reply.value(); QStringList::ConstIterator it; // build a list of service names of all running kmymoney applications without this one for (it = apps.constBegin(); it != apps.constEnd(); ++it) { // please change this method of creating a list of 'all the other kmymoney instances that are running on the system' // since assuming that D-Bus creates service names with org.kde.kmymoney-PID is an observation I don't think that it's documented somwhere if ((*it).indexOf("org.kde.kmymoney-") == 0) { uint thisProcPid = platformTools::processId(); if ((*it).indexOf(QString("org.kde.kmymoney-%1").arg(thisProcPid)) != 0) list += (*it); } } } else { qDebug("D-Bus returned the following error while obtaining instances: %s", qPrintable(reply.error().message())); } #endif return list; } void KMyMoneyApp::slotEquityPriceUpdate() { QPointer dlg = new KEquityPriceUpdateDlg(this); if (dlg->exec() == QDialog::Accepted && dlg != 0) dlg->storePrices(); delete dlg; } void KMyMoneyApp::webConnect(const QString& sourceUrl, const QByteArray& asn_id) { // // Web connect attempts to go through the known importers and see if the file // can be importing using that method. If so, it will import it using that // plugin // Q_UNUSED(asn_id) d->m_importUrlsQueue.enqueue(sourceUrl); // only start processing if this is the only import so far if (d->m_importUrlsQueue.count() == 1) { while (!d->m_importUrlsQueue.isEmpty()) { // get the value of the next item from the queue // but leave it on the queue for now QString url = d->m_importUrlsQueue.head(); // Bring this window to the forefront. This method was suggested by // Lubos Lunak of the KDE core development team. // TODO: port KF5 (WebConnect) //KStartupInfo::setNewStartupId(this, asn_id); // Make sure we have an open file if (! d->m_myMoneyView->fileOpen() && KMessageBox::warningContinueCancel(kmymoney, i18n("You must first select a KMyMoney file before you can import a statement.")) == KMessageBox::Continue) kmymoney->slotFileOpen(); // only continue if the user really did open a file. if (d->m_myMoneyView->fileOpen()) { KMSTATUS(i18n("Importing a statement via Web Connect")); // remove the statement files d->unlinkStatementXML(); QMap::const_iterator it_plugin = d->m_importerPlugins.constBegin(); while (it_plugin != d->m_importerPlugins.constEnd()) { if ((*it_plugin)->isMyFormat(url)) { QList statements; if (!(*it_plugin)->import(url)) { KMessageBox::error(this, i18n("Unable to import %1 using %2 plugin. The plugin returned the following error: %3", url, (*it_plugin)->formatName(), (*it_plugin)->lastError()), i18n("Importing error")); } break; } ++it_plugin; } // If we did not find a match, try importing it as a KMM statement file, // which is really just for testing. the statement file is not exposed // to users. if (it_plugin == d->m_importerPlugins.constEnd()) if (MyMoneyStatement::isStatementFile(url)) slotStatementImport(url); } // remove the current processed item from the queue d->m_importUrlsQueue.dequeue(); } } } void KMyMoneyApp::slotEnableMessages() { KMessageBox::enableAllMessages(); KMessageBox::information(this, i18n("All messages have been enabled."), i18n("All messages")); } void KMyMoneyApp::createInterfaces() { // Sets up the plugin interface KMyMoneyPlugin::pluginInterfaces().importInterface = new KMyMoneyPlugin::KMMImportInterface(this, this); KMyMoneyPlugin::pluginInterfaces().statementInterface = new KMyMoneyPlugin::KMMStatementInterface(this, this); KMyMoneyPlugin::pluginInterfaces().viewInterface = new KMyMoneyPlugin::KMMViewInterface(this, d->m_myMoneyView, this); // setup the calendar interface for schedules MyMoneySchedule::setProcessingCalendar(this); } void KMyMoneyApp::loadPlugins() { Q_ASSERT(!d->m_pluginLoader); d->m_pluginLoader = new KMyMoneyPlugin::PluginLoader(this); //! @todo Junior Job: Improve the config read system KSharedConfigPtr config = KSharedConfig::openConfig(); KConfigGroup group{ config->group("Plugins") }; const auto plugins = KPluginLoader::findPlugins("kmymoney"); d->m_pluginLoader->addPluginInfo(plugins); for (const KPluginMetaData & pluginData : plugins) { // Only load plugins which are enabled and have the right serviceType. Other serviceTypes are loaded on demand. if (isPluginEnabled(pluginData, group)) slotPluginLoad(pluginData); } connect(d->m_pluginLoader, &KMyMoneyPlugin::PluginLoader::pluginEnabled, this, &KMyMoneyApp::slotPluginLoad); connect(d->m_pluginLoader, &KMyMoneyPlugin::PluginLoader::pluginDisabled, this, &KMyMoneyApp::slotPluginUnload); } void KMyMoneyApp::unloadPlugins() { Q_ASSERT(d->m_pluginLoader); delete d->m_pluginLoader; } inline bool KMyMoneyApp::isPluginEnabled(const KPluginMetaData& metaData, const KConfigGroup& configGroup) { //! @fixme: there is a function in KMyMoneyPlugin::PluginLoader which has to have the same content if (metaData.serviceTypes().contains("KMyMoney/Plugin")) { const QString keyName{metaData.name() + "Enabled"}; if (configGroup.hasKey(keyName)) return configGroup.readEntry(keyName, true); return metaData.isEnabledByDefault(); } return false; } void KMyMoneyApp::slotPluginLoad(const KPluginMetaData& metaData) { std::unique_ptr loader{new QPluginLoader{metaData.fileName()}}; QObject* plugin = loader->instance(); if (!plugin) { qWarning("Could not load plugin '%s', error: %s", qPrintable(metaData.fileName()), qPrintable(loader->errorString())); return; } if ( d->m_plugins.contains(metaData.fileName()) ) { /** @fixme Handle a reload e.g. objectNames are equal but the object are different (plugin != d->m_plugins[plugin->objectName()]) * Also it could be usefull to drop the dependence on objectName() */ /* Note: there is nothing to delete here because if the plugin was loaded already, plugin points to the same object as the previously loaded one. */ return; } KMyMoneyPlugin::Plugin* kmmPlugin = qobject_cast(plugin); if (!kmmPlugin) { qWarning("Could not load plugin '%s'.", qPrintable(metaData.fileName())); return; } // check for online plugin KMyMoneyPlugin::OnlinePlugin* op = dynamic_cast(plugin); // check for extended online plugin KMyMoneyPlugin::OnlinePluginExtended* ope = dynamic_cast(plugin); // check for importer plugin KMyMoneyPlugin::ImporterPlugin* ip = dynamic_cast(plugin); // Tell the plugin it is about to get plugged kmmPlugin->plug(); // plug the plugin guiFactory()->addClient(kmmPlugin); d->m_plugins[metaData.fileName()] = kmmPlugin; if (op) d->m_onlinePlugins[plugin->objectName()] = op; if (ope) onlineJobAdministration::instance()->addPlugin(plugin->objectName(), ope); if (ip) d->m_importerPlugins[plugin->objectName()] = ip; slotUpdateActions(); } void KMyMoneyApp::slotPluginUnload(const KPluginMetaData& metaData) { KMyMoneyPlugin::Plugin* plugin = d->m_plugins[metaData.fileName()]; // Remove and test if the plugin was actually loaded if (!d->m_plugins.remove(metaData.fileName()) || plugin == nullptr) return; // check for online plugin KMyMoneyPlugin::OnlinePlugin* op = dynamic_cast(plugin); // check for importer plugin KMyMoneyPlugin::ImporterPlugin* ip = dynamic_cast(plugin); // unplug the plugin guiFactory()->removeClient(plugin); if (op) d->m_onlinePlugins.remove(plugin->objectName()); if (ip) d->m_importerPlugins.remove(plugin->objectName()); plugin->unplug(); slotUpdateActions(); } void KMyMoneyApp::slotAutoSave() { if (!d->m_inAutoSaving) { // store the focus widget so we can restore it after save QPointer focusWidget = qApp->focusWidget(); d->m_inAutoSaving = true; KMSTATUS(i18n("Auto saving...")); //calls slotFileSave if needed, and restart the timer //it the file is not saved, reinitializes the countdown. if (d->m_myMoneyView->dirty() && d->m_autoSaveEnabled) { if (!slotFileSave() && d->m_autoSavePeriod > 0) { d->m_autoSaveTimer->setSingleShot(true); d->m_autoSaveTimer->start(d->m_autoSavePeriod * 60 * 1000); } } d->m_inAutoSaving = false; if (focusWidget && focusWidget != qApp->focusWidget()) { // we have a valid focus widget so restore it focusWidget->setFocus(); } } } void KMyMoneyApp::slotDateChanged() { QDateTime dt = QDateTime::currentDateTime(); QDateTime nextDay(QDate(dt.date().addDays(1)), QTime(0, 0, 0)); // +1 is to make sure that we're already in the next day when the // signal is sent (this way we also avoid setting the timer to 0) QTimer::singleShot((dt.secsTo(nextDay) + 1)*1000, this, SLOT(slotDateChanged())); d->m_myMoneyView->slotRefreshViews(); } const MyMoneyAccount& KMyMoneyApp::account(const QString& key, const QString& value) const { QList list; QList::const_iterator it_a; MyMoneyFile::instance()->accountList(list); QString accId; for (it_a = list.constBegin(); it_a != list.constEnd(); ++it_a) { // search in the account's kvp container const QString& accountKvpValue = (*it_a).value(key); // search in the account's online settings kvp container const QString& onlineSettingsKvpValue = (*it_a).onlineBankingSettings().value(key); if (accountKvpValue.contains(value) || onlineSettingsKvpValue.contains(value)) { if(accId.isEmpty()) { accId = (*it_a).id(); } } if (accountKvpValue == value || onlineSettingsKvpValue == value) { accId = (*it_a).id(); break; } } // return the account found or an empty element return MyMoneyFile::instance()->account(accId); } void KMyMoneyApp::setAccountOnlineParameters(const MyMoneyAccount& _acc, const MyMoneyKeyValueContainer& kvps) { MyMoneyFileTransaction ft; try { MyMoneyAccount acc = MyMoneyFile::instance()->account(_acc.id()); acc.setOnlineBankingSettings(kvps); MyMoneyFile::instance()->modifyAccount(acc); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Unable to setup online parameters for account '%1'", _acc.name()), e.what()); } } void KMyMoneyApp::slotAccountUnmapOnline() { // no account selected if (d->m_selectedAccount.id().isEmpty()) return; // not a mapped account if (d->m_selectedAccount.onlineBankingSettings().value("provider").isEmpty()) return; if (KMessageBox::warningYesNo(this, QString("%1").arg(i18n("Do you really want to remove the mapping of account %1 to an online account? Depending on the details of the online banking method used, this action cannot be reverted.", d->m_selectedAccount.name())), i18n("Remove mapping to online account")) == KMessageBox::Yes) { MyMoneyFileTransaction ft; try { d->m_selectedAccount.setOnlineBankingSettings(MyMoneyKeyValueContainer()); // delete the kvp that is used in MyMoneyStatementReader too // we should really get rid of it, but since I don't know what it // is good for, I'll keep it around. (ipwizard) d->m_selectedAccount.deletePair("StatementKey"); MyMoneyFile::instance()->modifyAccount(d->m_selectedAccount); ft.commit(); // The mapping could disable the online task system onlineJobAdministration::instance()->updateOnlineTaskProperties(); } catch (const MyMoneyException &e) { KMessageBox::error(this, i18n("Unable to unmap account from online account: %1", e.what())); } } } void KMyMoneyApp::slotAccountMapOnline() { // no account selected if (d->m_selectedAccount.id().isEmpty()) return; // already an account mapped if (!d->m_selectedAccount.onlineBankingSettings().value("provider").isEmpty()) return; // check if user tries to map a brokerageAccount if (d->m_selectedAccount.name().contains(i18n(" (Brokerage)"))) { if (KMessageBox::warningContinueCancel(this, i18n("You try to map a brokerage account to an online account. This is usually not advisable. In general, the investment account should be mapped to the online account. Please cancel if you intended to map the investment account, continue otherwise"), i18n("Mapping brokerage account")) == KMessageBox::Cancel) { return; } } // if we have more than one provider let the user select the current provider QString provider; QMap::const_iterator it_p; switch (d->m_onlinePlugins.count()) { case 0: break; case 1: provider = d->m_onlinePlugins.begin().key(); break; default: { QMenu popup(this); popup.setTitle(i18n("Select online banking plugin")); // Populate the pick list with all the provider for (it_p = d->m_onlinePlugins.constBegin(); it_p != d->m_onlinePlugins.constEnd(); ++it_p) { popup.addAction(it_p.key())->setData(it_p.key()); } QAction *item = popup.actions()[0]; if (item) { popup.setActiveAction(item); } // cancelled if ((item = popup.exec(QCursor::pos(), item)) == 0) { return; } provider = item->data().toString(); } break; } if (provider.isEmpty()) return; // find the provider it_p = d->m_onlinePlugins.constFind(provider); if (it_p != d->m_onlinePlugins.constEnd()) { // plugin found, call it MyMoneyKeyValueContainer settings; if ((*it_p)->mapAccount(d->m_selectedAccount, settings)) { settings["provider"] = provider; MyMoneyAccount acc(d->m_selectedAccount); acc.setOnlineBankingSettings(settings); MyMoneyFileTransaction ft; try { MyMoneyFile::instance()->modifyAccount(acc); ft.commit(); // The mapping could enable the online task system onlineJobAdministration::instance()->updateOnlineTaskProperties(); } catch (const MyMoneyException &e) { KMessageBox::error(this, i18n("Unable to map account to online account: %1", e.what())); } } } } void KMyMoneyApp::slotAccountUpdateOnlineAll() { QList accList; MyMoneyFile::instance()->accountList(accList); QList::iterator it_a; QMap::const_iterator it_p; d->m_statementResults.clear(); d->m_collectingStatements = true; // remove all those from the list, that don't have a 'provider' or the // provider is not currently present for (it_a = accList.begin(); it_a != accList.end();) { if ((*it_a).onlineBankingSettings().value("provider").isEmpty() || d->m_onlinePlugins.find((*it_a).onlineBankingSettings().value("provider")) == d->m_onlinePlugins.end()) { it_a = accList.erase(it_a); } else ++it_a; } QVector disabledActions {Action::AccountUpdate, Action::AccountUpdateMenu, Action::AccountUpdateAll}; foreach (const auto a, disabledActions) actionCollection()->action(s_Actions.value(a))->setEnabled(false); // now work on the remaining list of accounts int cnt = accList.count() - 1; for (it_a = accList.begin(); it_a != accList.end(); ++it_a) { it_p = d->m_onlinePlugins.constFind((*it_a).onlineBankingSettings().value("provider")); (*it_p)->updateAccount(*it_a, cnt != 0); --cnt; } d->m_collectingStatements = false; if (!d->m_statementResults.isEmpty()) KMessageBox::informationList(this, i18n("The statements have been processed with the following results:"), d->m_statementResults, i18n("Statement stats")); // re-enable the disabled actions slotUpdateActions(); } void KMyMoneyApp::slotAccountUpdateOnline() { // no account selected if (d->m_selectedAccount.id().isEmpty()) return; // no online account mapped if (d->m_selectedAccount.onlineBankingSettings().value("provider").isEmpty()) return; QVector disabledActions {Action::AccountUpdate, Action::AccountUpdateMenu, Action::AccountUpdateAll}; foreach (const auto a, disabledActions) actionCollection()->action(s_Actions.value(a))->setEnabled(false); // find the provider QMap::const_iterator it_p; it_p = d->m_onlinePlugins.constFind(d->m_selectedAccount.onlineBankingSettings().value("provider")); if (it_p != d->m_onlinePlugins.constEnd()) { // plugin found, call it d->m_collectingStatements = true; d->m_statementResults.clear(); (*it_p)->updateAccount(d->m_selectedAccount); d->m_collectingStatements = false; if (!d->m_statementResults.isEmpty()) KMessageBox::informationList(this, i18n("The statements have been processed with the following results:"), d->m_statementResults, i18n("Statement stats")); } // re-enable the disabled actions slotUpdateActions(); } void KMyMoneyApp::slotNewOnlineTransfer() { kOnlineTransferForm *transferForm = new kOnlineTransferForm(this); if (!d->m_selectedAccount.id().isEmpty()) { transferForm->setCurrentAccount(d->m_selectedAccount.id()); } connect(transferForm, SIGNAL(rejected()), transferForm, SLOT(deleteLater())); connect(transferForm, SIGNAL(acceptedForSave(onlineJob)), this, SLOT(slotOnlineJobSave(onlineJob))); connect(transferForm, SIGNAL(acceptedForSend(onlineJob)), this, SLOT(slotOnlineJobSend(onlineJob))); connect(transferForm, SIGNAL(accepted()), transferForm, SLOT(deleteLater())); transferForm->show(); } void KMyMoneyApp::slotEditOnlineJob(const QString jobId) { try { const onlineJob constJob = MyMoneyFile::instance()->getOnlineJob(jobId); slotEditOnlineJob(constJob); } catch (MyMoneyException&) { // Prevent a crash in very rare cases } } void KMyMoneyApp::slotEditOnlineJob(onlineJob job) { try { slotEditOnlineJob(onlineJobTyped(job)); } catch (MyMoneyException&) { } } void KMyMoneyApp::slotEditOnlineJob(const onlineJobTyped job) { kOnlineTransferForm *transferForm = new kOnlineTransferForm(this); transferForm->setOnlineJob(job); connect(transferForm, SIGNAL(rejected()), transferForm, SLOT(deleteLater())); connect(transferForm, SIGNAL(acceptedForSave(onlineJob)), this, SLOT(slotOnlineJobSave(onlineJob))); connect(transferForm, SIGNAL(acceptedForSend(onlineJob)), this, SLOT(slotOnlineJobSend(onlineJob))); connect(transferForm, SIGNAL(accepted()), transferForm, SLOT(deleteLater())); transferForm->show(); } void KMyMoneyApp::slotOnlineJobSave(onlineJob job) { MyMoneyFileTransaction fileTransaction; if (job.id() == MyMoneyObject::emptyId()) MyMoneyFile::instance()->addOnlineJob(job); else MyMoneyFile::instance()->modifyOnlineJob(job); fileTransaction.commit(); } /** @todo when onlineJob queue is used, continue here */ void KMyMoneyApp::slotOnlineJobSend(onlineJob job) { MyMoneyFileTransaction fileTransaction; if (job.id() == MyMoneyObject::emptyId()) MyMoneyFile::instance()->addOnlineJob(job); else MyMoneyFile::instance()->modifyOnlineJob(job); fileTransaction.commit(); QList jobList; jobList.append(job); slotOnlineJobSend(jobList); } void KMyMoneyApp::slotOnlineJobSend(QList jobs) { MyMoneyFile *const kmmFile = MyMoneyFile::instance(); QMultiMap jobsByPlugin; // Sort jobs by online plugin & lock them foreach (onlineJob job, jobs) { Q_ASSERT(job.id() != MyMoneyObject::emptyId()); // find the provider const MyMoneyAccount originAcc = job.responsibleMyMoneyAccount(); job.setLock(); job.addJobMessage(onlineJobMessage(onlineJobMessage::debug, "KMyMoneyApp::slotOnlineJobSend", "Added to queue for plugin '" + originAcc.onlineBankingSettings().value("provider") + '\'')); MyMoneyFileTransaction fileTransaction; kmmFile->modifyOnlineJob(job); fileTransaction.commit(); jobsByPlugin.insert(originAcc.onlineBankingSettings().value("provider"), job); } // Send onlineJobs to plugins QList usedPlugins = jobsByPlugin.keys(); std::sort(usedPlugins.begin(), usedPlugins.end()); const QList::iterator newEnd = std::unique(usedPlugins.begin(), usedPlugins.end()); usedPlugins.erase(newEnd, usedPlugins.end()); foreach (const QString& pluginKey, usedPlugins) { QMap::const_iterator it_p = d->m_onlinePlugins.constFind(pluginKey); if (it_p != d->m_onlinePlugins.constEnd()) { // plugin found, call it KMyMoneyPlugin::OnlinePluginExtended *pluginExt = dynamic_cast< KMyMoneyPlugin::OnlinePluginExtended* >(*it_p); if (pluginExt == 0) { qWarning("Job given for plugin which is not an extended plugin"); continue; } //! @fixme remove debug message qDebug() << "Sending " << jobsByPlugin.count(pluginKey) << " job(s) to online plugin " << pluginKey; QList jobsToExecute = jobsByPlugin.values(pluginKey); QList executedJobs = jobsToExecute; pluginExt->sendOnlineJob(executedJobs); // Save possible changes of the online job and remove lock MyMoneyFileTransaction fileTransaction; foreach (onlineJob job, executedJobs) { fileTransaction.restart(); job.setLock(false); kmmFile->modifyOnlineJob(job); fileTransaction.commit(); } if (Q_UNLIKELY(executedJobs.size() != jobsToExecute.size())) { // OnlinePlugin did not return all jobs qWarning() << "Error saving send online tasks. After restart you should see at minimum all successfully executed jobs marked send. Imperfect plugin: " << pluginExt->objectName(); } } else { qWarning() << "Error, got onlineJob for an account without online plugin."; /** @FIXME can this actually happen? */ } } } void KMyMoneyApp::slotRemoveJob() { } void KMyMoneyApp::slotEditJob() { } void KMyMoneyApp::slotOnlineJobLog() { QStringList jobIds = d->m_myMoneyView->getOnlineJobOutbox()->selectedOnlineJobs(); slotOnlineJobLog(jobIds); } void KMyMoneyApp::slotOnlineJobLog(const QStringList& onlineJobIds) { onlineJobMessagesView *const dialog = new onlineJobMessagesView(); onlineJobMessagesModel *const model = new onlineJobMessagesModel(dialog); model->setOnlineJob(MyMoneyFile::instance()->getOnlineJob(onlineJobIds.first())); dialog->setModel(model); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); // Note: Objects are not deleted here, Qt's parent-child system has to do that. } void KMyMoneyApp::setHolidayRegion(const QString& holidayRegion) { #ifdef KF5Holidays_FOUND //since the cost of updating the cache is now not negligible //check whether the region has been modified if (!d->m_holidayRegion || d->m_holidayRegion->regionCode() != holidayRegion) { // Delete the previous holidayRegion before creating a new one. delete d->m_holidayRegion; // Create a new holidayRegion. d->m_holidayRegion = new KHolidays::HolidayRegion(holidayRegion); //clear and update the holiday cache preloadHolidays(); } #else Q_UNUSED(holidayRegion); #endif } bool KMyMoneyApp::isProcessingDate(const QDate& date) const { #ifdef KF5Holidays_FOUND if (!d->m_processingDays.testBit(date.dayOfWeek())) return false; if (!d->m_holidayRegion || !d->m_holidayRegion->isValid()) return true; //check first whether it's already in cache if (d->m_holidayMap.contains(date)) { return d->m_holidayMap.value(date, true); } else { bool processingDay = !d->m_holidayRegion->isHoliday(date); d->m_holidayMap.insert(date, processingDay); return processingDay; } #else Q_UNUSED(date); return true; #endif } void KMyMoneyApp::preloadHolidays() { #ifdef KF5Holidays_FOUND //clear the cache before loading d->m_holidayMap.clear(); //only do this if it is a valid region if (d->m_holidayRegion && d->m_holidayRegion->isValid()) { //load holidays for the forecast days plus 1 cycle, to be on the safe side int forecastDays = KMyMoneyGlobalSettings::forecastDays() + KMyMoneyGlobalSettings::forecastAccountCycle(); QDate endDate = QDate::currentDate().addDays(forecastDays); //look for holidays for the next 2 years as a minimum. That should give a good margin for the cache if (endDate < QDate::currentDate().addYears(2)) endDate = QDate::currentDate().addYears(2); KHolidays::Holiday::List holidayList = d->m_holidayRegion->holidays(QDate::currentDate(), endDate); KHolidays::Holiday::List::const_iterator holiday_it; for (holiday_it = holidayList.constBegin(); holiday_it != holidayList.constEnd(); ++holiday_it) { for (QDate holidayDate = (*holiday_it).observedStartDate(); holidayDate <= (*holiday_it).observedEndDate(); holidayDate = holidayDate.addDays(1)) d->m_holidayMap.insert(holidayDate, false); } for (QDate date = QDate::currentDate(); date <= endDate; date = date.addDays(1)) { //if it is not a processing day, set it to false if (!d->m_processingDays.testBit(date.dayOfWeek())) { d->m_holidayMap.insert(date, false); } else if (!d->m_holidayMap.contains(date)) { //if it is not a holiday nor a weekend, it is a processing day d->m_holidayMap.insert(date, true); } } } #endif } KMStatus::KMStatus(const QString &text) { m_prevText = kmymoney->slotStatusMsg(text); } KMStatus::~KMStatus() { kmymoney->slotStatusMsg(m_prevText); } void KMyMoneyApp::Private::unlinkStatementXML() { QDir d(KMyMoneySettings::logPath(), "kmm-statement*"); for (uint i = 0; i < d.count(); ++i) { qDebug("Remove %s", qPrintable(d[i])); d.remove(KMyMoneySettings::logPath() + QString("/%1").arg(d[i])); } m_statementXMLindex = 0; } void KMyMoneyApp::Private::closeFile() { q->slotSelectAccount(MyMoneyAccount()); q->slotSelectInstitution(MyMoneyInstitution()); q->slotSelectInvestment(MyMoneyAccount()); q->slotSelectSchedule(); q->slotSelectCurrency(); q->slotSelectBudget(QList()); q->slotSelectPayees(QList()); q->slotSelectTags(QList()); q->slotSelectTransactions(KMyMoneyRegister::SelectedTransactions()); m_reconciliationAccount = MyMoneyAccount(); m_myMoneyView->finishReconciliation(m_reconciliationAccount); m_myMoneyView->closeFile(); m_fileName = QUrl(); q->updateCaption(); // just create a new balance warning object delete m_balanceWarning; m_balanceWarning = new KBalanceWarning(q); emit q->fileLoaded(m_fileName); } diff --git a/kmymoney/widgets/CMakeLists.txt b/kmymoney/widgets/CMakeLists.txt index ec1825a9f..a449decf2 100644 --- a/kmymoney/widgets/CMakeLists.txt +++ b/kmymoney/widgets/CMakeLists.txt @@ -1,229 +1,227 @@ ########### create links ############### set(kmymoney_STAT_HEADERS kaccounttemplateselector.h kbudgetvalues.h kguiutils.h kmymoneyaccountcombo.h kmymoneyaccountcompletion.h kmymoneyaccountselector.h kmymoneycategory.h kmymoneycombo.h kmymoneymvccombo.h kmymoneycompletion.h kmymoneycurrencyselector.h kmymoneydateinput.h kmymoneyedit.h kmymoneylineedit.h kmymoneyselector.h - kmymoneytitlelabel.h kmymoneywizard.h register.h registeritem.h groupmarker.h fancydategroupmarker.h + kmymoneytitlelabel.h register.h registeritem.h groupmarker.h fancydategroupmarker.h scheduledtransaction.h selectedtransaction.h selectedtransactions.h stdtransactiondownloaded.h stdtransactionmatched.h transactioneditorcontainer.h transactionform.h transaction.h investtransaction.h stdtransaction.h transactionsortoption.h reporttabimpl.h reportcontrolimpl.h kmymoneyvalidationfeedback.h onlinejobmessagesview.h kmymoneydateedit.h amountedit.h creditdebithelper.h ) ########### Shared widget library ########### set(kmm_widgets_sources kmymoneydateinput.cpp kmymoneyvalidationfeedback.cpp styleditemdelegateforwarder.cpp kmymoneyedit.cpp kmymoneylineedit.cpp kmymoneytextedit.cpp kmymoneytextedithighlighter.cpp kmymoneymvccombo.cpp kmymoneygeneralcombo.cpp kmymoneyactivitycombo.cpp kmymoneycashflowcombo.cpp kmymoneyfrequencycombo.cpp kmymoneyoccurrencecombo.cpp kmymoneyoccurrenceperiodcombo.cpp kmymoneypayeecombo.cpp kmymoneyperiodcombo.cpp kmymoneyreconcilecombo.cpp kmymoneytagcombo.cpp ktagcontainer.cpp ktaglabel.cpp kmymoneyselector.cpp kmymoneycalculator.cpp ktreewidgetfilterlinewidget.cpp kguiutils.cpp onlinejobmessagesview.cpp kmymoneydateedit.cpp amountedit.cpp creditdebithelper.cpp ) ki18n_wrap_ui(kmm_widgets_sources kmymoneyvalidationfeedback.ui onlinejobmessagesview.ui ) add_library(kmm_widgets SHARED ${kmm_widgets_sources}) target_link_libraries(kmm_widgets PUBLIC KF5::TextWidgets KF5::KIOWidgets KF5::Completion KF5::Notifications KF5::ItemViews KF5::I18n Qt5::Gui Qt5::Sql Qt5::Core Alkimia::alkimia kmm_config kmm_mymoney ) set_target_properties(kmm_widgets PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} COMPILE_FLAGS "-DKMM_BUILD_WIDGETS_LIB" ) generate_export_header(kmm_widgets) install(TARGETS kmm_widgets ${INSTALL_TARGETS_DEFAULT_ARGS} ) ########### Basic Widget Library (kmymoney_base) STATIC ################# # Common sources for libkmymoney.so and libwidgets.a that do not # contain the KMM_DESIGNER flag set(_uncritial_common_sources fixedcolumntreeview.cpp kbudgetvalues.cpp kmymoneyaccountcombo.cpp kmymoneyaccountselector.cpp kmymoneyaccounttreeview.cpp accountsviewproxymodel.cpp budgetviewproxymodel.cpp kmymoneycombo.cpp kmymoneycompletion.cpp kmymoneytitlelabel.cpp kmymoneydateedit.cpp - kmymoneywizard.cpp - kmymoneywizardpage.cpp kpricetreeitem.cpp registeritem.cpp registerfilter.cpp scheduledtransaction.cpp selectedtransaction.cpp selectedtransactions.cpp stdtransactiondownloaded.cpp stdtransactionmatched.cpp transactionform.cpp tabbar.cpp transactionformitemdelegate.cpp transactionsortoption.cpp ) # sources that contain the KMM_DESIGNER flag set (_critial_common_sources kaccounttemplateselector.cpp kmymoneycurrencyselector.cpp kmymoneyaccountcompletion.cpp kmymoneycategory.cpp groupmarker.cpp groupmarkers.cpp fancydategroupmarker.cpp fancydategroupmarkers.cpp register.cpp itemptrvector.cpp qwidgetcontainer.cpp registeritemdelegate.cpp transaction.cpp stdtransaction.cpp investtransaction.cpp transactioneditorcontainer.cpp ) set (kmymoney_base_UI kbudgetvalues.ui transactionsortoption.ui kaccounttemplateselector.ui ) ki18n_wrap_ui(kmymoney_base_ui_srcs ${kmymoney_base_UI}) set(_uncritial_common_sources ${_uncritial_common_sources} ${kmymoney_base_ui_srcs}) # in order to use add_dependencies, we need to add this custom target # for all generated header files. # (see http://www.vtk.org/Wiki/CMake_FAQ#How_can_I_add_a_dependency_to_a_source_file_which_is_generated_in_a_subdirectory.3F ) add_custom_target(generate_base_ui_srcs DEPENDS ${kmymoney_base_ui_srcs}) # We can compile the uncritical sources without KMM_DESIGNER flags add_library(kmymoney_base STATIC ${_uncritial_common_sources}) # TODO: fix dependencies target_link_libraries(kmymoney_base KF5::XmlGui KF5::TextWidgets KF5::IconThemes KF5::I18n KF5::ConfigWidgets KF5::ConfigCore KF5::Completion KF5::Service Qt5::Gui Qt5::Widgets Qt5::Sql Qt5::Xml Alkimia::alkimia) add_dependencies(kmymoney_base kmm_config) ########### QtDesigner Widget Library (kmymoneywidgets) ################# # we never link against this library, # but it is needed for uic and QtDesigner if( USE_QT_DESIGNER ) set(kmymoneywidgets_PART_SRCS ${CMAKE_CURRENT_BINARY_DIR}/kmymoneywidgets.cpp) kde4_add_widget_files(kmymoneywidgets_PART_SRCS kmymoney.widgets) set(kmymoneywidgets_PART_SRCS ${_critial_common_sources} ${kmymoneywidgets_PART_SRCS}) add_library(kmymoneywidgets MODULE ${kmymoneywidgets_PART_SRCS}) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) # The option -DKMM_DESIGNER will leave away any code that breaks uic. set_target_properties(kmymoneywidgets PROPERTIES COMPILE_FLAGS "-DKMM_DESIGNER") # The qt-designer widget library shouldn't need to link against the # dialogs and converter libraries. If a widget references something # from one of these libraries it is most likely due to code that needs # to be excluded with a KMM_DESIGNER ifndef. target_link_libraries(kmymoneywidgets kmymoney_base kmm_mymoney kmymoney_common kmm_config models) install(TARGETS kmymoneywidgets DESTINATION ${QT_PLUGINS_DIR}/designer ) endif( USE_QT_DESIGNER ) ########### Widget Library (widgets) STATIC ################# set(libwidgets_a_SOURCES ${_critial_common_sources} kmymoneybriefschedule.cpp registersearchline.cpp transactioneditorcontainer.cpp reporttabimpl.cpp reportcontrolimpl.cpp daterangedlg.cpp ) set(libwidgets_a_UI kmymoneybriefschedule.ui reportcontrol.ui reporttabgeneral.ui reporttabrowcolquery.ui reporttabrowcolpivot.ui reporttabrange.ui reporttabchart.ui reporttabcapitalgain.ui reporttabperformance.ui daterangedlg.ui ) # using uic on the above UI files DEPENDS on libkmymoney.so. If uic # does not find libkmymoney.so, gcc will fail compiling # kmymoneyreportconfigtab2decl.cpp and throw errors like "invalid use # of undefined type `struct KMyMoneyGeneralCombo'" ki18n_wrap_ui(widgets_ui_srcs ${libwidgets_a_UI}) add_custom_target(generate_widgets_ui_srcs DEPENDS ${widgets_ui_srcs}) add_library(widgets STATIC ${libwidgets_a_SOURCES} ${widgets_ui_srcs} ) target_link_libraries(widgets KF5::XmlGui kmymoney_base) add_dependencies(widgets kmm_config) ########### install files ############### install(FILES ${kmymoney_STAT_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/kmm_widgets_export.h DESTINATION ${INCLUDE_INSTALL_DIR}/kmymoney COMPONENT Devel) diff --git a/kmymoney/widgets/kmymoneywizard.cpp b/kmymoney/widgets/kmymoneywizard.cpp deleted file mode 100644 index 7b3a7380c..000000000 --- a/kmymoney/widgets/kmymoneywizard.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/*************************************************************************** - kmymoneywizard.cpp - ------------------- - copyright : (C) 2006 by Thomas Baumagrt - email : ipwizard@users.sourceforge.net - (C) 2017 by Łukasz Wojniłowicz - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -// ---------------------------------------------------------------------------- -// QT Includes - -#include -#include -#include -#include -#include -#include -#include -#include - -// ---------------------------------------------------------------------------- -// KDE Includes - -#include -#include -#include -#include - -// ---------------------------------------------------------------------------- -// Project Includes - -#include "kmymoneywizardpage.h" -#include "kmymoneytitlelabel.h" -#include "icons/icons.h" -#include "kmymoneywizard.h" - -using namespace Icons; - -KMyMoneyWizard::KMyMoneyWizard(QWidget *parent, bool modal, Qt::WindowFlags f) : - QDialog(parent, f), - m_step(0) -{ - setModal(modal); - - // enable the little grip in the right corner - setSizeGripEnabled(true); - - // create buttons - m_cancelButton = new QPushButton(i18n("&Cancel"), this); - m_backButton = new QPushButton(i18nc("Go to previous page of the wizard", "&Back"), this); - m_nextButton = new QPushButton(i18nc("Go to next page of the wizard", "&Next"), this); - m_finishButton = new QPushButton(i18nc("Finish the wizard", "&Finish"), this); - m_helpButton = new QPushButton(i18n("&Help"), this); - - if (style()->styleHint(QStyle::SH_DialogButtonBox_ButtonsHaveIcons, 0, this)) { - m_backButton->setIcon(KStandardGuiItem::back(KStandardGuiItem::UseRTL).icon()); - m_nextButton->setIcon(KStandardGuiItem::forward(KStandardGuiItem::UseRTL).icon()); - m_finishButton->setIcon(QIcon::fromTheme(g_Icons[Icon::DialogOKApply])); - m_cancelButton->setIcon(QIcon::fromTheme(g_Icons[Icon::DialogCancel])); - m_helpButton->setIcon(QIcon::fromTheme(g_Icons[Icon::HelpContents])); - } - - // create button layout - m_buttonLayout = new QHBoxLayout; - m_buttonLayout->addWidget(m_helpButton); - m_buttonLayout->addStretch(1); - m_buttonLayout->addWidget(m_backButton); - m_buttonLayout->addWidget(m_nextButton); - m_buttonLayout->addWidget(m_finishButton); - m_buttonLayout->addWidget(m_cancelButton); - - // create wizard layout - m_wizardLayout = new QVBoxLayout(this); - m_wizardLayout->setContentsMargins(6, 6, 6, 6); - m_wizardLayout->setSpacing(0); - m_wizardLayout->setObjectName("wizardLayout"); - m_titleLabel = new KMyMoneyTitleLabel(this); - m_titleLabel->setObjectName("titleLabel"); - m_wizardLayout->addWidget(m_titleLabel); - - QHBoxLayout* hboxLayout = new QHBoxLayout; - hboxLayout->setContentsMargins(0, 0, 0, 0); - hboxLayout->setSpacing(6); - hboxLayout->setObjectName("hboxLayout"); - - // create stage layout and frame - m_stepFrame = new QFrame(this); - m_stepFrame->setObjectName("stepFrame"); - QPalette palette = m_stepFrame->palette(); - palette.setColor(m_stepFrame->backgroundRole(), KColorScheme::NormalText); - m_stepFrame->setPalette(palette); - m_stepLayout = new QVBoxLayout(m_stepFrame); - m_stepLayout->setContentsMargins(11, 11, 11, 11); - m_stepLayout->setSpacing(6); - m_stepLayout->setObjectName("stepLayout"); - m_stepLayout->addWidget(new QLabel(QString(), m_stepFrame)); - m_stepLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); - m_stepLabel = new QLabel(m_stepFrame); - m_stepLabel->setAlignment(Qt::AlignHCenter); - m_stepLayout->addWidget(m_stepLabel); - hboxLayout->addWidget(m_stepFrame); - - m_stepPalette = m_stepLabel->palette(); - - // add a vertical line between the stepFrame and the pages - QFrame* line = new QFrame(this); - line->setObjectName("line"); - line->setFrameShadow(QFrame::Sunken); - line->setFrameShape(QFrame::VLine); - hboxLayout->addWidget(line); - - // create page layout - m_pageLayout = new QVBoxLayout; - m_pageLayout->setContentsMargins(0, 0, 0, 0); - m_pageLayout->setSpacing(6); - m_pageLayout->setObjectName("pageLayout"); - - // the page will be inserted later dynamically above this line - line = new QFrame(this); - line->setObjectName("line"); - line->setFrameShadow(QFrame::Sunken); - line->setFrameShape(QFrame::HLine); - m_pageLayout->addWidget(line); - m_pageLayout->addLayout(m_buttonLayout); - - // now glue everything together - hboxLayout->addLayout(m_pageLayout); - m_wizardLayout->addLayout(hboxLayout); - - resize(QSize(670, 550).expandedTo(minimumSizeHint())); - - m_titleLabel->setText(i18n("No Title specified")); - m_titleLabel->setRightImageFile("pics/titlelabel_background.png"); - - m_finishButton->hide(); - - connect(m_backButton, &QAbstractButton::clicked, this, &KMyMoneyWizard::backButtonClicked); - connect(m_nextButton, &QAbstractButton::clicked, this, &KMyMoneyWizard::nextButtonClicked); - connect(m_cancelButton, &QAbstractButton::clicked, this, &QDialog::reject); - connect(m_finishButton, &QAbstractButton::clicked, this, &KMyMoneyWizard::accept); - connect(m_helpButton, &QAbstractButton::clicked, this, &KMyMoneyWizard::helpButtonClicked); -} - -KMyMoneyWizard::~KMyMoneyWizard() -{ -} - -void KMyMoneyWizard::setTitle(const QString& txt) -{ - m_titleLabel->setText(txt); -} - -void KMyMoneyWizard::addStep(const QString& text) -{ - QLabel* step = new QLabel(text, m_stepFrame); - step->setFrameStyle(QFrame::Panel | QFrame::Raised); - step->setAlignment(Qt::AlignHCenter); - step->setFrameStyle(QFrame::Box | QFrame::Sunken); - step->setMargin(2); - step->setPalette(m_stepPalette); - - m_steps.append(step); - m_stepLayout->insertWidget(m_steps.count(), step); - - QFont font(step->font()); - font.setBold(true); - QFontMetrics fm(font); - int w = fm.width(text) + 30; - if (m_stepFrame->minimumWidth() < w) { - m_stepFrame->setMinimumWidth(w); - } -} - -QList KMyMoneyWizard::historyPages() const -{ - return m_history; -} - -void KMyMoneyWizard::setStepHidden(int step, bool hidden) -{ - if ((step < 1) || (step > m_steps.count())) - return; - - m_steps[--step]->setHidden(hidden); - updateStepCount(); -} - -void KMyMoneyWizard::selectStep(int step) -{ - if ((step < 1) || (step > m_steps.count())) - return; - - m_step = step; - QList::iterator it_l; - QFont f = m_steps[0]->font(); - for (it_l = m_steps.begin(); it_l != m_steps.end(); ++it_l) { - f.setBold(false); - (*it_l)->setFrameStyle(QFrame::NoFrame); - if (--step == 0) { - f.setBold(true); - (*it_l)->setFrameStyle(QFrame::Box | QFrame::Sunken); - } - (*it_l)->setFont(f); - } - updateStepCount(); -} - -void KMyMoneyWizard::reselectStep() -{ - selectStep(m_step); -} - -void KMyMoneyWizard::setHelpContext(const QString& ctx) -{ - m_helpContext = ctx; -} - -void KMyMoneyWizard::updateStepCount() -{ - QList::iterator it_l; - int stepCount = 0; - int hiddenAdjust = 0; - int step = 0; - for (it_l = m_steps.begin(); it_l != m_steps.end(); ++it_l) { - if (!(*it_l)->isHidden()) - ++stepCount; - else if (step < m_step) - hiddenAdjust++; - ++step; - } - m_stepLabel->setText(i18n("Step %1 of %2", (m_step - hiddenAdjust), stepCount)); -} - -void KMyMoneyWizard::setFirstPage(KMyMoneyWizardPage* page) -{ - page->resetPage(); - m_history.clear(); - m_history.append(page); - switchPage(0); -} - -void KMyMoneyWizard::switchPage(KMyMoneyWizardPage* oldPage) -{ - if (oldPage) { - oldPage->widget()->hide(); - m_pageLayout->removeWidget(oldPage->widget()); - disconnect(oldPage->object(), SIGNAL(completeStateChanged()), this, SLOT(completeStateChanged())); - } - KMyMoneyWizardPage* newPage = m_history.back(); - if (newPage) { - m_pageLayout->insertWidget(0, newPage->widget()); - connect(newPage->object(), SIGNAL(completeStateChanged()), this, SLOT(completeStateChanged())); - newPage->widget()->show(); - selectStep(newPage->step()); - if (newPage->isLastPage()) { - m_nextButton->setDefault(false); - m_finishButton->setDefault(true); - } else { - m_finishButton->setDefault(false); - m_nextButton->setDefault(true); - } - QWidget* w = newPage->initialFocusWidget(); - if (w) - w->setFocus(); - } - completeStateChanged(); -} - -void KMyMoneyWizard::backButtonClicked() -{ - KMyMoneyWizardPage* oldPage = m_history.back(); - m_history.pop_back(); - oldPage->leavePage(); - oldPage->resetPage(); - switchPage(oldPage); -} - -void KMyMoneyWizard::nextButtonClicked() -{ - // make sure it is really complete. Some widgets only change state during focusOutEvent, - // so we just create such an animal by changing the focus to the next button and - // check again for copmpleness - m_nextButton->setFocus(); - KMyMoneyWizardPage* oldPage = m_history.back(); - if (oldPage->isComplete()) { - KMyMoneyWizardPage* newPage = oldPage->nextPage(); - m_history.append(newPage); - newPage->enterPage(); - newPage->resetPage(); - switchPage(oldPage); - } -} - -void KMyMoneyWizard::helpButtonClicked() -{ - KMyMoneyWizardPage* currentPage = m_history.back(); - QString ctx = currentPage->helpContext(); - if (ctx.isEmpty()) - ctx = m_helpContext; - KHelpClient::invokeHelp(ctx); -} - -void KMyMoneyWizard::completeStateChanged() -{ - KMyMoneyWizardPage* currentPage = m_history.back(); - bool lastPage = currentPage->isLastPage(); - - m_finishButton->setVisible(lastPage); - m_nextButton->setVisible(!lastPage); - - QPushButton* button; - - button = lastPage ? m_finishButton : m_nextButton; - - auto rc = currentPage->isComplete(); - button->setEnabled(rc); - - m_backButton->setEnabled(m_history.count() > 1); -} - -void KMyMoneyWizard::accept() -{ - // make sure it is really complete. Some widgets only change state during focusOutEvent, - // so we just create such an animal by changing the focus to the finish button and - // check again for completeness. - m_finishButton->setFocus(); - KMyMoneyWizardPage* page = m_history.back(); - if (page->isComplete()) - QDialog::accept(); -} diff --git a/kmymoney/wizards/CMakeLists.txt b/kmymoney/wizards/CMakeLists.txt index 9e612799a..03d6a5cd1 100644 --- a/kmymoney/wizards/CMakeLists.txt +++ b/kmymoney/wizards/CMakeLists.txt @@ -1,10 +1,19 @@ project(Wizards) include_directories( ${CMAKE_CURRENT_BINARY_DIR}/wizardpages) add_subdirectory( wizardpages ) add_subdirectory( newuserwizard ) add_subdirectory( newaccountwizard ) add_subdirectory( newinvestmentwizard ) add_subdirectory( newloanwizard ) add_subdirectory( endingbalancedlg ) + +set(kmymoneywizard_sources + kmymoneywizard.cpp + kmymoneywizardpage.cpp + ) + +add_library(kmymoneywizard STATIC ${kmymoneywizard_sources}) + +target_link_libraries(kmymoneywizard KF5::XmlGui KF5::TextWidgets) diff --git a/kmymoney/wizards/endingbalancedlg/CMakeLists.txt b/kmymoney/wizards/endingbalancedlg/CMakeLists.txt index ccacf5f8a..8a5fe3cce 100644 --- a/kmymoney/wizards/endingbalancedlg/CMakeLists.txt +++ b/kmymoney/wizards/endingbalancedlg/CMakeLists.txt @@ -1,25 +1,25 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) set (libendingbalancedlg_a_SOURCES kendingbalancedlg.cpp checkingstartwizardpage.cpp checkingstatementinfowizardpage.cpp interestchargecheckingswizardpage.cpp previouspostponewizardpage.cpp ) set (libendingbalancedlg_a_UI - kendingbalancedlgdecl.ui - checkingstartwizardpagedecl.ui - checkingstatementinfowizardpagedecl.ui - interestchargecheckingswizardpagedecl.ui - previouspostponewizardpagedecl.ui + kendingbalancedlg.ui + checkingstartwizardpage.ui + checkingstatementinfowizardpage.ui + interestchargecheckingswizardpage.ui + previouspostponewizardpage.ui ) ki18n_wrap_ui(libendingbalancedlg_a_SOURCES ${libendingbalancedlg_a_UI} ) add_library(endingbalancedlg STATIC ${libendingbalancedlg_a_SOURCES}) target_link_libraries(endingbalancedlg KF5::ConfigWidgets KF5::WidgetsAddons KF5::I18n KF5::Completion Qt5::Widgets Qt5::Sql Qt5::Xml Alkimia::alkimia) # we rely on some widgets to be generated add_dependencies(endingbalancedlg widgets dialogs) diff --git a/kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.cpp b/kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.cpp index c41573f98..1b6983e5e 100644 --- a/kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.cpp +++ b/kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.cpp @@ -1,39 +1,43 @@ /*************************************************************************** checkingstartwizardpage.cpp - description ------------------- begin : Sun Jul 18 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "checkingstartwizardpage.h" // ---------------------------------------------------------------------------- // QT Includes - // ---------------------------------------------------------------------------- // KDE Includes - // ---------------------------------------------------------------------------- // Project Includes +#include "ui_checkingstartwizardpage.h" -CheckingStartWizardPage::CheckingStartWizardPage(QWidget *parent) - : CheckingStartWizardPageDecl(parent) +CheckingStartWizardPage::CheckingStartWizardPage(QWidget *parent) : + QWizardPage(parent), + ui(new Ui::CheckingStartWizardPage) { - + ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly +} +CheckingStartWizardPage::~CheckingStartWizardPage() +{ + delete ui; } diff --git a/kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.h b/kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.h index 98296b9a2..13bda102d 100644 --- a/kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.h +++ b/kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.h @@ -1,54 +1,52 @@ /*************************************************************************** checkingstartwizardpage.h - description ------------------- begin : Sun Jul 18 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CHECKINGSTARTWIZARDPAGE_H #define CHECKINGSTARTWIZARDPAGE_H // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "ui_checkingstartwizardpagedecl.h" +namespace Ui { class CheckingStartWizardPage; } /** * This class implements the CheckingStart page of the * @ref KEndingBalanceDlg wizard. */ -class CheckingStartWizardPageDecl : public QWizardPage, public Ui::CheckingStartWizardPageDecl -{ -public: - CheckingStartWizardPageDecl(QWidget *parent) : QWizardPage(parent) { - setupUi(this); - } -}; -class CheckingStartWizardPage : public CheckingStartWizardPageDecl +class CheckingStartWizardPage : public QWizardPage { Q_OBJECT + Q_DISABLE_COPY(CheckingStartWizardPage) + public: - explicit CheckingStartWizardPage(QWidget *parent = 0); + explicit CheckingStartWizardPage(QWidget *parent = nullptr); + ~CheckingStartWizardPage(); +private: + Ui::CheckingStartWizardPage *ui; }; #endif diff --git a/kmymoney/wizards/endingbalancedlg/checkingstartwizardpagedecl.ui b/kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.ui similarity index 92% rename from kmymoney/wizards/endingbalancedlg/checkingstartwizardpagedecl.ui rename to kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.ui index 107470efc..e3ffc529b 100644 --- a/kmymoney/wizards/endingbalancedlg/checkingstartwizardpagedecl.ui +++ b/kmymoney/wizards/endingbalancedlg/checkingstartwizardpage.ui @@ -1,52 +1,52 @@ - CheckingStartWizardPageDecl - + CheckingStartWizardPage + 6 34 577 388 General Information 6 11 Reconciling your account ensures your records match those of your institution, and that there are no mistakes on either side. You should reconcile your account whenever you receive a statement from your institution. All relevant information necessary for this process is usually printed on your statement. On the next page you will verify that the ending balance matches that on your statement. If not, please modify it. The starting balance is the sum of your cleared and reconciled transactions. Qt::AlignTop true diff --git a/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.cpp b/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.cpp index 9583dc8b5..c60941ff9 100644 --- a/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.cpp +++ b/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.cpp @@ -1,46 +1,52 @@ /*************************************************************************** checkingstatementinfowizardpage.cpp - description ------------------- begin : Sun Jul 18 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "checkingstatementinfowizardpage.h" // ---------------------------------------------------------------------------- // QT Includes - // ---------------------------------------------------------------------------- // KDE Includes - // ---------------------------------------------------------------------------- // Project Includes +#include "ui_checkingstatementinfowizardpage.h" -CheckingStatementInfoWizardPage::CheckingStatementInfoWizardPage(QWidget *parent) - : CheckingStatementInfoWizardPageDecl(parent) +CheckingStatementInfoWizardPage::CheckingStatementInfoWizardPage(QWidget *parent) : + QWizardPage(parent), + ui(new Ui::CheckingStatementInfoWizardPage) { - m_statementDate->setDate(QDate::currentDate()); + ui->setupUi(this); + ui->m_statementDate->setDate(QDate::currentDate()); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly - registerField("statementDate", m_statementDate, "date", SIGNAL(dateChanged(QDate))); + registerField("statementDate", ui->m_statementDate, "date", SIGNAL(dateChanged(QDate))); - registerField("endingBalance", m_endingBalance, "value", SIGNAL(textChanged())); - registerField("endingBalanceValid", m_endingBalance, "valid", SIGNAL(textChanged())); - registerField("previousBalance", m_previousBalance, "value", SIGNAL(textChanged())); - registerField("previousBalanceValid", m_previousBalance, "valid", SIGNAL(textChanged())); + registerField("endingBalance", ui->m_endingBalance, "value", SIGNAL(textChanged())); + registerField("endingBalanceValid", ui->m_endingBalance, "valid", SIGNAL(textChanged())); + registerField("previousBalance", ui->m_previousBalance, "value", SIGNAL(textChanged())); + registerField("previousBalanceValid", ui->m_previousBalance, "valid", SIGNAL(textChanged())); +} + +CheckingStatementInfoWizardPage::~CheckingStatementInfoWizardPage() +{ + delete ui; } diff --git a/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.h b/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.h index 379e015d9..301c7bcd6 100644 --- a/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.h +++ b/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.h @@ -1,54 +1,51 @@ /*************************************************************************** checkingstatementinfowizardpage.h - description ------------------- begin : Sun Jul 18 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CHECKINGSTATEMENTINFOWIZARDPAGE_H #define CHECKINGSTATEMENTINFOWIZARDPAGE_H // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "ui_checkingstatementinfowizardpagedecl.h" +namespace Ui { class CheckingStatementInfoWizardPage; } /** * This class implements the CheckingStatementInfo page of the * @ref KEndingBalanceDlg wizard. */ -class CheckingStatementInfoWizardPageDecl : public QWizardPage, public Ui::CheckingStatementInfoWizardPageDecl -{ -public: - CheckingStatementInfoWizardPageDecl(QWidget *parent) : QWizardPage(parent) { - setupUi(this); - } -}; -class CheckingStatementInfoWizardPage : public CheckingStatementInfoWizardPageDecl +class CheckingStatementInfoWizardPage : public QWizardPage { Q_OBJECT + Q_DISABLE_COPY(CheckingStatementInfoWizardPage) + public: - explicit CheckingStatementInfoWizardPage(QWidget *parent = 0); + explicit CheckingStatementInfoWizardPage(QWidget *parent = nullptr); + ~CheckingStatementInfoWizardPage(); + Ui::CheckingStatementInfoWizardPage *ui; }; #endif diff --git a/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpagedecl.ui b/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.ui similarity index 98% rename from kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpagedecl.ui rename to kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.ui index fdc48132f..b09b1b433 100644 --- a/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpagedecl.ui +++ b/kmymoney/wizards/endingbalancedlg/checkingstatementinfowizardpage.ui @@ -1,177 +1,177 @@ - CheckingStatementInfoWizardPageDecl - + CheckingStatementInfoWizardPage + 6 34 577 388 Statement Information true Qt::Vertical QSizePolicy::Expanding 20 50 6 0 Qt::Horizontal QSizePolicy::Expanding 42 0 0 0 Statement date: false Starting balance of this statement: false false Ending balance of this statement: false Qt::Horizontal QSizePolicy::Expanding 46 0 Qt::Vertical QSizePolicy::Expanding 16 87 1 false diff --git a/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.cpp b/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.cpp index 2d268865b..6645ba611 100644 --- a/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.cpp +++ b/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.cpp @@ -1,69 +1,71 @@ /*************************************************************************** interestchargecheckingswizardpage.cpp - description ------------------- begin : Sun Jul 18 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "interestchargecheckingswizardpage.h" // ---------------------------------------------------------------------------- // QT Includes - // ---------------------------------------------------------------------------- // KDE Includes - // ---------------------------------------------------------------------------- // Project Includes +#include "ui_interestchargecheckingswizardpage.h" -InterestChargeCheckingsWizardPage::InterestChargeCheckingsWizardPage(QWidget *parent) - : InterestChargeCheckingsWizardPageDecl(parent) +InterestChargeCheckingsWizardPage::InterestChargeCheckingsWizardPage(QWidget *parent) : + QWizardPage(parent), + ui(new Ui::InterestChargeCheckingsWizardPage) { - + ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly - registerField("interestDateEdit", m_interestDateEdit, "date", SIGNAL(dateChanged(QDate))); - registerField("chargesDateEdit", m_chargesDateEdit, "date", SIGNAL(dateChanged(QDate))); + registerField("interestDateEdit", ui->m_interestDateEdit, "date", SIGNAL(dateChanged(QDate))); + registerField("chargesDateEdit", ui->m_chargesDateEdit, "date", SIGNAL(dateChanged(QDate))); - registerField("interestEdit", m_interestEdit, "value", SIGNAL(textChanged())); - registerField("interestEditValid", m_interestEdit, "valid", SIGNAL(textChanged())); - registerField("chargesEdit", m_chargesEdit, "value", SIGNAL(textChanged())); - registerField("chargesEditValid", m_chargesEdit, "valid", SIGNAL(textChanged())); + registerField("interestEdit", ui->m_interestEdit, "value", SIGNAL(textChanged())); + registerField("interestEditValid", ui->m_interestEdit, "valid", SIGNAL(textChanged())); + registerField("chargesEdit", ui->m_chargesEdit, "value", SIGNAL(textChanged())); + registerField("chargesEditValid", ui->m_chargesEdit, "valid", SIGNAL(textChanged())); - registerField("interestCategoryEdit", m_interestCategoryEdit, "selectedItem", SIGNAL(itemSelected(QString))); - registerField("chargesCategoryEdit", m_chargesCategoryEdit, "selectedItem", SIGNAL(itemSelected(QString))); + registerField("interestCategoryEdit", ui->m_interestCategoryEdit, "selectedItem", SIGNAL(itemSelected(QString))); + registerField("chargesCategoryEdit", ui->m_chargesCategoryEdit, "selectedItem", SIGNAL(itemSelected(QString))); - registerField("payeeEdit", m_payeeEdit, "selectedItem", SIGNAL(itemSelected(QString))); - - connect(m_interestEdit, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged())); - connect(m_interestCategoryEdit, SIGNAL(editTextChanged(QString)), this, SIGNAL(completeChanged())); - connect(m_chargesEdit, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged())); - connect(m_chargesCategoryEdit, SIGNAL(editTextChanged(QString)), this, SIGNAL(completeChanged())); + registerField("payeeEdit", ui->m_payeeEdit, "selectedItem", SIGNAL(itemSelected(QString))); + connect(ui->m_interestEdit, &KMyMoneyEdit::textChanged, this, &QWizardPage::completeChanged); + connect(ui->m_interestCategoryEdit, &QComboBox::editTextChanged, this, &QWizardPage::completeChanged); + connect(ui->m_chargesEdit, &KMyMoneyEdit::textChanged, this, &QWizardPage::completeChanged); + connect(ui->m_chargesCategoryEdit, &QComboBox::editTextChanged, this, &QWizardPage::completeChanged); +} +InterestChargeCheckingsWizardPage::~InterestChargeCheckingsWizardPage() +{ + delete ui; } bool InterestChargeCheckingsWizardPage::isComplete() const { - int cnt1, cnt2; - cnt1 = !m_interestEdit->value().isZero() + !m_interestCategoryEdit->selectedItem().isEmpty(); - cnt2 = !m_chargesEdit->value().isZero() + !m_chargesCategoryEdit->selectedItem().isEmpty(); + auto cnt1 = !ui->m_interestEdit->value().isZero() + !ui->m_interestCategoryEdit->selectedItem().isEmpty(); + auto cnt2 = !ui->m_chargesEdit->value().isZero() + !ui->m_chargesCategoryEdit->selectedItem().isEmpty(); if (cnt1 == 1 || cnt2 == 1) return false; return true; } diff --git a/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.h b/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.h index e887127c7..f693658e3 100644 --- a/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.h +++ b/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.h @@ -1,59 +1,56 @@ /*************************************************************************** interestchargecheckingswizardpage.h - description ------------------- begin : Sun Jul 18 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef INTERESTCHARGECHECKINGSWIZARDPAGE_H #define INTERESTCHARGECHECKINGSWIZARDPAGE_H // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "ui_interestchargecheckingswizardpagedecl.h" +namespace Ui { class InterestChargeCheckingsWizardPage; } /** * This class implements the InterestChargeCheckings page of the * @ref KEndingBalanceDlg wizard. */ -class InterestChargeCheckingsWizardPageDecl : public QWizardPage, public Ui::InterestChargeCheckingsWizardPageDecl -{ -public: - InterestChargeCheckingsWizardPageDecl(QWidget *parent) : QWizardPage(parent) { - setupUi(this); - } -}; -class InterestChargeCheckingsWizardPage : public InterestChargeCheckingsWizardPageDecl +class InterestChargeCheckingsWizardPage : public QWizardPage { Q_OBJECT + Q_DISABLE_COPY(InterestChargeCheckingsWizardPage) + public: - explicit InterestChargeCheckingsWizardPage(QWidget *parent = 0); + explicit InterestChargeCheckingsWizardPage(QWidget *parent = nullptr); + ~InterestChargeCheckingsWizardPage(); /** * Overload the isComplete function to control the Next button */ bool isComplete() const; + Ui::InterestChargeCheckingsWizardPage *ui; }; #endif diff --git a/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpagedecl.ui b/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.ui similarity index 98% rename from kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpagedecl.ui rename to kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.ui index f93d6be78..be3a32e73 100644 --- a/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpagedecl.ui +++ b/kmymoney/wizards/endingbalancedlg/interestchargecheckingswizardpage.ui @@ -1,219 +1,219 @@ - InterestChargeCheckingsWizardPageDecl - + InterestChargeCheckingsWizardPage + Interest / Charges If necessary, enter information about interest or charges here. KMyMoney will create transactions and cleares them directly for you. true QFrame::HLine QFrame::Sunken Qt::Vertical QSizePolicy::Expanding 16 16 Qt::Horizontal QSizePolicy::Expanding 60 20 0 0 Payee false 1 0 Interest 2 0 0 false Charges 2 0 0 false Qt::Horizontal QSizePolicy::Expanding 60 20 Qt::Vertical QSizePolicy::Expanding 16 16 KMyMoneyPayeeCombo KComboBox
kmymoneypayeecombo.h
1
diff --git a/kmymoney/wizards/endingbalancedlg/kendingbalancedlg.cpp b/kmymoney/wizards/endingbalancedlg/kendingbalancedlg.cpp index 33c314e3d..a0e03920e 100644 --- a/kmymoney/wizards/endingbalancedlg/kendingbalancedlg.cpp +++ b/kmymoney/wizards/endingbalancedlg/kendingbalancedlg.cpp @@ -1,391 +1,425 @@ /*************************************************************************** kendingbalancedlg.cpp ------------------- copyright : (C) 2000,2003 by Michael Edwardes, Thomas Baumgart email : mte@users.sourceforge.net ipwizard@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kendingbalancedlg.h" // ---------------------------------------------------------------------------- // QT Includes #include #include #include #include // ---------------------------------------------------------------------------- // KDE Includes #include #include // ---------------------------------------------------------------------------- // Project Includes +#include "ui_kendingbalancedlg.h" +#include "ui_checkingstatementinfowizardpage.h" +#include "ui_interestchargecheckingswizardpage.h" + +#include "mymoneymoney.h" #include "mymoneyutils.h" #include "kmymoneyedit.h" #include "mymoneysplit.h" #include "mymoneyfile.h" #include "mymoneyinstitution.h" #include "mymoneyaccount.h" #include "mymoneypayee.h" #include "mymoneysecurity.h" #include "mymoneytransaction.h" #include "mymoneytransactionfilter.h" #include "kmymoneycategory.h" #include "kmymoneyaccountselector.h" #include "kmymoneyutils.h" #include "kcurrencycalculator.h" #include "kmymoneysettings.h" -class KEndingBalanceDlg::Private +class KEndingBalanceDlgPrivate { + Q_DISABLE_COPY(KEndingBalanceDlgPrivate) + public: - explicit Private(int numPages) - : m_pages(numPages, true) {} + KEndingBalanceDlgPrivate(int numPages) : + ui(new Ui::KEndingBalanceDlg), + m_pages(numPages, true) + { + } + + ~KEndingBalanceDlgPrivate() + { + delete ui; + } + Ui::KEndingBalanceDlg *ui; MyMoneyTransaction m_tInterest; MyMoneyTransaction m_tCharges; MyMoneyAccount m_account; QMap m_helpAnchor; QBitArray m_pages; }; KEndingBalanceDlg::KEndingBalanceDlg(const MyMoneyAccount& account, QWidget *parent) : - KEndingBalanceDlgDecl(parent), - d(new Private(Page_InterestChargeCheckings + 1)) + QWizard(parent), + d_ptr(new KEndingBalanceDlgPrivate(Page_InterestChargeCheckings + 1)) { + Q_D(KEndingBalanceDlg); setModal(true); QString value; MyMoneyMoney endBalance, startBalance; d->m_account = account; MyMoneySecurity currency = MyMoneyFile::instance()->security(account.currencyId()); //FIXME: port - m_statementInfoPageCheckings->m_enterInformationLabel->setText(QString("") + i18n("Please enter the following fields with the information as you find them on your statement. Make sure to enter all values in %1.", currency.name()) + QString("")); + d->ui->m_statementInfoPageCheckings->ui->m_enterInformationLabel->setText(QString("") + i18n("Please enter the following fields with the information as you find them on your statement. Make sure to enter all values in %1.", currency.name()) + QString("")); // If the previous reconciliation was postponed, // we show a different first page value = account.value("lastReconciledBalance"); if (value.isEmpty()) { // if the last statement has been entered long enough ago (more than one month), // then take the last statement date and add one month and use that as statement // date. QDate lastStatementDate = account.lastReconciliationDate(); if (lastStatementDate.addMonths(1) < QDate::currentDate()) { setField("statementDate", lastStatementDate.addMonths(1)); } slotUpdateBalances(); d->m_pages.clearBit(Page_PreviousPostpone); } else { d->m_pages.clearBit(Page_CheckingStart); d->m_pages.clearBit(Page_InterestChargeCheckings); - //removePage(m_interestChargeCheckings); + //removePage(d->ui->m_interestChargeCheckings); // make sure, we show the correct start page setStartId(Page_PreviousPostpone); MyMoneyMoney factor(1, 1); if (d->m_account.accountGroup() == eMyMoney::Account::Liability) factor = -factor; startBalance = MyMoneyMoney(value) * factor; value = account.value("statementBalance"); endBalance = MyMoneyMoney(value) * factor; //FIXME: port - m_statementInfoPageCheckings->m_previousBalance->setValue(startBalance); - m_statementInfoPageCheckings->m_endingBalance->setValue(endBalance); + d->ui->m_statementInfoPageCheckings->ui->m_previousBalance->setValue(startBalance); + d->ui->m_statementInfoPageCheckings->ui->m_endingBalance->setValue(endBalance); } // We don't need to add the default into the list (see ::help() why) // m_helpAnchor[m_startPageCheckings] = QString(QString()); - d->m_helpAnchor[m_interestChargeCheckings] = QString("details.reconcile.wizard.interest"); - d->m_helpAnchor[m_statementInfoPageCheckings] = QString("details.reconcile.wizard.statement"); + d->m_helpAnchor[d->ui->m_interestChargeCheckings] = QString("details.reconcile.wizard.interest"); + d->m_helpAnchor[d->ui->m_statementInfoPageCheckings] = QString("details.reconcile.wizard.statement"); value = account.value("statementDate"); if (!value.isEmpty()) setField("statementDate", QDate::fromString(value, Qt::ISODate)); //FIXME: port - m_statementInfoPageCheckings->m_lastStatementDate->setText(QString()); + d->ui->m_statementInfoPageCheckings->ui->m_lastStatementDate->setText(QString()); if (account.lastReconciliationDate().isValid()) { - m_statementInfoPageCheckings->m_lastStatementDate->setText(i18n("Last reconciled statement: %1", QLocale().toString(account.lastReconciliationDate()))); + d->ui->m_statementInfoPageCheckings->ui->m_lastStatementDate->setText(i18n("Last reconciled statement: %1", QLocale().toString(account.lastReconciliationDate()))); } // connect the signals with the slots - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotReloadEditWidgets())); - connect(m_statementInfoPageCheckings->m_statementDate, SIGNAL(dateChanged(QDate)), this, SLOT(slotUpdateBalances())); - connect(m_interestChargeCheckings->m_interestCategoryEdit, SIGNAL(createItem(QString,QString&)), this, SLOT(slotCreateInterestCategory(QString,QString&))); - connect(m_interestChargeCheckings->m_chargesCategoryEdit, SIGNAL(createItem(QString,QString&)), this, SLOT(slotCreateChargesCategory(QString,QString&))); - connect(m_interestChargeCheckings->m_payeeEdit, SIGNAL(createItem(QString,QString&)), this, SIGNAL(createPayee(QString,QString&))); + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &KEndingBalanceDlg::slotReloadEditWidgets); + connect(d->ui->m_statementInfoPageCheckings->ui->m_statementDate, &KMyMoneyDateInput::dateChanged, this, &KEndingBalanceDlg::slotUpdateBalances); + connect(d->ui->m_interestChargeCheckings->ui->m_interestCategoryEdit, &KMyMoneyCombo::createItem, this, &KEndingBalanceDlg::slotCreateInterestCategory); + connect(d->ui->m_interestChargeCheckings->ui->m_chargesCategoryEdit, &KMyMoneyCombo::createItem, this, &KEndingBalanceDlg::slotCreateChargesCategory); + connect(d->ui->m_interestChargeCheckings->ui->m_payeeEdit, &KMyMoneyMVCCombo::createItem, this, &KEndingBalanceDlg::createPayee); - KMyMoneyMVCCombo::setSubstringSearchForChildren(m_interestChargeCheckings, !KMyMoneySettings::stringMatchFromStart()); + KMyMoneyMVCCombo::setSubstringSearchForChildren(d->ui->m_interestChargeCheckings, !KMyMoneySettings::stringMatchFromStart()); slotReloadEditWidgets(); // preset payee if possible try { // if we find a payee with the same name as the institution, // than this is what we use as payee. if (!d->m_account.institutionId().isEmpty()) { MyMoneyInstitution inst = MyMoneyFile::instance()->institution(d->m_account.institutionId()); MyMoneyPayee payee = MyMoneyFile::instance()->payeeByName(inst.name()); setField("payeeEdit", payee.id()); } } catch (const MyMoneyException &) { } KMyMoneyUtils::updateWizardButtons(this); // setup different text and icon on finish button setButtonText(QWizard::FinishButton, KStandardGuiItem::cont().text()); button(QWizard::FinishButton)->setIcon(KStandardGuiItem::cont().icon()); } KEndingBalanceDlg::~KEndingBalanceDlg() { + Q_D(KEndingBalanceDlg); delete d; } void KEndingBalanceDlg::slotUpdateBalances() { + Q_D(KEndingBalanceDlg); MYMONEYTRACER(tracer); // determine the beginning balance and ending balance based on the following // forumulas: // // end balance = current balance - sum(all non cleared transactions) // - sum(all cleared transactions posted // after statement date) // start balance = end balance - sum(all cleared transactions // up to statement date) MyMoneyTransactionFilter filter(d->m_account.id()); filter.addState((int)eMyMoney::TransactionFilter::State::NotReconciled); filter.setReportAllSplits(true); QList > transactionList; QList >::const_iterator it; // retrieve the list from the engine MyMoneyFile::instance()->transactionList(transactionList, filter); //first retrieve the oldest not reconciled transaction QDate oldestTransactionDate; it = transactionList.constBegin(); if (it != transactionList.constEnd()) { oldestTransactionDate = (*it).first.postDate(); - m_statementInfoPageCheckings->m_oldestTransactionDate->setText(i18n("Oldest unmarked transaction: %1", QLocale().toString(oldestTransactionDate))); + d->ui->m_statementInfoPageCheckings->ui->m_oldestTransactionDate->setText(i18n("Oldest unmarked transaction: %1", QLocale().toString(oldestTransactionDate))); } filter.addState((int)eMyMoney::TransactionFilter::State::Cleared); // retrieve the list from the engine to calculate the starting and ending balance MyMoneyFile::instance()->transactionList(transactionList, filter); MyMoneyMoney balance = MyMoneyFile::instance()->balance(d->m_account.id()); MyMoneyMoney factor(1, 1); if (d->m_account.accountGroup() == eMyMoney::Account::Liability) factor = -factor; MyMoneyMoney endBalance, startBalance; balance = balance * factor; endBalance = startBalance = balance; tracer.printf("total balance = %s", qPrintable(endBalance.formatMoney(QString(), 2))); for (it = transactionList.constBegin(); it != transactionList.constEnd(); ++it) { const MyMoneySplit& split = (*it).second; balance -= split.shares() * factor; if ((*it).first.postDate() > field("statementDate").toDate()) { tracer.printf("Reducing balances by %s because postdate of %s/%s(%s) is past statement date", qPrintable((split.shares() * factor).formatMoney(QString(), 2)), qPrintable((*it).first.id()), qPrintable(split.id()), qPrintable((*it).first.postDate().toString(Qt::ISODate))); endBalance -= split.shares() * factor; startBalance -= split.shares() * factor; } else { switch (split.reconcileFlag()) { case eMyMoney::Split::State::NotReconciled: tracer.printf("Reducing balances by %s because %s/%s(%s) is not reconciled", qPrintable((split.shares() * factor).formatMoney(QString(), 2)), qPrintable((*it).first.id()), qPrintable(split.id()), qPrintable((*it).first.postDate().toString(Qt::ISODate))); endBalance -= split.shares() * factor; startBalance -= split.shares() * factor; break; case eMyMoney::Split::State::Cleared: tracer.printf("Reducing start balance by %s because %s/%s(%s) is cleared", qPrintable((split.shares() * factor).formatMoney(QString(), 2)), qPrintable((*it).first.id()), qPrintable(split.id()), qPrintable((*it).first.postDate().toString(Qt::ISODate))); startBalance -= split.shares() * factor; break; default: break; } } } //FIXME: port - m_statementInfoPageCheckings->m_previousBalance->setValue(startBalance); - m_statementInfoPageCheckings->m_endingBalance->setValue(endBalance); + d->ui->m_statementInfoPageCheckings->ui->m_previousBalance->setValue(startBalance); + d->ui->m_statementInfoPageCheckings->ui->m_endingBalance->setValue(endBalance); tracer.printf("total balance = %s", qPrintable(endBalance.formatMoney(QString(), 2))); tracer.printf("start balance = %s", qPrintable(startBalance.formatMoney(QString(), 2))); setField("interestDateEdit", field("statementDate").toDate()); setField("chargesDateEdit", field("statementDate").toDate()); } void KEndingBalanceDlg::accept() { + Q_D(KEndingBalanceDlg); if ((!field("interestEditValid").toBool() || createTransaction(d->m_tInterest, -1, field("interestEdit").value(), field("interestCategoryEdit").toString(), field("interestDateEdit").toDate())) && (!field("chargesEditValid").toBool() || createTransaction(d->m_tCharges, 1, field("chargesEdit").value(), field("chargesCategoryEdit").toString(), field("chargesDateEdit").toDate()))) - KEndingBalanceDlgDecl::accept(); + QWizard::accept(); } void KEndingBalanceDlg::slotCreateInterestCategory(const QString& txt, QString& id) { createCategory(txt, id, MyMoneyFile::instance()->income()); } void KEndingBalanceDlg::slotCreateChargesCategory(const QString& txt, QString& id) { createCategory(txt, id, MyMoneyFile::instance()->expense()); } void KEndingBalanceDlg::createCategory(const QString& txt, QString& id, const MyMoneyAccount& parent) { MyMoneyAccount acc; acc.setName(txt); emit createCategory(acc, parent); id = acc.id(); } -const MyMoneyMoney KEndingBalanceDlg::endingBalance() const +MyMoneyMoney KEndingBalanceDlg::endingBalance() const +{ + Q_D(const KEndingBalanceDlg); + return adjustedReturnValue(d->ui->m_statementInfoPageCheckings->ui->m_endingBalance->value()); +} + +MyMoneyMoney KEndingBalanceDlg::previousBalance() const { - return adjustedReturnValue(m_statementInfoPageCheckings->m_endingBalance->value()); + Q_D(const KEndingBalanceDlg); + return adjustedReturnValue(d->ui->m_statementInfoPageCheckings->ui->m_previousBalance->value()); } -const MyMoneyMoney KEndingBalanceDlg::previousBalance() const +QDate KEndingBalanceDlg::statementDate() const { - return adjustedReturnValue(m_statementInfoPageCheckings->m_previousBalance->value()); + return field("statementDate").toDate(); } -const MyMoneyMoney KEndingBalanceDlg::adjustedReturnValue(const MyMoneyMoney& v) const +MyMoneyMoney KEndingBalanceDlg::adjustedReturnValue(const MyMoneyMoney& v) const { + Q_D(const KEndingBalanceDlg); return d->m_account.accountGroup() == eMyMoney::Account::Liability ? -v : v; } void KEndingBalanceDlg::slotReloadEditWidgets() { + Q_D(KEndingBalanceDlg); QString payeeId, interestId, chargesId; // keep current selected items payeeId = field("payeeEdit").toString(); interestId = field("interestCategoryEdit").toString(); chargesId = field("chargesCategoryEdit").toString(); // load the payee and category widgets with data from the engine //FIXME: port - m_interestChargeCheckings->m_payeeEdit->loadPayees(MyMoneyFile::instance()->payeeList()); + d->ui->m_interestChargeCheckings->ui->m_payeeEdit->loadPayees(MyMoneyFile::instance()->payeeList()); // a user request to show all categories in both selectors due to a valid use case. AccountSet aSet; aSet.addAccountGroup(eMyMoney::Account::Expense); aSet.addAccountGroup(eMyMoney::Account::Income); //FIXME: port - aSet.load(m_interestChargeCheckings->m_interestCategoryEdit->selector()); - aSet.load(m_interestChargeCheckings->m_chargesCategoryEdit->selector()); + aSet.load(d->ui->m_interestChargeCheckings->ui->m_interestCategoryEdit->selector()); + aSet.load(d->ui->m_interestChargeCheckings->ui->m_chargesCategoryEdit->selector()); // reselect currently selected items if (!payeeId.isEmpty()) setField("payeeEdit", payeeId); if (!interestId.isEmpty()) setField("interestCategoryEdit", interestId); if (!chargesId.isEmpty()) setField("chargesCategoryEdit", chargesId); } -const MyMoneyTransaction KEndingBalanceDlg::interestTransaction() +MyMoneyTransaction KEndingBalanceDlg::interestTransaction() { + Q_D(KEndingBalanceDlg); return d->m_tInterest; } -const MyMoneyTransaction KEndingBalanceDlg::chargeTransaction() +MyMoneyTransaction KEndingBalanceDlg::chargeTransaction() { + Q_D(KEndingBalanceDlg); return d->m_tCharges; } bool KEndingBalanceDlg::createTransaction(MyMoneyTransaction &t, const int sign, const MyMoneyMoney& amount, const QString& category, const QDate& date) { + Q_D(KEndingBalanceDlg); t = MyMoneyTransaction(); if (category.isEmpty() || !date.isValid()) return true; MyMoneySplit s1, s2; MyMoneyMoney val = amount * MyMoneyMoney(sign, 1); try { t.setPostDate(date); t.setCommodity(d->m_account.currencyId()); s1.setPayeeId(field("payeeEdit").toString()); s1.setReconcileFlag(eMyMoney::Split::State::Cleared); s1.setAccountId(d->m_account.id()); s1.setValue(-val); s1.setShares(-val); s2 = s1; s2.setAccountId(category); s2.setValue(val); t.addSplit(s1); t.addSplit(s2); QMap priceInfo; // just empty MyMoneyMoney shares; if (!KCurrencyCalculator::setupSplitPrice(shares, t, s2, priceInfo, this)) { t = MyMoneyTransaction(); return false; } s2.setShares(shares); t.modifySplit(s2); } catch (const MyMoneyException &e) { qDebug("%s", qPrintable(e.what())); t = MyMoneyTransaction(); return false; } return true; } void KEndingBalanceDlg::help() { + Q_D(KEndingBalanceDlg); QString anchor = d->m_helpAnchor[currentPage()]; if (anchor.isEmpty()) anchor = QString("details.reconcile.whatis"); KHelpClient::invokeHelp(anchor); } int KEndingBalanceDlg::nextId() const { + Q_D(const KEndingBalanceDlg); // Starting from the current page, look for the first enabled page // and return that value // If the end of the list is encountered first, then return -1. for (int i = currentId() + 1; i < d->m_pages.size() && i < pageIds().size(); ++i) { if (d->m_pages.testBit(i)) return pageIds()[i]; } return -1; } diff --git a/kmymoney/wizards/endingbalancedlg/kendingbalancedlg.h b/kmymoney/wizards/endingbalancedlg/kendingbalancedlg.h index cfb39d841..c04d5561d 100644 --- a/kmymoney/wizards/endingbalancedlg/kendingbalancedlg.h +++ b/kmymoney/wizards/endingbalancedlg/kendingbalancedlg.h @@ -1,114 +1,104 @@ /*************************************************************************** kendingbalancedlg.h ------------------- copyright : (C) 2000 by Michael Edwardes email : mte@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KENDINGBALANCEDLG_H #define KENDINGBALANCEDLG_H // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "ui_kendingbalancedlgdecl.h" - -#include "mymoneyaccount.h" - class QDate; +class MyMoneyMoney; class MyMoneyAccount; class MyMoneyTransaction; /** * This dialog is wizard based and used to enter additional * information required to start the reconciliation process. * This version implements the behaviour for checkings, * savings and credit card accounts. * * @author Thomas Baumgart */ -class KEndingBalanceDlgDecl : public QWizard, public Ui::KEndingBalanceDlgDecl -{ -public: - KEndingBalanceDlgDecl(QWidget *parent) : QWizard(parent) { - setupUi(this); - } -}; -class KEndingBalanceDlg : public KEndingBalanceDlgDecl + +class KEndingBalanceDlgPrivate; +class KEndingBalanceDlg : public QWizard { Q_OBJECT + Q_DISABLE_COPY(KEndingBalanceDlg) + public: enum { Page_CheckingStart, Page_PreviousPostpone, Page_CheckingStatementInfo, Page_InterestChargeCheckings }; - explicit KEndingBalanceDlg(const MyMoneyAccount& account, QWidget *parent = 0); + explicit KEndingBalanceDlg(const MyMoneyAccount& account, QWidget *parent = nullptr); ~KEndingBalanceDlg(); - const MyMoneyMoney endingBalance() const; - const MyMoneyMoney previousBalance() const; - const QDate statementDate() const { - return field("statementDate").toDate(); - }; + MyMoneyMoney endingBalance() const; + MyMoneyMoney previousBalance() const; + QDate statementDate() const; - const MyMoneyTransaction interestTransaction(); - const MyMoneyTransaction chargeTransaction(); + MyMoneyTransaction interestTransaction(); + MyMoneyTransaction chargeTransaction(); /** * This method returns the id of the next page in the wizard. * It is overloaded here to support the dynamic nature of this wizard. * * @return id of the next page or -1 if there is no next page */ int nextId() const; protected: bool createTransaction(MyMoneyTransaction& t, const int sign, const MyMoneyMoney& amount, const QString& category, const QDate& date); - const MyMoneyMoney adjustedReturnValue(const MyMoneyMoney& v) const; + MyMoneyMoney adjustedReturnValue(const MyMoneyMoney& v) const; void createCategory(const QString& txt, QString& id, const MyMoneyAccount& parent); protected slots: void slotReloadEditWidgets(); void help(); void slotCreateInterestCategory(const QString& txt, QString& id); void slotCreateChargesCategory(const QString& txt, QString& id); void accept(); void slotUpdateBalances(); signals: /** * proxy signal for KMyMoneyPayeeCombo::createItem(const QString&, QString&) */ void createPayee(const QString&, QString&); /** * emit when a category is about to be created */ void createCategory(MyMoneyAccount& acc, const MyMoneyAccount& parent); private: - /// \internal d-pointer class. - class Private; - /// \internal d-pointer instance. - Private* const d; + KEndingBalanceDlgPrivate * const d_ptr; + Q_DECLARE_PRIVATE(KEndingBalanceDlg) }; #endif diff --git a/kmymoney/wizards/endingbalancedlg/kendingbalancedlgdecl.ui b/kmymoney/wizards/endingbalancedlg/kendingbalancedlg.ui similarity index 94% rename from kmymoney/wizards/endingbalancedlg/kendingbalancedlgdecl.ui rename to kmymoney/wizards/endingbalancedlg/kendingbalancedlg.ui index ed7675402..c1fd90980 100644 --- a/kmymoney/wizards/endingbalancedlg/kendingbalancedlgdecl.ui +++ b/kmymoney/wizards/endingbalancedlg/kendingbalancedlg.ui @@ -1,61 +1,61 @@ - KEndingBalanceDlgDecl - + KEndingBalanceDlg + 0 0 589 465 Reconciliation Wizard KComboBox QComboBox
kcombobox.h
KMyMoneyDateInput QFrame
kmymoneydateinput.h
KMyMoneyCategory KComboBox
kmymoneycategory.h
KMyMoneyEdit QFrame
kmymoneyedit.h
KMyMoneyPayeeCombo KComboBox
kmymoneypayeecombo.h
1
KMyMoneyAccountSelector QWidget
kmymoneyaccountselector.h
diff --git a/kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.cpp b/kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.cpp index 2974aeb18..bfb3d34cb 100644 --- a/kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.cpp +++ b/kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.cpp @@ -1,39 +1,44 @@ /*************************************************************************** previouspostponewizardpage.cpp - description ------------------- begin : Sun Jul 18 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "previouspostponewizardpage.h" // ---------------------------------------------------------------------------- // QT Includes - // ---------------------------------------------------------------------------- // KDE Includes - // ---------------------------------------------------------------------------- // Project Includes +#include "ui_previouspostponewizardpage.h" -PreviousPostponeWizardPage::PreviousPostponeWizardPage(QWidget *parent) - : PreviousPostponeWizardPageDecl(parent) +PreviousPostponeWizardPage::PreviousPostponeWizardPage(QWidget *parent) : + QWizardPage(parent), + ui(new Ui::PreviousPostponeWizardPage) { - + ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly } + +PreviousPostponeWizardPage::~PreviousPostponeWizardPage() +{ + delete ui; +} diff --git a/kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.h b/kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.h index a22585d45..0658cda11 100644 --- a/kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.h +++ b/kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.h @@ -1,54 +1,51 @@ /*************************************************************************** previouspostponewizardpage.h - description ------------------- begin : Sun Jul 18 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef PREVIOUSPOSTPONEWIZARDPAGE_H #define PREVIOUSPOSTPONEWIZARDPAGE_H // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "ui_previouspostponewizardpagedecl.h" +namespace Ui { class PreviousPostponeWizardPage; } /** * This class implements the PreviousPostpone page of the * @ref KEndingBalanceDlg wizard. */ -class PreviousPostponeWizardPageDecl : public QWizardPage, public Ui::PreviousPostponeWizardPageDecl -{ -public: - PreviousPostponeWizardPageDecl(QWidget *parent) : QWizardPage(parent) { - setupUi(this); - } -}; -class PreviousPostponeWizardPage : public PreviousPostponeWizardPageDecl +class PreviousPostponeWizardPage : public QWizardPage { Q_OBJECT + Q_DISABLE_COPY(PreviousPostponeWizardPage) + public: - explicit PreviousPostponeWizardPage(QWidget *parent = 0); + explicit PreviousPostponeWizardPage(QWidget *parent = nullptr); + ~PreviousPostponeWizardPage(); + Ui::PreviousPostponeWizardPage *ui; }; #endif diff --git a/kmymoney/wizards/endingbalancedlg/previouspostponewizardpagedecl.ui b/kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.ui similarity index 92% rename from kmymoney/wizards/endingbalancedlg/previouspostponewizardpagedecl.ui rename to kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.ui index d75c7466a..2dcda233a 100644 --- a/kmymoney/wizards/endingbalancedlg/previouspostponewizardpagedecl.ui +++ b/kmymoney/wizards/endingbalancedlg/previouspostponewizardpage.ui @@ -1,50 +1,50 @@ - PreviousPostponeWizardPageDecl - + PreviousPostponeWizardPage + 6 34 577 388 Restarting postponed reconciliation 6 11 You have previously postponed the reconciliation of this account. If you have entered charges or interests the last time you started reconciling this account you can modify these in the ledger later on. It is important, that you continue with the same statement you used when you postponed the reconciliation. All information you have entered into this wizard will be shown and all transactions that you already cleared are marked with a 'C'. Qt::AlignTop true diff --git a/kmymoney/wizards/kmymoneywizard.cpp b/kmymoney/wizards/kmymoneywizard.cpp new file mode 100644 index 000000000..9b8a8131b --- /dev/null +++ b/kmymoney/wizards/kmymoneywizard.cpp @@ -0,0 +1,176 @@ +/*************************************************************************** + kmymoneywizard.cpp + ------------------- + copyright : (C) 2006 by Thomas Baumagrt + email : ipwizard@users.sourceforge.net + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kmymoneywizard.h" +#include "kmymoneywizard_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "kmymoneywizardpage.h" +#include "kmymoneytitlelabel.h" + + +KMyMoneyWizard::KMyMoneyWizard(QWidget *parent, bool modal, Qt::WindowFlags f) : + QDialog(parent, f), + d_ptr(new KMyMoneyWizardPrivate(this)) +{ + Q_D(KMyMoneyWizard); + d->init(modal); +} + +KMyMoneyWizard::KMyMoneyWizard(KMyMoneyWizardPrivate &dd, QWidget* parent, bool modal, Qt::WindowFlags f) : + QDialog(parent, f), + d_ptr(&dd) +{ + Q_D(KMyMoneyWizard); + d->init(modal); +} + +KMyMoneyWizard::~KMyMoneyWizard() +{ + Q_D(KMyMoneyWizard); + delete d; +} + +void KMyMoneyWizard::setTitle(const QString& txt) +{ + Q_D(KMyMoneyWizard); + d->m_titleLabel->setText(txt); +} + +void KMyMoneyWizard::addStep(const QString& text) +{ + Q_D(KMyMoneyWizard); + QLabel* step = new QLabel(text, d->m_stepFrame); + step->setFrameStyle(QFrame::Panel | QFrame::Raised); + step->setAlignment(Qt::AlignHCenter); + step->setFrameStyle(QFrame::Box | QFrame::Sunken); + step->setMargin(2); + step->setPalette(d->m_stepPalette); + + d->m_steps.append(step); + d->m_stepLayout->insertWidget(d->m_steps.count(), step); + + QFont font(step->font()); + font.setBold(true); + QFontMetrics fm(font); + int w = fm.width(text) + 30; + if (d->m_stepFrame->minimumWidth() < w) { + d->m_stepFrame->setMinimumWidth(w); + } +} + +QList KMyMoneyWizard::historyPages() const +{ + Q_D(const KMyMoneyWizard); + return d->m_history; +} + +void KMyMoneyWizard::reselectStep() +{ + Q_D(KMyMoneyWizard); + d->selectStep(d->m_step); +} + +void KMyMoneyWizard::setHelpContext(const QString& ctx) +{ + Q_D(KMyMoneyWizard); + d->m_helpContext = ctx; +} + +void KMyMoneyWizard::backButtonClicked() +{ + Q_D(KMyMoneyWizard); + KMyMoneyWizardPage* oldPage = d->m_history.back(); + d->m_history.pop_back(); + oldPage->leavePage(); + oldPage->resetPage(); + d->switchPage(oldPage); +} + +void KMyMoneyWizard::nextButtonClicked() +{ + Q_D(KMyMoneyWizard); + // make sure it is really complete. Some widgets only change state during focusOutEvent, + // so we just create such an animal by changing the focus to the next button and + // check again for copmpleness + d->m_nextButton->setFocus(); + KMyMoneyWizardPage* oldPage = d->m_history.back(); + if (oldPage->isComplete()) { + KMyMoneyWizardPage* newPage = oldPage->nextPage(); + d->m_history.append(newPage); + newPage->enterPage(); + newPage->resetPage(); + d->switchPage(oldPage); + } +} + +void KMyMoneyWizard::helpButtonClicked() +{ + Q_D(KMyMoneyWizard); + KMyMoneyWizardPage* currentPage = d->m_history.back(); + QString ctx = currentPage->helpContext(); + if (ctx.isEmpty()) + ctx = d->m_helpContext; + KHelpClient::invokeHelp(ctx); +} + +void KMyMoneyWizard::completeStateChanged() +{ + Q_D(KMyMoneyWizard); + KMyMoneyWizardPage* currentPage = d->m_history.back(); + bool lastPage = currentPage->isLastPage(); + + d->m_finishButton->setVisible(lastPage); + d->m_nextButton->setVisible(!lastPage); + + QPushButton* button; + + button = lastPage ? d->m_finishButton : d->m_nextButton; + + auto rc = currentPage->isComplete(); + button->setEnabled(rc); + + d->m_backButton->setEnabled(d->m_history.count() > 1); +} + +void KMyMoneyWizard::accept() +{ + Q_D(KMyMoneyWizard); + // make sure it is really complete. Some widgets only change state during focusOutEvent, + // so we just create such an animal by changing the focus to the finish button and + // check again for completeness. + d->m_finishButton->setFocus(); + KMyMoneyWizardPage* page = d->m_history.back(); + if (page->isComplete()) + QDialog::accept(); +} diff --git a/kmymoney/widgets/kmymoneywizard.h b/kmymoney/wizards/kmymoneywizard.h similarity index 79% rename from kmymoney/widgets/kmymoneywizard.h rename to kmymoney/wizards/kmymoneywizard.h index 4d5e9519f..fad26b965 100644 --- a/kmymoney/widgets/kmymoneywizard.h +++ b/kmymoney/wizards/kmymoneywizard.h @@ -1,297 +1,219 @@ /*************************************************************************** kmymoneywizard.h ------------------- copyright : (C) 2006 by Thomas Baumagrt email : ipwizard@users.sourceforge.net (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KMYMONEYWIZARD_H #define KMYMONEYWIZARD_H // ---------------------------------------------------------------------------- // QT Includes #include -#include -#include -class QVBoxLayout; -class QHBoxLayout; -class QLabel; -class QFrame; // ---------------------------------------------------------------------------- // KDE Includes -class QPushButton; - // ---------------------------------------------------------------------------- // Project Includes -class KMyMoneyTitleLabel; class KMyMoneyWizardPage; +template class QList; + /** * @author Thomas Baumgart (C) 2006 * * This is a base class for implementation of the KMyMoneyWizard. It provides * the following layout of a wizard: * * @code * +-wizardLayout-----------------------------------------------+ * | | * +------------------------------------------------------------+ * |+-stepLayout--++-------------------------------------------+| * || ||+-pageLayout------------------------------+|| * || ||| ||| * || ||| ||| * || ||| ||| * || ||| ||| * || ||| ||| * || ||| ||| * || ||+-----------------------------------------+|| * || |||+-buttonLayout--------------------------+||| * || |||| |||| * || |||+---------------------------------------+||| * || ||+-----------------------------------------+|| * |+-------------++-------------------------------------------+| * +------------------------------------------------------------+ * @endcode * * The top bar is filled with a KMyMoneyTitleLabel as known from * KMyMoney's views. To the left there is an area in the same color * as the title bar showing the steps for this wizard. Each such step * can consist of one or more wizard pages. At the bottom of this area * the text "Step x of y" is shown and updated. To the right of this * part, the actual wizard page is shown. At the bottom of the page * the class inserts a standard button widget consisting of a Help, * Back, Next/Finish and Cancel button. * * The wizard serves as container for the wizard pages. In order to access * the data filled into the pages, one would have to provide getter methods. * * Here is an example how this object could be used. Please also see the * example described with the KMyMoneyWizardPage class. * * @code * * class KNewUserGeneral; * class KNewUserPersonal; * * class KNewUserWizard : public KMyMoneyWizard * { * Q_OBJECT * public: * KNewUserWizard(QWidget* parent = nullptr, const char* name = 0, bool modal = false, Qt::WindowFlags flags = 0); * * private: * KNewUserGeneral* m_generalPage; * KNewUserPersonal* m_personalPage; * KNewUserFinal* m_finalPage; * // add more pages here * * friend class KNewUserGeneral; * friend class KNewUserPersonal; * friend class KNewUserFinal; * // add more pages here * }; * @endcode * * The implementation is also easy and looks like this: * * @code * KNewUserWizard::KNewUserWizard(QWidget* parent, const char* name, bool modal, Qt::WindowFlags flags) : * KMyMoneyWizard(parent, name, modal, flags) * { * setTitle("KMyMoney New User Setup"); * addStep("General Data"); * addStep("Personal Data"); * addStep("Finish"); * * m_generalPage = new KNewUserGeneral(this); * m_personalPage = new KNewUserPersonal(this); * m_finalPage = new KNewUserFinal(this); * * setFirstPage(m_testPage1); * } * @endcode * * Don't forget to call setFirstPage() to get things started. * * The code to use this whole structure would then look something like this: * * @code * KNewUserWizard* wizard = new KNewUserWizard(this, "NewUserWizard"); * int rc = wizard->exec(); * @endcode * * The return code of exec() is either @p QDialog::Accepted or * @p QDialog::Rejected. * * @note The implementation of this class is heavily based on ideas found at * http://doc.trolltech.com/4.1/dialogs-complexwizard.html */ +class KMyMoneyWizardPrivate; class KMyMoneyWizard : public QDialog { friend class KMyMoneyWizardPage; Q_OBJECT Q_DISABLE_COPY(KMyMoneyWizard) public: /** * Modify the title of the wizard to be @p txt. * * @param txt The text that should be used as title */ void setTitle(const QString& txt); /** * Add step @p text to the wizard * * @param text Text to be shown for this step */ void addStep(const QString& text); QList historyPages() const; /** * This method repeats selection of the current step in the * step frame. * This is used to allow changes made to showing and hiding * pages to immediately to be reflected in the step frame */ void reselectStep(); /** * Setup a global help context for the wizard. It will be used whenever * there is no specific help context available for the current page. * * @sa KMyMoneyWizardPage::helpContext() */ void setHelpContext(const QString& ctx); virtual ~KMyMoneyWizard(); signals: /** * This signal is sent out, when a new payee needs to be created * @sa KMyMoneyCombo::createItem() * * @param txt The name of the payee to be created * @param id A connected slot should store the id of the created object in this variable */ void createPayee(const QString& txt, QString& id); /** * This signal is sent out, when a new category needs to be created * @sa KMyMoneyCombo::createItem() * * @param txt The name of the category to be created * @param id A connected slot should store the id of the created object in this variable */ void createCategory(const QString& txt, QString& id); protected: + KMyMoneyWizardPrivate * const d_ptr; + KMyMoneyWizard(KMyMoneyWizardPrivate &dd, QWidget* parent = nullptr, bool modal = false, Qt::WindowFlags f = 0); /** * Constructor (kept protected, so that one cannot create such an object directly) */ explicit KMyMoneyWizard(QWidget* parent = nullptr, bool modal = false, Qt::WindowFlags f = 0); - /** - * This method sets up the first page after creation of the object - * - * @param page pointer to first page of wizard - */ - void setFirstPage(KMyMoneyWizardPage* page); - - /** - * This method allows to hide or show a @p step. - * - * @param step step to be shown/hidden - * @param hidden hide step if true (the default) or show it if false - */ - void setStepHidden(int step, bool hidden = true); - protected slots: - virtual void accept(); + void accept() override; void completeStateChanged(); -private: - void updateStepCount(); - private slots: void backButtonClicked(); void nextButtonClicked(); void helpButtonClicked(); -protected: - /* - * The buttons - */ - QPushButton* m_cancelButton; - QPushButton* m_backButton; - QPushButton* m_nextButton; - QPushButton* m_finishButton; - QPushButton* m_helpButton; - private: - /** - * Switch to page which is currently the top of the history stack. - * @p oldPage is a pointer to the current page or 0 if no page - * is shown. - * - * @param oldPage pointer to currently displayed page - */ - void switchPage(KMyMoneyWizardPage* oldPage); - - /** - * This method selects the step given by @p step. - * - * @param step step to be selected - */ - void selectStep(int step); - - /* - * The layouts - */ - QVBoxLayout* m_wizardLayout; - QVBoxLayout* m_stepLayout; - QVBoxLayout* m_pageLayout; - QHBoxLayout* m_buttonLayout; - - /* - * Some misc. widgets required - */ - QFrame* m_stepFrame; - QLabel* m_stepLabel; - QPalette m_stepPalette; - - QList m_steps; // the list of step labels - int m_step; // the currently selected step - - /* - * The title bar - */ - KMyMoneyTitleLabel* m_titleLabel; - - /* - * The history stack - */ - QList m_history; - - QString m_helpContext; + Q_DECLARE_PRIVATE(KMyMoneyWizard) }; - - #endif diff --git a/kmymoney/wizards/kmymoneywizard_p.h b/kmymoney/wizards/kmymoneywizard_p.h new file mode 100644 index 000000000..a4bcc45dd --- /dev/null +++ b/kmymoney/wizards/kmymoneywizard_p.h @@ -0,0 +1,320 @@ +/*************************************************************************** + kmymoneywizard_p.h + ------------------- + copyright : (C) 2006 by Thomas Baumagrt + email : ipwizard@users.sourceforge.net + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KMYMONEYWIZARD_P_H +#define KMYMONEYWIZARD_P_H + +#include "kmymoneywizard.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "kmymoneywizardpage.h" +#include "kmymoneywizardpage_p.h" +#include "kmymoneytitlelabel.h" +#include "icons/icons.h" + +using namespace Icons; + +class KMyMoneyWizardPrivate +{ + Q_DISABLE_COPY(KMyMoneyWizardPrivate) + Q_DECLARE_PUBLIC(KMyMoneyWizard) + +public: + KMyMoneyWizardPrivate(KMyMoneyWizard *qq) : + q_ptr(qq), + m_step(0) + { + } + + virtual ~KMyMoneyWizardPrivate() + { + } + + void init(bool modal) + { + Q_Q(KMyMoneyWizard); + q->setModal(modal); + + // enable the little grip in the right corner + q->setSizeGripEnabled(true); + + // create buttons + m_cancelButton = new QPushButton(i18n("&Cancel"), q); + m_backButton = new QPushButton(i18nc("Go to previous page of the wizard", "&Back"), q); + m_nextButton = new QPushButton(i18nc("Go to next page of the wizard", "&Next"), q); + m_finishButton = new QPushButton(i18nc("Finish the wizard", "&Finish"), q); + m_helpButton = new QPushButton(i18n("&Help"), q); + + if (q->style()->styleHint(QStyle::SH_DialogButtonBox_ButtonsHaveIcons, 0, q)) { + m_backButton->setIcon(KStandardGuiItem::back(KStandardGuiItem::UseRTL).icon()); + m_nextButton->setIcon(KStandardGuiItem::forward(KStandardGuiItem::UseRTL).icon()); + m_finishButton->setIcon(QIcon::fromTheme(g_Icons[Icon::DialogOKApply])); + m_cancelButton->setIcon(QIcon::fromTheme(g_Icons[Icon::DialogCancel])); + m_helpButton->setIcon(QIcon::fromTheme(g_Icons[Icon::HelpContents])); + } + + // create button layout + m_buttonLayout = new QHBoxLayout; + m_buttonLayout->addWidget(m_helpButton); + m_buttonLayout->addStretch(1); + m_buttonLayout->addWidget(m_backButton); + m_buttonLayout->addWidget(m_nextButton); + m_buttonLayout->addWidget(m_finishButton); + m_buttonLayout->addWidget(m_cancelButton); + + // create wizard layout + m_wizardLayout = new QVBoxLayout(q); + m_wizardLayout->setContentsMargins(6, 6, 6, 6); + m_wizardLayout->setSpacing(0); + m_wizardLayout->setObjectName("wizardLayout"); + m_titleLabel = new KMyMoneyTitleLabel(q); + m_titleLabel->setObjectName("titleLabel"); + m_wizardLayout->addWidget(m_titleLabel); + + QHBoxLayout* hboxLayout = new QHBoxLayout; + hboxLayout->setContentsMargins(0, 0, 0, 0); + hboxLayout->setSpacing(6); + hboxLayout->setObjectName("hboxLayout"); + + // create stage layout and frame + m_stepFrame = new QFrame(q); + m_stepFrame->setObjectName("stepFrame"); + QPalette palette = m_stepFrame->palette(); + palette.setColor(m_stepFrame->backgroundRole(), KColorScheme::NormalText); + m_stepFrame->setPalette(palette); + m_stepLayout = new QVBoxLayout(m_stepFrame); + m_stepLayout->setContentsMargins(11, 11, 11, 11); + m_stepLayout->setSpacing(6); + m_stepLayout->setObjectName("stepLayout"); + m_stepLayout->addWidget(new QLabel(QString(), m_stepFrame)); + m_stepLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding)); + m_stepLabel = new QLabel(m_stepFrame); + m_stepLabel->setAlignment(Qt::AlignHCenter); + m_stepLayout->addWidget(m_stepLabel); + hboxLayout->addWidget(m_stepFrame); + + m_stepPalette = m_stepLabel->palette(); + + // add a vertical line between the stepFrame and the pages + QFrame* line = new QFrame(q); + line->setObjectName("line"); + line->setFrameShadow(QFrame::Sunken); + line->setFrameShape(QFrame::VLine); + hboxLayout->addWidget(line); + + // create page layout + m_pageLayout = new QVBoxLayout; + m_pageLayout->setContentsMargins(0, 0, 0, 0); + m_pageLayout->setSpacing(6); + m_pageLayout->setObjectName("pageLayout"); + + // the page will be inserted later dynamically above q line + line = new QFrame(q); + line->setObjectName("line"); + line->setFrameShadow(QFrame::Sunken); + line->setFrameShape(QFrame::HLine); + m_pageLayout->addWidget(line); + m_pageLayout->addLayout(m_buttonLayout); + + // now glue everything together + hboxLayout->addLayout(m_pageLayout); + m_wizardLayout->addLayout(hboxLayout); + + q->resize(QSize(670, 550).expandedTo(q->minimumSizeHint())); + + m_titleLabel->setText(i18n("No Title specified")); + m_titleLabel->setRightImageFile("pics/titlelabel_background.png"); + + m_finishButton->hide(); + + q->connect(m_backButton, &QAbstractButton::clicked, q, &KMyMoneyWizard::backButtonClicked); + q->connect(m_nextButton, &QAbstractButton::clicked, q, &KMyMoneyWizard::nextButtonClicked); + q->connect(m_cancelButton, &QAbstractButton::clicked, q, &QDialog::reject); + q->connect(m_finishButton, &QAbstractButton::clicked, q, &KMyMoneyWizard::accept); + q->connect(m_helpButton, &QAbstractButton::clicked, q, &KMyMoneyWizard::helpButtonClicked); + } + + /** + * Switch to page which is currently the top of the history stack. + * @p oldPage is a pointer to the current page or 0 if no page + * is shown. + * + * @param oldPage pointer to currently displayed page + */ + void switchPage(KMyMoneyWizardPage* oldPage) + { + Q_Q(KMyMoneyWizard); + if (oldPage) { + oldPage->widget()->hide(); + m_pageLayout->removeWidget(oldPage->widget()); + q->disconnect(oldPage->object(), SIGNAL(completeStateChanged()), q, SLOT(completeStateChanged())); + } + KMyMoneyWizardPage* newPage = m_history.back(); + if (newPage) { + m_pageLayout->insertWidget(0, newPage->widget()); + q->connect(newPage->object(), SIGNAL(completeStateChanged()), q, SLOT(completeStateChanged())); + newPage->widget()->show(); + selectStep(newPage->step()); + if (newPage->isLastPage()) { + m_nextButton->setDefault(false); + m_finishButton->setDefault(true); + } else { + m_finishButton->setDefault(false); + m_nextButton->setDefault(true); + } + QWidget* w = newPage->initialFocusWidget(); + if (w) + w->setFocus(); + } + q->completeStateChanged(); + } + + /** + * This method selects the step given by @p step. + * + * @param step step to be selected + */ + void selectStep(int step) + { + Q_Q(KMyMoneyWizard); + if ((step < 1) || (step > m_steps.count())) + return; + + m_step = step; + QList::iterator it_l; + QFont f = m_steps[0]->font(); + for (it_l = m_steps.begin(); it_l != m_steps.end(); ++it_l) { + f.setBold(false); + (*it_l)->setFrameStyle(QFrame::NoFrame); + if (--step == 0) { + f.setBold(true); + (*it_l)->setFrameStyle(QFrame::Box | QFrame::Sunken); + } + (*it_l)->setFont(f); + } + updateStepCount(); + } + + /** + * This method sets up the first page after creation of the object + * + * @param page pointer to first page of wizard + */ + void setFirstPage(KMyMoneyWizardPage* page) + { + page->resetPage(); + m_history.clear(); + m_history.append(page); + switchPage(0); + } + + /** + * This method allows to hide or show a @p step. + * + * @param step step to be shown/hidden + * @param hidden hide step if true (the default) or show it if false + */ + void setStepHidden(int step, bool hidden = true) + { + Q_Q(KMyMoneyWizard); + if ((step < 1) || (step > m_steps.count())) + return; + + m_steps[--step]->setHidden(hidden); + updateStepCount(); + } + + void updateStepCount() + { + QList::iterator it_l; + int stepCount = 0; + int hiddenAdjust = 0; + int step = 0; + for (it_l = m_steps.begin(); it_l != m_steps.end(); ++it_l) { + if (!(*it_l)->isHidden()) + ++stepCount; + else if (step < m_step) + hiddenAdjust++; + ++step; + } + m_stepLabel->setText(i18n("Step %1 of %2", (m_step - hiddenAdjust), stepCount)); + } + + KMyMoneyWizard *q_ptr; + + /* + * The buttons + */ + QPushButton* m_cancelButton; + QPushButton* m_backButton; + QPushButton* m_nextButton; + QPushButton* m_finishButton; + QPushButton* m_helpButton; + + /* + * The layouts + */ + QVBoxLayout* m_wizardLayout; + QVBoxLayout* m_stepLayout; + QVBoxLayout* m_pageLayout; + QHBoxLayout* m_buttonLayout; + + /* + * Some misc. widgets required + */ + QFrame* m_stepFrame; + QLabel* m_stepLabel; + QPalette m_stepPalette; + + QList m_steps; // the list of step labels + int m_step; // the currently selected step + + /* + * The title bar + */ + KMyMoneyTitleLabel* m_titleLabel; + + /* + * The history stack + */ + QList m_history; + + QString m_helpContext; +}; + +#endif diff --git a/kmymoney/widgets/kmymoneywizardpage.cpp b/kmymoney/wizards/kmymoneywizardpage.cpp similarity index 60% rename from kmymoney/widgets/kmymoneywizardpage.cpp rename to kmymoney/wizards/kmymoneywizardpage.cpp index 9efe5f8e7..ee21175b2 100644 --- a/kmymoney/widgets/kmymoneywizardpage.cpp +++ b/kmymoney/wizards/kmymoneywizardpage.cpp @@ -1,121 +1,130 @@ /*************************************************************************** kmymoneywizardpage.cpp ------------------- copyright : (C) 2006 by Thomas Baumagrt email : ipwizard@users.sourceforge.net (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kmymoneywizardpage.h" +#include "kmymoneywizardpage_p.h" #include "kmymoneywizard_p.h" // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "kguiutils.h" #include "kmymoneywizard.h" -KMyMoneyWizardPagePrivate::KMyMoneyWizardPagePrivate(QObject* parent) : - QObject(parent) +KMyMoneyWizardPage::KMyMoneyWizardPage(uint step, QWidget* widget) : + d_ptr(new KMyMoneyWizardPagePrivate(widget)) { + Q_D(KMyMoneyWizardPage); + d->m_step = step; + d->m_widget = widget; + d->m_mandatoryGroup = new KMandatoryFieldGroup(widget); + QObject::connect(d->m_mandatoryGroup, static_cast(&KMandatoryFieldGroup::stateChanged), object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + widget->hide(); } -void KMyMoneyWizardPagePrivate::emitCompleteStateChanged() -{ - emit completeStateChanged(); -} - - -KMyMoneyWizardPage::KMyMoneyWizardPage(unsigned int step, QWidget* widget) : - m_step(step), - m_widget(widget), - d(new KMyMoneyWizardPagePrivate(widget)) +KMyMoneyWizardPage::KMyMoneyWizardPage(KMyMoneyWizardPagePrivate &dd, uint step, QWidget *widget) : + d_ptr(&dd) { - m_mandatoryGroup = new KMandatoryFieldGroup(widget); - QObject::connect(m_mandatoryGroup, SIGNAL(stateChanged()), object(), SIGNAL(completeStateChanged())); + Q_D(KMyMoneyWizardPage); + d->m_step = step; + d->m_widget = widget; + d->m_mandatoryGroup = new KMandatoryFieldGroup(widget); + QObject::connect(d->m_mandatoryGroup, static_cast(&KMandatoryFieldGroup::stateChanged), object(), &KMyMoneyWizardPagePrivate::completeStateChanged); widget->hide(); } KMyMoneyWizardPage::~KMyMoneyWizardPage() { + Q_D(KMyMoneyWizardPage); + delete d; } -QObject* KMyMoneyWizardPage::object() const +const KMyMoneyWizardPagePrivate* KMyMoneyWizardPage::object() const { + Q_D(const KMyMoneyWizardPage); return d; } QWidget* KMyMoneyWizardPage::initialFocusWidget() const { return nullptr; } -void KMyMoneyWizardPage::completeStateChanged() const +void KMyMoneyWizardPage::completeStateChanged() { + Q_D(KMyMoneyWizardPage); d->emitCompleteStateChanged(); } void KMyMoneyWizardPage::resetPage() { } void KMyMoneyWizardPage::enterPage() { } void KMyMoneyWizardPage::leavePage() { } KMyMoneyWizardPage* KMyMoneyWizardPage::nextPage() const { return 0; } bool KMyMoneyWizardPage::isLastPage() const { return nextPage() == 0; } bool KMyMoneyWizardPage::isComplete() const { + Q_D(const KMyMoneyWizardPage); if (!isLastPage()) - wizard()->m_nextButton->setToolTip(i18n("Continue with next page")); + wizard()->d_func()->m_nextButton->setToolTip(i18n("Continue with next page")); else - wizard()->m_finishButton->setToolTip(i18n("Finish wizard")); - return m_mandatoryGroup->isEnabled(); + wizard()->d_func()->m_finishButton->setToolTip(i18n("Finish wizard")); + return d->m_mandatoryGroup->isEnabled(); } unsigned int KMyMoneyWizardPage::step() const { - return m_step; + Q_D(const KMyMoneyWizardPage); + return d->m_step; } QWidget* KMyMoneyWizardPage::widget() const { - return m_widget; + Q_D(const KMyMoneyWizardPage); + return d->m_widget; } QString KMyMoneyWizardPage::helpContext() const { return QString(); } diff --git a/kmymoney/widgets/kmymoneywizardpage.h b/kmymoney/wizards/kmymoneywizardpage.h similarity index 89% rename from kmymoney/widgets/kmymoneywizardpage.h rename to kmymoney/wizards/kmymoneywizardpage.h index ae7dcdaf2..2d76230ec 100644 --- a/kmymoney/widgets/kmymoneywizardpage.h +++ b/kmymoney/wizards/kmymoneywizardpage.h @@ -1,289 +1,252 @@ /*************************************************************************** kmymoneywizardpage.h ------------------- copyright : (C) 2006 by Thomas Baumagrt email : ipwizard@users.sourceforge.net (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KMYMONEYWIZARDPAGE_H #define KMYMONEYWIZARDPAGE_H // ---------------------------------------------------------------------------- // QT Includes -#include -#include -#include -class QVBoxLayout; -class QHBoxLayout; -class QLabel; -class QFrame; +#include // ---------------------------------------------------------------------------- // KDE Includes -class QPushButton; - // ---------------------------------------------------------------------------- // Project Includes -class KMyMoneyTitleLabel; +class QString; +class QWidget; + class KMyMoneyWizard; -class KMyMoneyWizardPagePrivate; -class KMandatoryFieldGroup; /** * @author Thomas Baumgart (C) 2006 * * @note: the following documentation is somewhat outdated * as of May 2007. Wizards should use a namespace * for the pages and can use the WizardPage template class. * See the NewUserWizard class and NewUserWizardPages namespace * as an example of this setup. * * This class represents the base class for wizard pages for the * KMyMoneyWizard. One cannot create a wizard page directly, but * must derive from it. The KMyMoneyWizardPage class provides the * necessary functionality to work in concert with KMyMoneyWizard. * * Therefore, few steps are necessary to use this class. They seem to * be awkward at some stage, but I wanted to be able to use Qt designer * to actually design the widget for the page. That's why some things * aren't implemented in a more straight fashion than one would * normally do this. * * The first step is to derive a specific base page for the specific wizard. * In this example we use the name NewUser as template for the specific wizard. * This class provides a 'back'-pointer to the actual wizard object * for all pages. * * @code * class KNewUserPage : public KMyMoneyWizardPage * { * public: * KNewUserPage(unsigned int step, QWidget* widget, KNewUserWizard* parent, const char* name); * * protected: * KNewUserWizard* m_wizard; * } * @endcode * * The implementation of this class is rather straight-forward: * * @code * KNewUserPage::KNewUserPage(unsigned int step, QWidget* widget, KNewUserWizard* parent, const char* name) : * KMyMoneyWizardPage(step, widget, name), * m_wizard(parent) * { * } * @endcode * * For each page of the wizard, you will have to create a @p ui file with * Qt designer. * Let's assume we call the first page of the wizard 'General' and go * from there. * We also assume, that the wizard has more than one page. * The ui designer generated class should have the name KNewUserGeneral * as all other dialogs. The class definition of KNewUserGeneral will * look like this: * * @code * class KNewUserGeneral : public KNewUserGeneral, public KNewUserPage * { * Q_OBJECT * public: * KNewUserGeneral(KNewUserWizard* parent, const char* name = 0); * KMyMoneyWizardPage* nextPage(); * bool isLastPage() { return false; } * * protected: * KNewUserWizard* m_wizard; * } * @endcode * * The implementation depends heavily on the logic of your code. If you only * fill some widgets, it could be as simple as: * * @code * KNewUserGeneral::KNewUserGeneral(KNewUserWizard* parent, const char* name) : * KNewUserGeneral(parent), * KNewUserPage(1, this, parent, name) * { * KMandatoryFieldGroup* mandatoryGroup = new KMandatoryFieldGroup(this); * mandatoryGroup->add(m_userName); * connect(m_mandatoryGroup, SIGNAL(stateChanged()), object(), SIGNAL(completeStateChanged())); * } * * KMyMoneyWizardPage* KNewUserGeneral::nextPage() * { * return m_wizard->m_personalPage; * } * @endcode * * A note on the first parameter to KNewUserPage in the above example: it ties * this page to be part of step 1 (see KMyMoneyWizard::addStep() for details). * * Depending on the actual logic of the page, you would want to override the * following methods: resetPage, nextPage, isLastPage and isComplete. * * @note The implementation of this class is heavily based on ideas found at * http://doc.trolltech.com/4.1/dialogs-complexwizard.html */ +class KMyMoneyWizardPagePrivate; class KMyMoneyWizardPage { public: /** * This method is called by the wizard when the page is entered from * the previous page. The default implementation does nothing. */ virtual void enterPage(); /** * This method is called by the wizard when the page is left to return to * the previous page. The default implementation does nothing. */ virtual void leavePage(); /** * This method is called by the wizard whenever a page is entered * (either in forward or backward direction). The default * implementation does nothing. */ virtual void resetPage(); /** * This method returns a pointer to the next page that should be * shown when the user presses the 'Next' button. * * @return pointer to next wizard page */ virtual KMyMoneyWizardPage* nextPage() const; /** * This returns, if the current page is the last page of the wizard. * The default implementation returns @p false if nextPage() returns 0, * @p true otherwise. * * @retval false more pages follow * @retval true this is the last page of the wizard */ virtual bool isLastPage() const; /** * This returns, if all necessary data for this page has been * filled. It is used to enabled the 'Next' or 'Finish' button. * The button is only enabled, if this method returns @p true, * which is the default implementation. * * @retval false more data required from the user before we can proceed * @retval true all data available, we allow to switch to the next page */ virtual bool isComplete() const; /** * This method returns the step to which this page belongs. * It is required by the KMyMoneyWizard and is not intended * to be used by application code. * * @return step of wizard this page belongs to */ unsigned int step() const; /** * This method returns a pointer to the widget of the page. * It is required by the KMyMoneyWizard and is not intended * to be used by application code. * * @return pointer to widget of page */ QWidget* widget() const; /** * This method returns a pointer to the QObject used for * the signal/slot mechanism. * It is required by the KMyMoneyWizard and can be used * by application code for signal/slot connections as well. * Other use is not foreseen. */ - QObject* object() const; + const KMyMoneyWizardPagePrivate *object() const; /** * This method returns a pointer to the widget which should * receive the focus when the page is opened. * * @return pointer to widget or 0 if none is to be selected * The default implementation returns 0 */ virtual QWidget* initialFocusWidget() const; virtual KMyMoneyWizard* wizard() const = 0; /** * This method returns a specific help context for the page shown * The default returns an empty string. */ virtual QString helpContext() const; virtual ~KMyMoneyWizardPage(); protected: + KMyMoneyWizardPagePrivate * const d_ptr; + + KMyMoneyWizardPage(KMyMoneyWizardPagePrivate &dd, uint step, QWidget *widget); + Q_DECLARE_PRIVATE(KMyMoneyWizardPage) + /** * Constructor (kept protected, so that one cannot create such an object directly) */ - explicit KMyMoneyWizardPage(unsigned int step, QWidget* widget); + explicit KMyMoneyWizardPage(uint step, QWidget* widget); /** * This method must be called by the implementation when the * data in the fields of the wizard change and the state of * completeness changed. * * @note If you do not override isComplete() then there is no need * to call this method. */ - void completeStateChanged() const; - -protected: - KMandatoryFieldGroup* m_mandatoryGroup; - -private: - unsigned int m_step; - QWidget* m_widget; - KMyMoneyWizardPagePrivate* const d; + void completeStateChanged(); }; - - -/** - * The general base class for wizard pages - * - * @author Thomas Baumgart - */ -template -class WizardPage : public KMyMoneyWizardPage -{ -public: - WizardPage(unsigned int step, QWidget* widget, T* parent) : - KMyMoneyWizardPage(step, widget), - m_wizard(parent), - m_wizardBase(parent) { - } - virtual ~WizardPage() {} - virtual KMyMoneyWizard* wizard() const { - return m_wizardBase; - } - -protected: - T* m_wizard; - KMyMoneyWizard* m_wizardBase; -}; - - #endif diff --git a/kmymoney/widgets/kmymoneywizard_p.h b/kmymoney/wizards/kmymoneywizardpage_p.h similarity index 74% copy from kmymoney/widgets/kmymoneywizard_p.h copy to kmymoney/wizards/kmymoneywizardpage_p.h index 2e365e93c..58683a20e 100644 --- a/kmymoney/widgets/kmymoneywizard_p.h +++ b/kmymoney/wizards/kmymoneywizardpage_p.h @@ -1,55 +1,71 @@ /*************************************************************************** - kmymoneywizard_p.h + kmymoneywizardpage_p.h ------------------- copyright : (C) 2006 by Thomas Baumagrt email : ipwizard@users.sourceforge.net (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef KMYMONEYWIZARD_P_H -#define KMYMONEYWIZARD_P_H +#ifndef KMYMONEYWIZARDPAGE_P_H +#define KMYMONEYWIZARDPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes +class KMandatoryFieldGroup; + /** * @author Thomas Baumgart (C) 2006 * * This class represents a helper object required * to be able to use Qt's signal/slot mechanism within * the KMyMoneyWizardPage object which cannot be * derived from QObject directly. */ + class KMyMoneyWizardPagePrivate : public QObject { - Q_OBJECT + Q_OBJECT + Q_DISABLE_COPY(KMyMoneyWizardPagePrivate) + public: - /** - * Constructor - */ - explicit KMyMoneyWizardPagePrivate(QObject* parent); + explicit KMyMoneyWizardPagePrivate(QObject* parent) : + QObject(parent) + { + } + + virtual ~KMyMoneyWizardPagePrivate() + { + } + + void emitCompleteStateChanged() + { + emit completeStateChanged(); + } - void emitCompleteStateChanged(void); + uint m_step; + QWidget *m_widget; + KMandatoryFieldGroup *m_mandatoryGroup; signals: - void completeStateChanged(void); + void completeStateChanged(); }; #endif diff --git a/kmymoney/wizards/newaccountwizard/CMakeLists.txt b/kmymoney/wizards/newaccountwizard/CMakeLists.txt index 000dc491f..a86ee156f 100644 --- a/kmymoney/wizards/newaccountwizard/CMakeLists.txt +++ b/kmymoney/wizards/newaccountwizard/CMakeLists.txt @@ -1,22 +1,34 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) set (libnewaccountwizard_a_SOURCES knewaccountwizard.cpp + kaccountsummarypage.cpp + kaccounttypepage.cpp + kbrokeragepage.cpp + kcreditcardschedulepage.cpp + kgeneralloaninfopage.cpp + khierarchypage.cpp + kinstitutionpage.cpp + kloandetailspage.cpp + kloanpaymentpage.cpp + kloanpayoutpage.cpp + kloanschedulepage.cpp + hierarchyfilterproxymodel.cpp ) set (libnewaccountwizard_a_UI - kaccountsummarypagedecl.ui kaccounttypepagedecl.ui - kbrokeragepagedecl.ui kgeneralloaninfopagedecl.ui - khierarchypagedecl.ui kinstitutionpagedecl.ui - kloandetailspagedecl.ui kloanpaymentpagedecl.ui - kloanpayoutpagedecl.ui kloanschedulepagedecl.ui kschedulepagedecl.ui + kaccountsummarypage.ui kaccounttypepage.ui + kbrokeragepage.ui kgeneralloaninfopage.ui + kgeneralloaninfopage.ui kinstitutionpage.ui + kloandetailspage.ui kloanpaymentpage.ui + kloanpayoutpage.ui kloanschedulepage.ui kcreditcardschedulepage.ui khierarchypage.ui ) ki18n_wrap_ui(libnewaccountwizard_a_SOURCES ${libnewaccountwizard_a_UI} ) add_library(newaccountwizard STATIC ${libnewaccountwizard_a_SOURCES}) # TODO: clean dependencies -target_link_libraries(newaccountwizard KF5::XmlGui KF5::Service KF5::IconThemes KF5::ConfigGui KF5::WidgetsAddons KF5::TextWidgets KF5::Completion Qt5::Widgets Qt5::Xml Qt5::Sql Alkimia::alkimia) +target_link_libraries(newaccountwizard kmymoneywizard KF5::XmlGui KF5::Service KF5::IconThemes KF5::ConfigGui KF5::WidgetsAddons KF5::TextWidgets KF5::Completion Qt5::Widgets Qt5::Xml Qt5::Sql Alkimia::alkimia) # we rely on some dialogs to be generated add_dependencies(newaccountwizard dialogs) diff --git a/kmymoney/wizards/newaccountwizard/hierarchyfilterproxymodel.cpp b/kmymoney/wizards/newaccountwizard/hierarchyfilterproxymodel.cpp new file mode 100644 index 000000000..1ad8e98c3 --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/hierarchyfilterproxymodel.cpp @@ -0,0 +1,65 @@ +/*************************************************************************** + hierarchyfilterproxymodel.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "hierarchyfilterproxymodel.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "accountsmodel.h" +#include "accountsproxymodel.h" +#include "modelenums.h" + +namespace NewAccountWizard +{ + HierarchyFilterProxyModel::HierarchyFilterProxyModel(QObject *parent) + : AccountsProxyModel(parent) + { + } + + /** + * Filter the favorites accounts group. + */ + bool HierarchyFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const + { + if (!source_parent.isValid()) { + auto accCol = m_mdlColumns->indexOf(eAccountsModel::Column::Account); + QVariant data = sourceModel()->index(source_row, accCol, source_parent).data((int)eAccountsModel::Role::ID); + if (data.isValid() && data.toString() == AccountsModel::favoritesAccountId) + return false; + } + return AccountsProxyModel::filterAcceptsRow(source_row, source_parent); + } + + /** + * Filter all but the first column. + */ + bool HierarchyFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const + { + Q_UNUSED(source_parent) + if (source_column == 0) + return true; + return false; + } +} diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/hierarchyfilterproxymodel.h similarity index 64% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/hierarchyfilterproxymodel.h index 473078b58..1ba9a5e11 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/hierarchyfilterproxymodel.h @@ -1,49 +1,52 @@ /*************************************************************************** - userinfo.cpp + hierarchyfilterproxymodel.h ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef HIERACHRYFILTERPROXYMODEL_H +#define HIERACHRYFILTERPROXYMODEL_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "accountsproxymodel.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) -{ - m_userNameEdit->setFocus(); -} +class Wizard; +class MyMoneyInstitution; -MyMoneyPayee UserInfo::user() const +namespace NewAccountWizard { - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} + class HierarchyFilterProxyModel : public AccountsProxyModel + { + Q_OBJECT + Q_DISABLE_COPY(HierarchyFilterProxyModel) + + public: + explicit HierarchyFilterProxyModel(QObject *parent = 0); + + protected: + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const; + }; +} // namespace + +#endif diff --git a/kmymoney/wizards/newaccountwizard/kaccountsummarypage.cpp b/kmymoney/wizards/newaccountwizard/kaccountsummarypage.cpp new file mode 100644 index 000000000..2bedecb6d --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kaccountsummarypage.cpp @@ -0,0 +1,225 @@ +/*************************************************************************** + kaccountsummarypage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kaccountsummarypage.h" +#include "kaccountsummarypage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kaccountsummarypage.h" + +#include "kaccountsummarypage.h" +#include "kaccounttypepage.h" +#include "kbrokeragepage.h" +#include "kcreditcardschedulepage.h" +#include "kgeneralloaninfopage.h" +#include "kinstitutionpage.h" +#include "kloandetailspage.h" +#include "kloanpaymentpage.h" +#include "kloanpayoutpage.h" +#include "kloanschedulepage.h" + +#include "kaccountsummarypage_p.h" +#include "kaccounttypepage_p.h" +#include "kbrokeragepage_p.h" +#include "kcreditcardschedulepage_p.h" +#include "kgeneralloaninfopage_p.h" +#include "kloandetailspage_p.h" +#include "kloanpayoutpage_p.h" +#include "kloanschedulepage_p.h" + +#include "kmymoneycategory.h" +#include "kmymoneycurrencyselector.h" +#include "kmymoneydateinput.h" +#include "kmymoneyedit.h" +#include "kmymoneyfrequencycombo.h" +#include "kmymoneygeneralcombo.h" +#include "kmymoneypayeecombo.h" +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "mymoneyaccount.h" +#include "mymoneyenums.h" +#include "mymoneyfile.h" +#include "mymoneyinstitution.h" +#include "mymoneymoney.h" +#include "mymoneyprice.h" +#include "mymoneyschedule.h" +#include "mymoneysecurity.h" +#include "mymoneyutils.h" +#include "wizardpage.h" + +using namespace NewAccountWizard; +using namespace Icons; +using namespace eMyMoney; + +namespace NewAccountWizard +{ + AccountSummaryPage::AccountSummaryPage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new AccountSummaryPagePrivate(wizard), StepFinish, this, wizard) + { + Q_D(AccountSummaryPage); + d->ui->setupUi(this); + } + + AccountSummaryPage::~AccountSummaryPage() + { + } + + void AccountSummaryPage::enterPage() + { + Q_D(AccountSummaryPage); + MyMoneyAccount acc = d->m_wizard->account(); + MyMoneySecurity sec = d->m_wizard->d_func()->currency(); + acc.fraction(sec); + + // assign an id to the account inside the wizard which is required for a schedule + // get the schedule and clear the id again in the wizards object. + MyMoneyAccount tmp(QLatin1String("Phony-ID"), acc); + d->m_wizard->setAccount(tmp); + MyMoneySchedule sch = d->m_wizard->schedule(); + d->m_wizard->setAccount(acc); + + d->ui->m_dataList->clear(); + + // Account data + d->ui->m_dataList->setFontWeight(QFont::Bold); + d->ui->m_dataList->append(i18n("Account information")); + d->ui->m_dataList->setFontWeight(QFont::Normal); + d->ui->m_dataList->append(i18nc("Account name", "Name: %1", acc.name())); + if (!acc.isLoan()) + d->ui->m_dataList->append(i18n("Subaccount of %1", d->m_wizard->parentAccount().name())); + QString accTypeText; + if (acc.accountType() == Account::AssetLoan) + accTypeText = i18n("Loan"); + else + accTypeText = d->m_wizard->d_func()->m_accountTypePage->d_func()->ui->m_typeSelection->currentText(); + d->ui->m_dataList->append(i18n("Type: %1", accTypeText)); + + d->ui->m_dataList->append(i18n("Currency: %1", d->m_wizard->d_func()->currency().name())); + d->ui->m_dataList->append(i18n("Opening date: %1", QLocale().toString(acc.openingDate()))); + if (d->m_wizard->d_func()->currency().id() != MyMoneyFile::instance()->baseCurrency().id()) { + d->ui->m_dataList->append(i18n("Conversion rate: %1", d->m_wizard->conversionRate().rate(QString()).formatMoney(QString(), d->m_wizard->d_func()->currency().pricePrecision()))); + } + if (!acc.isLoan() || !d->m_wizard->openingBalance().isZero()) + d->ui->m_dataList->append(i18n("Opening balance: %1", MyMoneyUtils::formatMoney(d->m_wizard->openingBalance(), acc, sec))); + + if (!d->m_wizard->d_func()->m_institutionPage->institution().id().isEmpty()) { + d->ui->m_dataList->append(i18n("Institution: %1", d->m_wizard->d_func()->m_institutionPage->institution().name())); + if (!acc.number().isEmpty()) { + d->ui->m_dataList->append(i18n("Number: %1", acc.number())); + } + if (!acc.value("iban").isEmpty()) { + d->ui->m_dataList->append(i18n("IBAN: %1", acc.value("iban"))); + } + } + + if (acc.accountType() == Account::Investment) { + if (d->m_wizard->d_func()->m_brokeragepage->d_func()->ui->m_createBrokerageButton->isChecked()) { + d->ui->m_dataList->setFontWeight(QFont::Bold); + d->ui->m_dataList->append(i18n("Brokerage Account")); + d->ui->m_dataList->setFontWeight(QFont::Normal); + + d->ui->m_dataList->append(i18nc("Account name", "Name: %1 (Brokerage)", acc.name())); + d->ui->m_dataList->append(i18n("Currency: %1", d->m_wizard->d_func()->m_brokeragepage->d_func()->ui->m_brokerageCurrency->security().name())); + if (d->m_wizard->d_func()->m_brokeragepage->d_func()->ui->m_accountNumber->isEnabled() && !d->m_wizard->d_func()->m_brokeragepage->d_func()->ui->m_accountNumber->text().isEmpty()) + d->ui->m_dataList->append(i18n("Number: %1", d->m_wizard->d_func()->m_brokeragepage->d_func()->ui->m_accountNumber->text())); + if (d->m_wizard->d_func()->m_brokeragepage->d_func()->ui->m_iban->isEnabled() && !d->m_wizard->d_func()->m_brokeragepage->d_func()->ui->m_iban->text().isEmpty()) + d->ui->m_dataList->append(i18n("IBAN: %1", d->m_wizard->d_func()->m_brokeragepage->d_func()->ui->m_iban->text())); + } + } + + // Loan + if (acc.isLoan()) { + d->ui->m_dataList->setFontWeight(QFont::Bold); + d->ui->m_dataList->append(i18n("Loan information")); + d->ui->m_dataList->setFontWeight(QFont::Normal); + if (d->m_wizard->moneyBorrowed()) { + d->ui->m_dataList->append(i18n("Amount borrowed: %1", d->m_wizard->d_func()->m_loanDetailsPage->d_func()->ui->m_loanAmount->value().formatMoney(d->m_wizard->d_func()->currency().tradingSymbol(), d->m_wizard->d_func()->precision()))); + } else { + d->ui->m_dataList->append(i18n("Amount lent: %1", d->m_wizard->d_func()->m_loanDetailsPage->d_func()->ui->m_loanAmount->value().formatMoney(d->m_wizard->d_func()->currency().tradingSymbol(), d->m_wizard->d_func()->precision()))); + } + d->ui->m_dataList->append(i18n("Interest rate: %1 %", d->m_wizard->d_func()->m_loanDetailsPage->d_func()->ui->m_interestRate->value().formatMoney(QString(), -1))); + d->ui->m_dataList->append(i18n("Interest rate is %1", d->m_wizard->d_func()->m_generalLoanInfoPage->d_func()->ui->m_interestType->currentText())); + d->ui->m_dataList->append(i18n("Principal and interest: %1", MyMoneyUtils::formatMoney(d->m_wizard->d_func()->m_loanDetailsPage->d_func()->ui->m_paymentAmount->value(), acc, sec))); + d->ui->m_dataList->append(i18n("Additional Fees: %1", MyMoneyUtils::formatMoney(d->m_wizard->d_func()->m_loanPaymentPage->additionalFees(), acc, sec))); + d->ui->m_dataList->append(i18n("Payment frequency: %1", d->m_wizard->d_func()->m_generalLoanInfoPage->d_func()->ui->m_paymentFrequency->currentText())); + d->ui->m_dataList->append(i18n("Payment account: %1", d->m_wizard->d_func()->m_loanSchedulePage->d_func()->ui->m_paymentAccount->currentText())); + + if (!d->m_wizard->d_func()->m_loanPayoutPage->d_func()->ui->m_noPayoutTransaction->isChecked() && d->m_wizard->openingBalance().isZero()) { + d->ui->m_dataList->setFontWeight(QFont::Bold); + d->ui->m_dataList->append(i18n("Payout information")); + d->ui->m_dataList->setFontWeight(QFont::Normal); + if (d->m_wizard->d_func()->m_loanPayoutPage->d_func()->ui->m_refinanceLoan->isChecked()) { + d->ui->m_dataList->append(i18n("Refinance: %1", d->m_wizard->d_func()->m_loanPayoutPage->d_func()->ui->m_loanAccount->currentText())); + } else { + if (d->m_wizard->moneyBorrowed()) + d->ui->m_dataList->append(i18n("Transfer amount to %1", d->m_wizard->d_func()->m_loanPayoutPage->d_func()->ui->m_assetAccount->currentText())); + else + d->ui->m_dataList->append(i18n("Transfer amount from %1", d->m_wizard->d_func()->m_loanPayoutPage->d_func()->ui->m_assetAccount->currentText())); + } + d->ui->m_dataList->append(i18n("Payment date: %1 ", QLocale().toString(d->m_wizard->d_func()->m_loanPayoutPage->d_func()->ui->m_payoutDate->date()))); + } + } + + // Schedule + if (!(sch == MyMoneySchedule())) { + d->ui->m_dataList->setFontWeight(QFont::Bold); + d->ui->m_dataList->append(i18n("Schedule information")); + d->ui->m_dataList->setFontWeight(QFont::Normal); + d->ui->m_dataList->append(i18nc("Schedule name", "Name: %1", sch.name())); + if (acc.accountType() == Account::CreditCard) { + MyMoneyAccount paymentAccount = MyMoneyFile::instance()->account(d->m_wizard->d_func()->m_schedulePage->d_func()->ui->m_paymentAccount->selectedItem()); + d->ui->m_dataList->append(i18n("Occurrence: Monthly")); + d->ui->m_dataList->append(i18n("Paid from %1", paymentAccount.name())); + d->ui->m_dataList->append(i18n("Pay to %1", d->m_wizard->d_func()->m_schedulePage->d_func()->ui->m_payee->currentText())); + d->ui->m_dataList->append(i18n("Amount: %1", MyMoneyUtils::formatMoney(d->m_wizard->d_func()->m_schedulePage->d_func()->ui->m_amount->value(), acc, sec))); + d->ui->m_dataList->append(i18n("First payment due on %1", QLocale().toString(sch.nextDueDate()))); + d->ui->m_dataList->append(i18n("Payment method: %1", d->m_wizard->d_func()->m_schedulePage->d_func()->ui->m_method->currentText())); + } + if (acc.isLoan()) { + d->ui->m_dataList->append(i18n("Occurrence: %1", d->m_wizard->d_func()->m_generalLoanInfoPage->d_func()->ui->m_paymentFrequency->currentText())); + d->ui->m_dataList->append(i18n("Amount: %1", MyMoneyUtils::formatMoney(d->m_wizard->d_func()->m_loanPaymentPage->basePayment() + d->m_wizard->d_func()->m_loanPaymentPage->additionalFees(), acc, sec))); + d->ui->m_dataList->append(i18n("First payment due on %1", QLocale().toString(d->m_wizard->d_func()->m_loanSchedulePage->firstPaymentDueDate()))); + } + } + } + + QWidget* AccountSummaryPage::initialFocusWidget() const + { + Q_D(const AccountSummaryPage); + return d->ui->m_dataList; + } + +} diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kaccountsummarypage.h similarity index 63% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kaccountsummarypage.h index 473078b58..e21b8b96f 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kaccountsummarypage.h @@ -1,49 +1,57 @@ /*************************************************************************** - userinfo.cpp + kaccountsummarypage.h ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTACCOUNTSUMMARYPAGE_H +#define KNEWACCOUNTACCOUNTSUMMARYPAGE_H // ---------------------------------------------------------------------------- // QT Includes +#include + // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" - +#include "wizardpage.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); -} + class Wizard; -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} + class AccountSummaryPagePrivate; + class AccountSummaryPage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(AccountSummaryPage) + + public: + explicit AccountSummaryPage(Wizard* parent); + ~AccountSummaryPage() override; + + void enterPage(); + QWidget* initialFocusWidget() const override; + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, AccountSummaryPage) + friend class Wizard; + }; +} // namespace + +#endif diff --git a/kmymoney/wizards/newaccountwizard/kaccountsummarypagedecl.ui b/kmymoney/wizards/newaccountwizard/kaccountsummarypage.ui similarity index 94% rename from kmymoney/wizards/newaccountwizard/kaccountsummarypagedecl.ui rename to kmymoney/wizards/newaccountwizard/kaccountsummarypage.ui index bcee9ea3a..943b2770a 100644 --- a/kmymoney/wizards/newaccountwizard/kaccountsummarypagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/kaccountsummarypage.ui @@ -1,55 +1,55 @@ - KAccountSummaryPageDecl - + KAccountSummaryPage + 0 0 600 480 Qt::NoFocus This page summarizes the data you have entered. Press <b>Finish</b> to create the account, schedules, etc. or use <b>Back</b> to modify your entries. true 7 3 0 2 true KTextEdit QTextEdit
ktextedit.h
diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kaccountsummarypage_p.h similarity index 62% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kaccountsummarypage_p.h index 473078b58..0edbda75a 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kaccountsummarypage_p.h @@ -1,49 +1,59 @@ /*************************************************************************** - userinfo.cpp + kaccountsummarypage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTACCOUNTSUMMARYPAGE_P_H +#define KNEWACCOUNTACCOUNTSUMMARYPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_kaccountsummarypage.h" +#include "wizardpage_p.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); + class Wizard; + + class AccountSummaryPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(AccountSummaryPagePrivate) + + public: + AccountSummaryPagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KAccountSummaryPage) + { + } + + ~AccountSummaryPagePrivate() + { + delete ui; + } + + Ui::KAccountSummaryPage *ui; + }; } -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/kaccounttypepage.cpp b/kmymoney/wizards/newaccountwizard/kaccounttypepage.cpp new file mode 100644 index 000000000..2e4692663 --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kaccounttypepage.cpp @@ -0,0 +1,272 @@ +/*************************************************************************** + kaccounttypepage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kaccounttypepage.h" +#include "kaccounttypepage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kaccounttypepage.h" + +#include "kequitypriceupdatedlg.h" +#include "kmymoneycurrencyselector.h" +#include "kmymoneydateinput.h" +#include "kmymoneyedit.h" +#include "kmymoneygeneralcombo.h" +#include "kmymoneyglobalsettings.h" +#include "kmymoneywizardpage.h" +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "kbrokeragepage.h" +#include "kcreditcardschedulepage.h" +#include "kgeneralloaninfopage.h" +#include "khierarchypage.h" +#include "mymoneyaccount.h" +#include "mymoneyfile.h" +#include "mymoneymoney.h" +#include "mymoneyprice.h" +#include "mymoneysecurity.h" +#include "wizardpage.h" +#include "kguiutils.h" +#include "mymoneyenums.h" + +using namespace eMyMoney; + +namespace NewAccountWizard +{ + AccountTypePage::AccountTypePage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new AccountTypePagePrivate(wizard), StepAccount, this, wizard) + { + Q_D(AccountTypePage); + d->ui->setupUi(this); + d->m_showPriceWarning = true; + d->ui->m_typeSelection->insertItem(i18n("Checking"), (int)Account::Checkings); + d->ui->m_typeSelection->insertItem(i18n("Savings"), (int)Account::Savings); + d->ui->m_typeSelection->insertItem(i18n("Credit Card"), (int)Account::CreditCard); + d->ui->m_typeSelection->insertItem(i18n("Cash"), (int)Account::Cash); + d->ui->m_typeSelection->insertItem(i18n("Loan"), (int)Account::Loan); + d->ui->m_typeSelection->insertItem(i18n("Investment"), (int)Account::Investment); + d->ui->m_typeSelection->insertItem(i18n("Asset"), (int)Account::Asset); + d->ui->m_typeSelection->insertItem(i18n("Liability"), (int)Account::Liability); + if (KMyMoneyGlobalSettings::expertMode()) { + d->ui->m_typeSelection->insertItem(i18n("Equity"), (int)Account::Equity); + } + + d->ui->m_typeSelection->setCurrentItem((int)Account::Checkings); + + d->ui->m_currencyComboBox->setSecurity(MyMoneyFile::instance()->baseCurrency()); + + d->m_mandatoryGroup->add(d->ui->m_accountName); + d->m_mandatoryGroup->add(d->ui->m_conversionRate->lineedit()); + + d->ui->m_conversionRate->setValue(MyMoneyMoney::ONE); + slotUpdateCurrency(); + + connect(d->ui->m_typeSelection, &KMyMoneyGeneralCombo::itemSelected, this, &AccountTypePage::slotUpdateType); + connect(d->ui->m_currencyComboBox, static_cast(&QComboBox::activated), this, &AccountTypePage::slotUpdateCurrency); + connect(d->ui->m_conversionRate, &KMyMoneyEdit::textChanged, this, &AccountTypePage::slotUpdateConversionRate); + connect(d->ui->m_conversionRate, &KMyMoneyEdit::valueChanged, this, &AccountTypePage::slotPriceWarning); + connect(d->ui->m_onlineQuote, &QAbstractButton::clicked, this, &AccountTypePage::slotGetOnlineQuote); + } + + AccountTypePage::~AccountTypePage() + { + } + + void AccountTypePage::slotUpdateType(int i) + { + Q_D(AccountTypePage); + hideShowPages(static_cast(i)); + d->ui->m_openingBalance->setDisabled(static_cast(i) == Account::Equity); + } + + void AccountTypePage::hideShowPages(Account accountType) const + { + Q_D(const AccountTypePage); + bool hideSchedulePage = (accountType != Account::CreditCard) + && (accountType != Account::Loan); + bool hideLoanPage = (accountType != Account::Loan); + d->m_wizard->d_func()->setStepHidden(StepDetails, hideLoanPage); + d->m_wizard->d_func()->setStepHidden(StepPayments, hideLoanPage); + d->m_wizard->d_func()->setStepHidden(StepFees, hideLoanPage); + d->m_wizard->d_func()->setStepHidden(StepSchedule, hideSchedulePage); + d->m_wizard->d_func()->setStepHidden(StepPayout, (accountType != Account::Loan)); + d->m_wizard->d_func()->setStepHidden(StepBroker, accountType != Account::Investment); + d->m_wizard->d_func()->setStepHidden(StepParentAccount, accountType == Account::Loan); + // Force an update of the steps in case the list has changed + d->m_wizard->reselectStep(); + } + + KMyMoneyWizardPage* AccountTypePage::nextPage() const + { + Q_D(const AccountTypePage); + if (accountType() == Account::Loan) + return d->m_wizard->d_func()->m_generalLoanInfoPage; + if (accountType() == Account::CreditCard) + return d->m_wizard->d_func()->m_schedulePage; + if (accountType() == Account::Investment) + return d->m_wizard->d_func()->m_brokeragepage; + return d->m_wizard->d_func()->m_hierarchyPage; + } + + QWidget* AccountTypePage::initialFocusWidget() const + { + Q_D(const AccountTypePage); + return d->ui->m_accountName; + } + + void AccountTypePage::slotUpdateCurrency() + { + Q_D(AccountTypePage); + MyMoneyAccount acc; + acc.setAccountType(accountType()); + + d->ui->m_openingBalance->setPrecision(MyMoneyMoney::denomToPrec(acc.fraction(currency()))); + + bool show = d->ui->m_currencyComboBox->security().id() != MyMoneyFile::instance()->baseCurrency().id(); + d->ui->m_conversionLabel->setVisible(show); + d->ui->m_conversionRate->setVisible(show); + d->ui->m_conversionExample->setVisible(show); + d->ui->m_onlineQuote->setVisible(show); + d->ui->m_conversionRate->setEnabled(show); // make sure to include/exclude in mandatoryGroup + d->ui->m_conversionRate->setPrecision(d->ui->m_currencyComboBox->security().pricePrecision()); + d->m_mandatoryGroup->changed(); + slotUpdateConversionRate(d->ui->m_conversionRate->lineedit()->text()); + } + + void AccountTypePage::slotGetOnlineQuote() + { + Q_D(AccountTypePage); + QString id = MyMoneyFile::instance()->baseCurrency().id() + ' ' + d->ui->m_currencyComboBox->security().id(); + QPointer dlg = new KEquityPriceUpdateDlg(this, id); + if (dlg->exec() == QDialog::Accepted) { + const MyMoneyPrice &price = dlg->price(id); + if (price.isValid()) { + d->ui->m_conversionRate->setValue(price.rate(d->ui->m_currencyComboBox->security().id())); + if (price.date() != d->ui->m_openingDate->date()) { + priceWarning(true); + } + } + } + delete dlg; + } + + void AccountTypePage::slotPriceWarning() + { + priceWarning(false); + } + + void AccountTypePage::priceWarning(bool always) + { + Q_D(AccountTypePage); + if (d->m_showPriceWarning || always) { + KMessageBox::information(this, i18n("Please make sure to enter the correct conversion for the selected opening date. If you requested an online quote it might be provided for a different date."), i18n("Check date")); + } + d->m_showPriceWarning = false; + } + + void AccountTypePage::slotUpdateConversionRate(const QString& txt) + { + Q_D(AccountTypePage); + d->ui->m_conversionExample->setText(i18n("1 %1 equals %2", MyMoneyFile::instance()->baseCurrency().tradingSymbol(), MyMoneyMoney(txt).formatMoney(d->ui->m_currencyComboBox->security().tradingSymbol(), d->ui->m_currencyComboBox->security().pricePrecision()))); + } + + bool AccountTypePage::isComplete() const + { + Q_D(const AccountTypePage); + // check that the conversion rate is positive if enabled + bool rc = !d->ui->m_conversionRate->isVisible() || (!d->ui->m_conversionRate->value().isZero() && !d->ui->m_conversionRate->value().isNegative()); + if (!rc) { + d->m_wizard->d_func()->m_nextButton->setToolTip(i18n("Conversion rate is not positive")); + + } else { + rc = KMyMoneyWizardPage::isComplete(); + + if (!rc) { + d->m_wizard->d_func()->m_nextButton->setToolTip(i18n("No account name supplied")); + } + } + hideShowPages(accountType()); + return rc; + } + + Account AccountTypePage::accountType() const + { + Q_D(const AccountTypePage); + return static_cast(d->ui->m_typeSelection->currentItem()); + } + + const MyMoneySecurity& AccountTypePage::currency() const + { + Q_D(const AccountTypePage); + return d->ui->m_currencyComboBox->security(); + } + + void AccountTypePage::setAccount(const MyMoneyAccount& acc) + { + Q_D(const AccountTypePage); + if (acc.accountType() != Account::Unknown) { + if (acc.accountType() == Account::AssetLoan) { + d->ui->m_typeSelection->setCurrentItem((int)Account::Loan); + } else { + d->ui->m_typeSelection->setCurrentItem((int)acc.accountType()); + } + } + d->ui->m_openingDate->setDate(acc.openingDate()); + d->ui->m_accountName->setText(acc.name()); + } + + const MyMoneyAccount& AccountTypePage::parentAccount() + { + switch (accountType()) { + case Account::CreditCard: + case Account::Liability: + case Account::Loan: // Can be either but we return liability here + return MyMoneyFile::instance()->liability(); + break; + case Account::Equity: + return MyMoneyFile::instance()->equity(); + default: + break; + } + return MyMoneyFile::instance()->asset(); + } + + bool AccountTypePage::allowsParentAccount() const + { + return accountType() != Account::Loan; + } +} diff --git a/kmymoney/wizards/newaccountwizard/kaccounttypepage.h b/kmymoney/wizards/newaccountwizard/kaccounttypepage.h new file mode 100644 index 000000000..8bfe15137 --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kaccounttypepage.h @@ -0,0 +1,86 @@ +/*************************************************************************** + kaccounttypepage.h + ------------------- + begin : Tue Sep 25 2007 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KNEWACCOUNTWIZARDACCOUNTTYPEPAGE_H +#define KNEWACCOUNTWIZARDACCOUNTTYPEPAGE_H + +// ---------------------------------------------------------------------------- +// QT Includes + +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "wizardpage.h" + +class MyMoneyAccount; +class MyMoneySecurity; + +namespace eMyMoney { enum class Account; } + +namespace NewAccountWizard +{ + class Wizard; + + class AccountTypePagePrivate; + class AccountTypePage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(AccountTypePage) + + public: + explicit AccountTypePage(Wizard* parent); + ~AccountTypePage() override; + + virtual bool isComplete() const; + KMyMoneyWizardPage* nextPage() const; + + QWidget* initialFocusWidget() const override; + + eMyMoney::Account accountType() const; + const MyMoneyAccount& parentAccount(); + bool allowsParentAccount() const; + const MyMoneySecurity& currency() const; + + void setAccount(const MyMoneyAccount& acc); + + private: + void hideShowPages(eMyMoney::Account i) const; + void priceWarning(bool); + + private slots: + void slotUpdateType(int i); + void slotUpdateCurrency(); + void slotUpdateConversionRate(const QString&); + void slotGetOnlineQuote(); + void slotPriceWarning(); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, AccountTypePage) + friend class Wizard; + friend class AccountSummaryPage; + friend class BrokeragePage; + friend class CreditCardSchedulePage; + friend class LoanPayoutPage; + }; +} // namespace + +#endif diff --git a/kmymoney/wizards/newaccountwizard/kaccounttypepagedecl.ui b/kmymoney/wizards/newaccountwizard/kaccounttypepage.ui similarity index 99% rename from kmymoney/wizards/newaccountwizard/kaccounttypepagedecl.ui rename to kmymoney/wizards/newaccountwizard/kaccounttypepage.ui index ee0ce6f41..998433aa9 100644 --- a/kmymoney/wizards/newaccountwizard/kaccounttypepagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/kaccounttypepage.ui @@ -1,317 +1,317 @@ - KAccountTypePageDecl - + KAccountTypePage + 0 0 555 404 10 Qt::NoFocus Enter the name of the account under which it is known within KMyMoney. Select the type for the new account. Use the <b>What's this?</b> feature to see more details about the various account types. Enter the date the account was opened and its currency. true Account name false 0 0 Enter a name under which this account is known within KMyMoney. Account type false 0 0 <p><b>Checking</b> Use the checking account type to manage activities on your checking account e.g. payments, checks and cash card purchases.</p> <p><b>Savings</b> Use the savings account type to manage activities on your savings account.</p> <p><b>Credit Card</b> Use the credit card account type to manage activities on your credit card.</p> <p><b>Cash</b> Use the cash account type to manage activities in your wallet.</p> <p><b>Loan</b> Use the loan account type to manage amortization loans (e.g. mortgages, car loan, money you lend, private loans etc.).</p> <p><b>Investment</b> Use the investment account to manage your stock, mutual fund and other investments.</p> <p><b>Asset</b> Use the asset account type to manage assets (e.g. your house, car or art collection).</p> <p><b>Liability</b> Use the liability account type to manage any type of liability except amortization loans. Use it for taxes you owe or money you borrowed from friends. For amortization loans like mortgages you should create a loan account.</p> Currency false 0 0 Select the currency in which this account is denominated. Qt::Horizontal QSizePolicy::Expanding 231 20 Opening date false Qt::StrongFocus <p>The opening date would be the date of the last statement. In case you want to keep track of transactions prior to this date, enter the ending balance and statement date of a prior statement and add all following transactions into KMyMoney. KMyMoney will not allow you to enter or modify transactions prior to this date.</p> <p><i>Note</i>: If you do not know the exact amount of the opening balance, enter an estimate. You can change this value later before you reconcile this account for the first time.</p> Opening balance false 150 0 Qt::StrongFocus <p>The opening balance is the balance of the account when you start using it with KMyMoney. For new accounts this is usually 0 but for existing accounts this may well differ. Please consult the account statements to figure out this value. The opening balance is to be provided in the currency of the account as selected with the currency button.</p> <p><i>Note</i>: If you do not know the exact amount of the opening balance, enter an estimate. You can change this value later before you reconcile this account for the first time.</p> false Conversion rate false Qt::StrongFocus For foreign currencies an initial conversion rate needs to be provided. This should be the price of the foreign currency in the base currency on the opening date of the account. false Online quote Qt::Horizontal QSizePolicy::Expanding 61 21 xxx false Mark this checkbox if the account should be maintained as preferred account Selecting the <b>Preferred Account</b> checkbox will allow preferred access in some dialogs and views of KMyMoney. Preferred account Qt::Vertical QSizePolicy::Expanding 20 16 KMyMoneyDateInput QFrame
kmymoneydateinput.h
KMyMoneySecuritySelector KComboBox
kmymoneycurrencyselector.h
1
KMyMoneyEdit QFrame
kmymoneyedit.h
KMyMoneyGeneralCombo KComboBox
kmymoneygeneralcombo.h
1
KLineEdit QLineEdit
klineedit.h
KComboBox QComboBox
kcombobox.h
diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kaccounttypepage_p.h similarity index 61% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kaccounttypepage_p.h index 473078b58..3a8a7e03e 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kaccounttypepage_p.h @@ -1,49 +1,60 @@ /*************************************************************************** - userinfo.cpp + kaccounttypepage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDACCOUNTTYPEPAGE_P_H +#define KNEWACCOUNTWIZARDACCOUNTTYPEPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_kaccounttypepage.h" +#include "wizardpage_p.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); + class Wizard; + + class AccountTypePagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(AccountTypePagePrivate) + + public: + AccountTypePagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KAccountTypePage) + { + } + + ~AccountTypePagePrivate() + { + delete ui; + } + + Ui::KAccountTypePage *ui; + bool m_showPriceWarning; + }; } -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/kbrokeragepage.cpp b/kmymoney/wizards/newaccountwizard/kbrokeragepage.cpp new file mode 100644 index 000000000..ecb46be3b --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kbrokeragepage.cpp @@ -0,0 +1,100 @@ +/*************************************************************************** + kbrokeragepage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kbrokeragepage.h" +#include "kbrokeragepage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kbrokeragepage.h" + +#include "kmymoneycurrencyselector.h" +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "kaccounttypepage.h" +#include "kaccounttypepage_p.h" +#include "kbrokeragepage_p.h" +#include "khierarchypage.h" +#include "kinstitutionpage.h" +#include "kinstitutionpage_p.h" +#include "mymoneyfile.h" +#include "mymoneysecurity.h" +#include "wizardpage.h" + +namespace NewAccountWizard +{ + BrokeragePage::BrokeragePage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new BrokeragePagePrivate(wizard), StepBroker, this, wizard) + { + Q_D(BrokeragePage); + d->ui->setupUi(this); + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &BrokeragePage::slotLoadWidgets); + } + + BrokeragePage::~BrokeragePage() + { + } + + void BrokeragePage::slotLoadWidgets() + { + Q_D(BrokeragePage); + d->ui->m_brokerageCurrency->update(QString("x")); + } + + void BrokeragePage::enterPage() + { + Q_D(BrokeragePage); + // assign the currency of the investment account to the + // brokerage account if nothing else has ever been selected + if (d->ui->m_brokerageCurrency->security().id().isEmpty()) { + d->ui->m_brokerageCurrency->setSecurity(d->m_wizard->d_func()->m_accountTypePage->d_func()->ui->m_currencyComboBox->security()); + } + + // check if the institution relevant fields should be enabled or not + bool enabled = d->m_wizard->d_func()->m_institutionPage->d_func()->ui->m_accountNumber->isEnabled(); + d->ui->m_accountNumberLabel->setEnabled(enabled); + d->ui->m_accountNumber->setEnabled(enabled); + d->ui->m_ibanLabel->setEnabled(enabled); + d->ui->m_iban->setEnabled(enabled); + } + + QWidget* BrokeragePage::initialFocusWidget() const + { + Q_D(const BrokeragePage); + return d->ui->m_createBrokerageButton; + } + + KMyMoneyWizardPage* BrokeragePage::nextPage() const + { + Q_D(const BrokeragePage); + return d->m_wizard->d_func()->m_hierarchyPage; + } +} diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kbrokeragepage.h similarity index 60% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kbrokeragepage.h index 473078b58..d55dcf3af 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kbrokeragepage.h @@ -1,49 +1,63 @@ /*************************************************************************** - userinfo.cpp + kbrokeragepage.h ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDBROKERAGEPAGE_H +#define KNEWACCOUNTWIZARDBROKERAGEPAGE_H // ---------------------------------------------------------------------------- // QT Includes +#include + // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" - +#include "wizardpage.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); -} + class Wizard; -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} + class BrokeragePagePrivate; + class BrokeragePage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(BrokeragePage) + + public: + explicit BrokeragePage(Wizard* parent); + ~BrokeragePage() override; + + KMyMoneyWizardPage* nextPage() const; + void enterPage(); + + QWidget* initialFocusWidget() const override; + + private slots: + void slotLoadWidgets(); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, BrokeragePage) + friend class Wizard; + friend class AccountSummaryPage; + }; +} // namespace + +#endif diff --git a/kmymoney/wizards/newaccountwizard/kbrokeragepagedecl.ui b/kmymoney/wizards/newaccountwizard/kbrokeragepage.ui similarity index 98% rename from kmymoney/wizards/newaccountwizard/kbrokeragepagedecl.ui rename to kmymoney/wizards/newaccountwizard/kbrokeragepage.ui index 99a873b35..11228f88d 100644 --- a/kmymoney/wizards/newaccountwizard/kbrokeragepagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/kbrokeragepage.ui @@ -1,187 +1,187 @@ - KBrokeragePageDecl - + KBrokeragePage + 0 0 594 398 10 Qt::NoFocus Does this investment account have a brokerage account?<p> <b>Check</b> the mark if this investment account has an associated account for money that is not invested.<br> <b>Uncheck</b> it if you do not use this account for active stock brokerage. You should also uncheck it if the account is not maintained by a bank or broker. true Create brokerage account false QFrame::NoFrame QFrame::Raised 0 Currency false 0 0 Account number false IBAN false Qt::Horizontal QSizePolicy::Expanding 30 20 Qt::Vertical QSizePolicy::Expanding 21 30 KMyMoneySecuritySelector KComboBox
kmymoneycurrencyselector.h
1
KLineEdit QLineEdit
klineedit.h
KComboBox QComboBox
kcombobox.h
m_createBrokerageButton m_brokerageCurrency m_accountNumber m_iban m_createBrokerageButton toggled(bool) m_currencyFrame setEnabled(bool) 20 20 20 20
diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kbrokeragepage_p.h similarity index 63% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kbrokeragepage_p.h index 473078b58..e7f9a1441 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kbrokeragepage_p.h @@ -1,49 +1,59 @@ /*************************************************************************** - userinfo.cpp + kbrokeragepage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDBROKERAGEPAGE_P_H +#define KNEWACCOUNTWIZARDBROKERAGEPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_kbrokeragepage.h" +#include "wizardpage_p.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); + class Wizard; + + class BrokeragePagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(BrokeragePagePrivate) + + public: + BrokeragePagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KBrokeragePage) + { + } + + ~BrokeragePagePrivate() + { + delete ui; + } + + Ui::KBrokeragePage *ui; + }; } -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/kcreditcardschedulepage.cpp b/kmymoney/wizards/newaccountwizard/kcreditcardschedulepage.cpp new file mode 100644 index 000000000..3d0e97799 --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kcreditcardschedulepage.cpp @@ -0,0 +1,162 @@ +/*************************************************************************** + kcreditcardschedulepage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kcreditcardschedulepage.h" +#include "kcreditcardschedulepage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kcreditcardschedulepage.h" + +#include "kmymoneyaccountselector.h" +#include "kmymoneycategory.h" +#include "kmymoneydateinput.h" +#include "kmymoneyedit.h" +#include "kmymoneygeneralcombo.h" +#include "kmymoneypayeecombo.h" +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "kaccounttypepage.h" +#include "kaccounttypepage_p.h" +#include "kcreditcardschedulepage_p.h" +#include "khierarchypage.h" +#include "mymoneyenums.h" +#include "mymoneyfile.h" +#include "kguiutils.h" +#include "mymoneypayee.h" +#include "wizardpage.h" + +using namespace eMyMoney; + +namespace NewAccountWizard +{ + CreditCardSchedulePage::CreditCardSchedulePage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new CreditCardSchedulePagePrivate(wizard), StepSchedule, this, wizard) + { + Q_D(CreditCardSchedulePage); + d->ui->setupUi(this); + d->m_mandatoryGroup->add(d->ui->m_name); + d->m_mandatoryGroup->add(d->ui->m_payee); + d->m_mandatoryGroup->add(d->ui->m_amount->lineedit()); + d->m_mandatoryGroup->add(d->ui->m_paymentAccount); + connect(d->ui->m_paymentAccount, &KMyMoneyCombo::itemSelected, object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + connect(d->ui->m_payee, &KMyMoneyMVCCombo::itemSelected, object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + connect(d->ui->m_date, &KMyMoneyDateInput::dateChanged, object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + + connect(d->ui->m_payee, &KMyMoneyMVCCombo::createItem, wizard, &KMyMoneyWizard::createPayee); + + d->ui->m_reminderCheckBox->setChecked(true); + connect(d->ui->m_reminderCheckBox, &QAbstractButton::toggled, object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &CreditCardSchedulePage::slotLoadWidgets); + + d->ui->m_method->insertItem(i18n("Write check"), (int)Schedule::PaymentType::WriteChecque); +#if 0 + d->ui->m_method->insertItem(i18n("Direct debit"), Schedule::PaymentType::DirectDebit); + d->ui->m_method->insertItem(i18n("Bank transfer"), Schedule::PaymentType::BankTransfer); +#endif + d->ui->m_method->insertItem(i18n("Standing order"), (int)Schedule::PaymentType::StandingOrder); + d->ui->m_method->insertItem(i18n("Manual deposit"), (int)Schedule::PaymentType::ManualDeposit); + d->ui->m_method->insertItem(i18n("Direct deposit"), (int)Schedule::PaymentType::DirectDeposit); + d->ui->m_method->insertItem(i18nc("Other payment method", "Other"), (int)Schedule::PaymentType::Other); + d->ui->m_method->setCurrentItem((int)Schedule::PaymentType::DirectDebit); + + slotLoadWidgets(); + } + + CreditCardSchedulePage::~CreditCardSchedulePage() + { + } + + void CreditCardSchedulePage::enterPage() + { + Q_D(CreditCardSchedulePage); + if (d->ui->m_name->text().isEmpty()) + d->ui->m_name->setText(i18n("Credit Card %1 monthly payment", d->m_wizard->d_func()->m_accountTypePage->d_func()->ui->m_accountName->text())); + } + + QWidget* CreditCardSchedulePage::initialFocusWidget() const + { + Q_D(const CreditCardSchedulePage); + return d->ui->m_reminderCheckBox; + } + + bool CreditCardSchedulePage::isComplete() const + { + Q_D(const CreditCardSchedulePage); + bool rc = true; + QString msg = i18n("Finish entry and create account"); + if (d->ui->m_reminderCheckBox->isChecked()) { + msg = i18n("Finish entry and create account and schedule"); + if (d->ui->m_date->date() < d->m_wizard->d_func()->m_accountTypePage->d_func()->ui->m_openingDate->date()) { + rc = false; + msg = i18n("Next due date is prior to opening date"); + } + if (d->ui->m_paymentAccount->selectedItem().isEmpty()) { + rc = false; + msg = i18n("No account selected"); + } + if (d->ui->m_amount->lineedit()->text().isEmpty()) { + rc = false; + msg = i18n("No amount for payment selected"); + } + if (d->ui->m_payee->selectedItem().isEmpty()) { + rc = false; + msg = i18n("No payee for payment selected"); + } + if (d->ui->m_name->text().isEmpty()) { + rc = false; + msg = i18n("No name assigned for schedule"); + } + } + d->m_wizard->d_func()->m_finishButton->setToolTip(msg); + + return rc; + } + + void CreditCardSchedulePage::slotLoadWidgets() + { + Q_D(CreditCardSchedulePage); + AccountSet set; + set.addAccountGroup(Account::Asset); + set.load(d->ui->m_paymentAccount->selector()); + + d->ui->m_payee->loadPayees(MyMoneyFile::instance()->payeeList()); + } + + KMyMoneyWizardPage* CreditCardSchedulePage::nextPage() const + { + Q_D(const CreditCardSchedulePage); + return d->m_wizard->d_func()->m_hierarchyPage; + } +} diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kcreditcardschedulepage.h similarity index 57% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kcreditcardschedulepage.h index 473078b58..f95908fd3 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kcreditcardschedulepage.h @@ -1,49 +1,65 @@ /*************************************************************************** - userinfo.cpp + kcreditcardschedulepage.h ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDCREDITCARDSCHEDULE_H +#define KNEWACCOUNTWIZARDCREDITCARDSCHEDULE_H // ---------------------------------------------------------------------------- // QT Includes +#include + // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" - +#include "wizardpage.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); -} + class Wizard; -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} + class CreditCardSchedulePagePrivate; + class CreditCardSchedulePage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(CreditCardSchedulePage) + + public: + explicit CreditCardSchedulePage(Wizard* parent); + ~CreditCardSchedulePage() override; + + KMyMoneyWizardPage* nextPage() const; + virtual bool isComplete() const; + void enterPage(); + + QWidget* initialFocusWidget() const override; + + private slots: + void slotLoadWidgets(); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, CreditCardSchedulePage) + friend class Wizard; + friend class AccountSummaryPage; + }; + +} // namespace + +#endif diff --git a/kmymoney/wizards/newaccountwizard/kschedulepagedecl.ui b/kmymoney/wizards/newaccountwizard/kcreditcardschedulepage.ui similarity index 98% rename from kmymoney/wizards/newaccountwizard/kschedulepagedecl.ui rename to kmymoney/wizards/newaccountwizard/kcreditcardschedulepage.ui index f452af628..35b6cd69f 100644 --- a/kmymoney/wizards/newaccountwizard/kschedulepagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/kcreditcardschedulepage.ui @@ -1,202 +1,202 @@ - KSchedulePageDecl - + KCreditCardSchedulePage + 0 0 544 391 For credit card accounts you can create a monthly schedule which will automatically remind you about the payment. Please fill in the details about this payment here. true Qt::StrongFocus Yes, remind me when the payment is due QFrame::NoFrame QFrame::Plain 0 0 5 0 0 180 0 Name of schedule false Payee false Estimated monthly payment false Qt::StrongFocus Due date of next payment false Qt::StrongFocus Payment should be made from account Qt::AlignTop false Payment method false 20 31 QSizePolicy::Expanding Qt::Vertical m_reminderCheckBox toggled(bool) m_paymentFrame setEnabled(bool) KMyMoneyGeneralCombo QWidget
kmymoneygeneralcombo.h
1
KMyMoneyPayeeCombo QWidget
kmymoneypayeecombo.h
1
KLineEdit QLineEdit
klineedit.h
diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kcreditcardschedulepage_p.h similarity index 61% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kcreditcardschedulepage_p.h index 473078b58..7ec7b5a2f 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kcreditcardschedulepage_p.h @@ -1,49 +1,59 @@ /*************************************************************************** - userinfo.cpp + kcreditcardschedulepage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDCREDITCARDSCHEDULE_P_H +#define KNEWACCOUNTWIZARDCREDITCARDSCHEDULE_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_kcreditcardschedulepage.h" +#include "wizardpage_p.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); + class Wizard; + + class CreditCardSchedulePagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(CreditCardSchedulePagePrivate) + + public: + CreditCardSchedulePagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KCreditCardSchedulePage) + { + } + + ~CreditCardSchedulePagePrivate() + { + delete ui; + } + + Ui::KCreditCardSchedulePage *ui; + }; } -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/kgeneralloaninfopage.cpp b/kmymoney/wizards/newaccountwizard/kgeneralloaninfopage.cpp new file mode 100644 index 000000000..c48f13bfe --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kgeneralloaninfopage.cpp @@ -0,0 +1,176 @@ +/*************************************************************************** + kgeneralloaninfopage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgeneralloaninfopage.h" +#include "kgeneralloaninfopage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kgeneralloaninfopage.h" + +#include "kmymoneydateinput.h" +#include "kmymoneyedit.h" +#include "kmymoneyfrequencycombo.h" +#include "kmymoneypayeecombo.h" +#include "kmymoneywizardpage.h" +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "kgeneralloaninfopage_p.h" +#include "kloandetailspage.h" +#include "mymoneyenums.h" +#include "mymoneyfile.h" +#include "mymoneymoney.h" +#include "mymoneypayee.h" +#include "kguiutils.h" +#include "wizardpage.h" + +using namespace eMyMoney; + +namespace NewAccountWizard +{ + GeneralLoanInfoPage::GeneralLoanInfoPage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new GeneralLoanInfoPagePrivate(wizard), StepDetails, this, wizard) + { + Q_D(GeneralLoanInfoPage); + d->ui->setupUi(this); + d->m_firstTime = true; + d->m_mandatoryGroup->add(d->ui->m_payee); + + // remove the unsupported payment and compounding frequencies and setup default + d->ui->m_paymentFrequency->removeItem((int)Schedule::Occurrence::Once); + d->ui->m_paymentFrequency->removeItem((int)Schedule::Occurrence::EveryOtherYear); + d->ui->m_paymentFrequency->setCurrentItem((int)Schedule::Occurrence::Monthly); + d->ui->m_compoundFrequency->removeItem((int)Schedule::Occurrence::Once); + d->ui->m_compoundFrequency->removeItem((int)Schedule::Occurrence::EveryOtherYear); + d->ui->m_compoundFrequency->setCurrentItem((int)Schedule::Occurrence::Monthly); + + slotLoadWidgets(); + + connect(d->ui->m_payee, &KMyMoneyMVCCombo::createItem, wizard, &KMyMoneyWizard::createPayee); + connect(d->ui->m_anyPayments, static_cast(&QComboBox::activated), object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + connect(d->ui->m_recordings, static_cast(&QComboBox::activated), object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + + connect(d->ui->m_interestType, static_cast(&QComboBox::activated), object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + connect(d->ui->m_interestChangeDateEdit, &KMyMoneyDateInput::dateChanged, object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + connect(d->ui->m_openingBalance, &KMyMoneyEdit::textChanged, object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &GeneralLoanInfoPage::slotLoadWidgets); + } + + GeneralLoanInfoPage::~GeneralLoanInfoPage() + { + } + + KMyMoneyWizardPage* GeneralLoanInfoPage::nextPage() const + { + Q_D(const GeneralLoanInfoPage); + return d->m_wizard->d_func()->m_loanDetailsPage; + } + + bool GeneralLoanInfoPage::recordAllPayments() const + { + Q_D(const GeneralLoanInfoPage); + bool rc = true; // all payments + if (d->ui->m_recordings->isEnabled()) { + if (d->ui->m_recordings->currentIndex() != 0) + rc = false; + } + return rc; + } + + void GeneralLoanInfoPage::enterPage() + { + Q_D(GeneralLoanInfoPage); + if (d->m_firstTime) { + // setup default dates to last of this month and one year on top + QDate firstDay(QDate::currentDate().year(), QDate::currentDate().month(), 1); + d->ui->m_firstPaymentDate->setDate(firstDay.addMonths(1).addDays(-1)); + d->ui->m_interestChangeDateEdit->setDate(d->ui->m_firstPaymentDate->date().addYears(1));; + d->m_firstTime = false; + } + } + + bool GeneralLoanInfoPage::isComplete() const + { + Q_D(const GeneralLoanInfoPage); + d->m_wizard->d_func()->setStepHidden(StepPayout, !d->m_wizard->openingBalance().isZero()); + bool rc = KMyMoneyWizardPage::isComplete(); + if (!rc) { + d->m_wizard->d_func()->m_nextButton->setToolTip(i18n("No payee supplied")); + } + + // fixup availability of items on this page + d->ui->m_recordings->setDisabled(d->ui->m_anyPayments->currentIndex() == 0); + + d->ui->m_interestFrequencyAmountEdit->setDisabled(d->ui->m_interestType->currentIndex() == 0); + d->ui->m_interestFrequencyUnitEdit->setDisabled(d->ui->m_interestType->currentIndex() == 0); + d->ui->m_interestChangeDateEdit->setDisabled(d->ui->m_interestType->currentIndex() == 0); + + d->ui->m_openingBalance->setDisabled(recordAllPayments()); + + if (d->ui->m_openingBalance->isEnabled() && d->ui->m_openingBalance->lineedit()->text().length() == 0) { + rc = false; + d->m_wizard->d_func()->m_nextButton->setToolTip(i18n("No opening balance supplied")); + } + + if (rc + && (d->ui->m_interestType->currentIndex() != 0) + && (d->ui->m_interestChangeDateEdit->date() <= d->ui->m_firstPaymentDate->date())) { + rc = false; + d->m_wizard->d_func()->m_nextButton->setToolTip(i18n("An interest change can only happen after the first payment")); + } + return rc; + } + + const MyMoneyAccount& GeneralLoanInfoPage::parentAccount() + { + Q_D(GeneralLoanInfoPage); + return (d->ui->m_loanDirection->currentIndex() == 0) + ? MyMoneyFile::instance()->liability() + : MyMoneyFile::instance()->asset(); + } + + QWidget* GeneralLoanInfoPage::initialFocusWidget() const + { + Q_D(const GeneralLoanInfoPage); + return d->ui->m_loanDirection; + } + + void GeneralLoanInfoPage::slotLoadWidgets() + { + Q_D(GeneralLoanInfoPage); + d->ui->m_payee->loadPayees(MyMoneyFile::instance()->payeeList()); + } + +} diff --git a/kmymoney/wizards/wizardpages/currency.cpp b/kmymoney/wizards/newaccountwizard/kgeneralloaninfopage.h similarity index 50% copy from kmymoney/wizards/wizardpages/currency.cpp copy to kmymoney/wizards/newaccountwizard/kgeneralloaninfopage.h index 5bcaf7fff..42ee685df 100644 --- a/kmymoney/wizards/wizardpages/currency.cpp +++ b/kmymoney/wizards/newaccountwizard/kgeneralloaninfopage.h @@ -1,70 +1,75 @@ /*************************************************************************** - userinfo.cpp + kgeneralloaninfopage.h ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "currency.h" +#ifndef KNEWACCOUNTWIZARDGENERALLOANINFOPAGE_H +#define KNEWACCOUNTWIZARDGENERALLOANINFOPAGE_H // ---------------------------------------------------------------------------- // QT Includes -#include -#include +#include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneysecurity.h" +#include "wizardpage.h" -Currency::Currency(QWidget* parent) : - CurrencyDecl(parent) -{ - m_currencyList->setAllColumnsShowFocus(true); - m_currencyList->setColumnWidth(0, size().width()*6 / 10); -} +class MyMoneyAccount; -QTreeWidgetItem* Currency::insertCurrency(const MyMoneySecurity& sec) +namespace NewAccountWizard { - QStringList item = QStringList(); - item.append(sec.name()); - item.append(QString(sec.id())); - item.append(sec.tradingSymbol()); + class Wizard; - return new QTreeWidgetItem(m_currencyList, item); -} + class GeneralLoanInfoPagePrivate; + class GeneralLoanInfoPage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(GeneralLoanInfoPage) -void Currency::selectCurrency(const MyMoneySecurity& sec) -{ - QList selectedItems = m_currencyList->findItems(sec.id(), Qt::MatchExactly, 1); - QList::iterator itemIt = selectedItems.begin(); - while (itemIt != selectedItems.end()) { - (*itemIt)->setSelected(true); - m_currencyList->scrollToItem(*itemIt); - } -} + public: + explicit GeneralLoanInfoPage(Wizard* parent); + ~GeneralLoanInfoPage() override; + KMyMoneyWizardPage* nextPage() const; + virtual bool isComplete() const; + void enterPage(); + const MyMoneyAccount& parentAccount(); -QString Currency::selectedCurrency() const -{ - QString id; + QWidget* initialFocusWidget() const override; + + /** + * Returns @p true if the user decided to record all payments, @p false otherwise. + */ + bool recordAllPayments() const; + + private slots: + void slotLoadWidgets(); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, GeneralLoanInfoPage) + friend class Wizard; + friend class AccountSummaryPage; + friend class LoanDetailsPage; + friend class LoanSchedulePage; + friend class WizardPrivate; + }; +} // namespace - if (m_currencyList->selectedItems().size() > 0) { - id = m_currencyList->selectedItems().at(0)->text(1); - } - return id; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/kgeneralloaninfopagedecl.ui b/kmymoney/wizards/newaccountwizard/kgeneralloaninfopage.ui similarity index 99% rename from kmymoney/wizards/newaccountwizard/kgeneralloaninfopagedecl.ui rename to kmymoney/wizards/newaccountwizard/kgeneralloaninfopage.ui index 7e47a7e8b..412fb6606 100644 --- a/kmymoney/wizards/newaccountwizard/kgeneralloaninfopagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/kgeneralloaninfopage.ui @@ -1,375 +1,375 @@ - KGeneralLoanInfoPageDecl - + KGeneralLoanInfoPage + 0 0 675 494 Qt::NoFocus Please select the required options. Please use the <b>What's this?</b> feature to see more information about the items. true What is the type of the loan? false I am borrowing money I am lending money Who is the payee/payer of the loan? false Enter the name of the person or bank you owe money or who owes you money. If the name does not exist within KMyMoney's database, you are asked if you want to create it. Did you make/receive any payments yet? false Were there any payments for this loan whether they are entered into KMyMoney or not? Note: Payments made to obtain the loan (e.g. Disagio) are not considered as payments in this context. No Yes Which payments do you want to record? false <qt>Select which transactions should be recorded. <b>All payments</b> allows you to enter all payments made for this loan. The option to <b>start from the beginning of the current year</b> is meant for loans that have already been active for a longer period of time, and for which you do not want to enter all past transactions. </qt> All payments Start with this year's payments Balance before start of recording Enter the ending balance found on the statement that is the last one before you want to start recording this loan in KMyMoney. false You have selected to record only payments from the beginning of this year. Since prior transactions will not be recorded, you need to supply the balance of the loan on January 1st of this year. Payment frequency false Qt::TabFocus Interest Compounding frequency false Select the frequency with which the interest is compounded. If uncertain, select the same as the payment frequency. Consult your loan contract for details. Due date of first payment to be recorded false Qt::StrongFocus Depending on the answer to <b>What do you want to record?</b> this field means the following:<p> <b>All payments</b><br> Enter the due date of the very first payment<p> <b>Start with this year's payments</b><br> Enter the due date of the first payment in the current year Type of interest rate false Fixed Variable Time between interest changes false 1 999 3 Days Weeks Months Years Next interest change is due false Qt::StrongFocus 29 20 QSizePolicy::Expanding Qt::Horizontal 20 16 QSizePolicy::Expanding Qt::Vertical KComboBox QComboBox
kcombobox.h
QSpinBox QSpinBox
knuminput.h
KMyMoneyPayeeCombo QWidget
kmymoneypayeecombo.h
1
KMyMoneyFrequencyCombo QWidget
kmymoneyfrequencycombo.h
1
diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kgeneralloaninfopage_p.h similarity index 60% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kgeneralloaninfopage_p.h index 473078b58..ce372682d 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kgeneralloaninfopage_p.h @@ -1,49 +1,60 @@ /*************************************************************************** - userinfo.cpp + kgeneralloaninfopage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDGENERALLOANINFOPAGE_P_H +#define KNEWACCOUNTWIZARDGENERALLOANINFOPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_kgeneralloaninfopage.h" +#include "wizardpage_p.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); + class Wizard; + + class GeneralLoanInfoPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(GeneralLoanInfoPagePrivate) + + public: + GeneralLoanInfoPagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KGeneralLoanInfoPage) + { + } + + ~GeneralLoanInfoPagePrivate() + { + delete ui; + } + + Ui::KGeneralLoanInfoPage *ui; + bool m_firstTime; + }; } -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/khierarchypage.cpp b/kmymoney/wizards/newaccountwizard/khierarchypage.cpp new file mode 100644 index 000000000..0f96673a3 --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/khierarchypage.cpp @@ -0,0 +1,127 @@ +/*************************************************************************** + khierarchypage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "khierarchypage.h" +#include "khierarchypage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_khierarchypage.h" + +#include "accountsmodel.h" +#include "hierarchyfilterproxymodel.h" +#include "kmymoneyaccounttreeview.h" +#include "kmymoneyglobalsettings.h" +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "kaccountsummarypage.h" +#include "kaccounttypepage.h" +#include "khierarchypage_p.h" +#include "modelenums.h" +#include "models.h" +#include "mymoneyaccount.h" +#include "mymoneyenums.h" +#include "wizardpage.h" + +using namespace eMyMoney; + +namespace NewAccountWizard +{ + HierarchyPage::HierarchyPage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new HierarchyPagePrivate(wizard), StepParentAccount, this, wizard) + { + Q_D(HierarchyPage); + d->ui->setupUi(this); + d->m_filterProxyModel = nullptr; + // the proxy filter model + d->m_filterProxyModel = new HierarchyFilterProxyModel(this); + d->m_filterProxyModel->setHideClosedAccounts(true); + d->m_filterProxyModel->setHideEquityAccounts(!KMyMoneyGlobalSettings::expertMode()); + d->m_filterProxyModel->addAccountGroup(QVector {Account::Asset, Account::Liability}); + auto const model = Models::instance()->accountsModel(); + d->m_filterProxyModel->setSourceModel(model); + d->m_filterProxyModel->setSourceColumns(model->getColumns()); + d->m_filterProxyModel->setDynamicSortFilter(true); + + d->ui->m_parentAccounts->setModel(d->m_filterProxyModel); + d->ui->m_parentAccounts->sortByColumn((int)eAccountsModel::Column::Account, Qt::AscendingOrder); + + connect(d->ui->m_parentAccounts->selectionModel(), &QItemSelectionModel::currentChanged, this, &HierarchyPage::parentAccountChanged); + } + + HierarchyPage::~HierarchyPage() + { + } + + void HierarchyPage::enterPage() + { + Q_D(HierarchyPage); + // Ensure that the list reflects the Account Type + MyMoneyAccount topAccount = d->m_wizard->d_func()->m_accountTypePage->parentAccount(); + d->m_filterProxyModel->clear(); + d->m_filterProxyModel->addAccountGroup(QVector {topAccount.accountGroup()}); + d->ui->m_parentAccounts->expandAll(); + } + + KMyMoneyWizardPage* HierarchyPage::nextPage() const + { + Q_D(const HierarchyPage); + return d->m_wizard->d_func()->m_accountSummaryPage; + } + + QWidget* HierarchyPage::initialFocusWidget() const + { + Q_D(const HierarchyPage); + return d->ui->m_parentAccounts; + } + + const MyMoneyAccount& HierarchyPage::parentAccount() + { + Q_D(HierarchyPage); + QVariant data = d->ui->m_parentAccounts->model()->data(d->ui->m_parentAccounts->currentIndex(), (int)eAccountsModel::Role::Account); + if (data.isValid()) { + d->m_parentAccount = data.value(); + } else { + d->m_parentAccount = MyMoneyAccount(); + } + return d->m_parentAccount; + } + + bool HierarchyPage::isComplete() const + { + Q_D(const HierarchyPage); + return d->ui->m_parentAccounts->currentIndex().isValid(); + } + + void HierarchyPage::parentAccountChanged() + { + completeStateChanged(); + } +} diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/khierarchypage.h similarity index 56% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/khierarchypage.h index 473078b58..b56f433ee 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/khierarchypage.h @@ -1,49 +1,69 @@ /*************************************************************************** - userinfo.cpp + khierarchypage.h ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDHIERACHRYPAGE_H +#define KNEWACCOUNTWIZARDHIERACHRYPAGE_H // ---------------------------------------------------------------------------- // QT Includes +#include + // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "wizardpage.h" +class MyMoneyAccount; -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); -} + class Wizard; + class HierarchyFilterProxyModel; -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} + class HierarchyPagePrivate; + class HierarchyPage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(HierarchyPage) + + public: + explicit HierarchyPage(Wizard* parent); + ~HierarchyPage() override; + + void enterPage(); + KMyMoneyWizardPage* nextPage() const; + QWidget* initialFocusWidget() const override; + const MyMoneyAccount& parentAccount(); + + bool isComplete() const; + + protected slots: + void parentAccountChanged(); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, HierarchyPage) + friend class Wizard; + friend class AccountSummaryPage; + }; + +} // namespace + +#endif diff --git a/kmymoney/wizards/newaccountwizard/khierarchypagedecl.ui b/kmymoney/wizards/newaccountwizard/khierarchypage.ui similarity index 95% rename from kmymoney/wizards/newaccountwizard/khierarchypagedecl.ui rename to kmymoney/wizards/newaccountwizard/khierarchypage.ui index 43b305d42..d3706f3c8 100644 --- a/kmymoney/wizards/newaccountwizard/khierarchypagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/khierarchypage.ui @@ -1,74 +1,74 @@ - KHierarchyPageDecl - + KHierarchyPage + 0 0 674 419 0 0 Qt::NoFocus This page allows you to select the parent account. true Subaccount of false Qt::Vertical QSizePolicy::Preferred 20 30 KMyMoneyAccountTreeView QTreeView
kmymoneyaccounttreeview.h
diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/khierarchypage_p.h similarity index 58% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/khierarchypage_p.h index 473078b58..f3c9c1721 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/khierarchypage_p.h @@ -1,49 +1,63 @@ /*************************************************************************** - userinfo.cpp + khierarchypage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDHIERACHRYPAGE_P_H +#define KNEWACCOUNTWIZARDHIERACHRYPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_khierarchypage.h" +#include "wizardpage_p.h" +#include "mymoneyaccount.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); + class Wizard; + class HierarchyFilterProxyModel; + + class HierarchyPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(HierarchyPagePrivate) + + public: + HierarchyPagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KHierarchyPage) + { + } + + ~HierarchyPagePrivate() + { + delete ui; + } + + Ui::KHierarchyPage *ui; + HierarchyFilterProxyModel *m_filterProxyModel; + MyMoneyAccount m_parentAccount; + }; } -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/kinstitutionpage.cpp b/kmymoney/wizards/newaccountwizard/kinstitutionpage.cpp new file mode 100644 index 000000000..b538ee601 --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kinstitutionpage.cpp @@ -0,0 +1,147 @@ +/*************************************************************************** + kinstitutionpage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kinstitutionpage.h" +#include "kinstitutionpage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kinstitutionpage.h" + +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "kaccounttypepage.h" +#include "kinstitutionpage_p.h" +#include "mymoneyfile.h" +#include "mymoneyinstitution.h" +#include "wizardpage.h" + +namespace NewAccountWizard +{ + InstitutionPage::InstitutionPage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new InstitutionPagePrivate(wizard),StepInstitution, this, wizard) + { + Q_D(InstitutionPage); + d->ui->setupUi(this); + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &InstitutionPage::slotLoadWidgets); + connect(d_func()->ui->m_newInstitutionButton, &QAbstractButton::clicked, this, &InstitutionPage::slotNewInstitution); + connect(d_func()->ui->m_institutionComboBox, static_cast(&QComboBox::activated), this, &InstitutionPage::slotSelectInstitution); + + slotLoadWidgets(); + d_func()->ui->m_institutionComboBox->setCurrentItem(0); + slotSelectInstitution(0); + } + + InstitutionPage::~InstitutionPage() + { + } + + void InstitutionPage::slotLoadWidgets() + { + Q_D(InstitutionPage); + d_func()->ui->m_institutionComboBox->clear(); + + d->m_list.clear(); + MyMoneyFile::instance()->institutionList(d->m_list); + qSort(d->m_list); + + QList::const_iterator it_l; + d->ui->m_institutionComboBox->addItem(QString()); + for (it_l = d->m_list.constBegin(); it_l != d->m_list.constEnd(); ++it_l) { + d->ui->m_institutionComboBox->addItem((*it_l).name()); + } + } + + void InstitutionPage::slotNewInstitution() + { + Q_D(InstitutionPage); + MyMoneyInstitution institution; + + emit d->m_wizard->createInstitution(institution); + + if (!institution.id().isEmpty()) { + QList::const_iterator it_l; + int i = 0; + for (it_l = d->m_list.constBegin(); it_l != d->m_list.constEnd(); ++it_l) { + if ((*it_l).id() == institution.id()) { + // select the item and remember that the very first one is the empty item + d->ui->m_institutionComboBox->setCurrentIndex(i + 1); + slotSelectInstitution(i + 1); + d->ui->m_accountNumber->setFocus(); + break; + } + ++i; + } + } + } + + void InstitutionPage::slotSelectInstitution(const int index) + { + Q_D(InstitutionPage); + d->ui->m_accountNumber->setEnabled(index != 0); + d->ui->m_iban->setEnabled(index != 0); + } + + void InstitutionPage::selectExistingInstitution(const QString& id) + { + Q_D(InstitutionPage); + for (int i = 0; i < d->m_list.length(); ++i) { + if (d->m_list[i].id() == id) { + d->ui->m_institutionComboBox->setCurrentIndex(i + 1); + slotSelectInstitution(i + 1); + break; + } + } + } + + const MyMoneyInstitution& InstitutionPage::institution() const + { + Q_D(const InstitutionPage); + static MyMoneyInstitution emptyInstitution; + if (d->ui->m_institutionComboBox->currentIndex() == 0) + return emptyInstitution; + + return d->m_list[d->ui->m_institutionComboBox->currentIndex()-1]; + } + + KMyMoneyWizardPage* InstitutionPage::nextPage() const + { + Q_D(const InstitutionPage); + return d->m_wizard->d_func()->m_accountTypePage; + } + + QWidget* InstitutionPage::initialFocusWidget() const + { + Q_D(const InstitutionPage); + return d->ui->m_institutionComboBox; + } +} diff --git a/kmymoney/wizards/wizardpages/currency.cpp b/kmymoney/wizards/newaccountwizard/kinstitutionpage.h similarity index 50% copy from kmymoney/wizards/wizardpages/currency.cpp copy to kmymoney/wizards/newaccountwizard/kinstitutionpage.h index 5bcaf7fff..9cfb6db65 100644 --- a/kmymoney/wizards/wizardpages/currency.cpp +++ b/kmymoney/wizards/newaccountwizard/kinstitutionpage.h @@ -1,70 +1,75 @@ /*************************************************************************** - userinfo.cpp + kinstitutionpage.h ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "currency.h" +#ifndef KNEWACCOUNTWIZARDINSTITUTION_H +#define KNEWACCOUNTWIZARDINSTITUTION_H // ---------------------------------------------------------------------------- // QT Includes -#include -#include +#include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneysecurity.h" +#include "wizardpage.h" -Currency::Currency(QWidget* parent) : - CurrencyDecl(parent) -{ - m_currencyList->setAllColumnsShowFocus(true); - m_currencyList->setColumnWidth(0, size().width()*6 / 10); -} +class MyMoneyInstitution; -QTreeWidgetItem* Currency::insertCurrency(const MyMoneySecurity& sec) +namespace NewAccountWizard { - QStringList item = QStringList(); - item.append(sec.name()); - item.append(QString(sec.id())); - item.append(sec.tradingSymbol()); + class Wizard; - return new QTreeWidgetItem(m_currencyList, item); -} + class InstitutionPagePrivate; + class InstitutionPage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(InstitutionPage) -void Currency::selectCurrency(const MyMoneySecurity& sec) -{ - QList selectedItems = m_currencyList->findItems(sec.id(), Qt::MatchExactly, 1); - QList::iterator itemIt = selectedItems.begin(); - while (itemIt != selectedItems.end()) { - (*itemIt)->setSelected(true); - m_currencyList->scrollToItem(*itemIt); - } -} + public: + explicit InstitutionPage(Wizard* parent); + ~InstitutionPage() override; + KMyMoneyWizardPage* nextPage() const; + QWidget* initialFocusWidget() const override; -QString Currency::selectedCurrency() const -{ - QString id; + /** + * Returns the information about an institution if entered by + * the user. If the id field is empty, then he did not enter + * such information. + */ + const MyMoneyInstitution& institution() const; + + void selectExistingInstitution(const QString& id); + + private slots: + void slotLoadWidgets(); + void slotNewInstitution(); + void slotSelectInstitution(int index); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, InstitutionPage) + friend class Wizard; + friend class AccountSummaryPage; + friend class BrokeragePage; + }; +} // namespace - if (m_currencyList->selectedItems().size() > 0) { - id = m_currencyList->selectedItems().at(0)->text(1); - } - return id; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/kinstitutionpagedecl.ui b/kmymoney/wizards/newaccountwizard/kinstitutionpage.ui similarity index 98% rename from kmymoney/wizards/newaccountwizard/kinstitutionpagedecl.ui rename to kmymoney/wizards/newaccountwizard/kinstitutionpage.ui index ad1583005..c33f738f3 100644 --- a/kmymoney/wizards/newaccountwizard/kinstitutionpagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/kinstitutionpage.ui @@ -1,161 +1,161 @@ - KInstitutionPageDecl - + KInstitutionPage + 0 0 586 322 -1 10 Qt::NoFocus If this account is managed by an institution please select the institution from the list. If the institution does not exist yet, please choose the <b>New Institution</b> button to create it. Otherwise, leave this field empty. Enter the account number used by the institution to identify the account. true -1 Institution false Select the institution which manages this account or leave empty New Institution Account number false Accounts managed by an institution are usually referenced by a unique number the so called account number. Enter that number here. KMyMoney currently uses this number only for some online banking functions. IBAN false Enter the International Bank Account Number into this field You can enter the IBAN (International Bank Account Number) into this field if you know it. Usually, people at your institution can tell you the number or it is printed on your statements. See also http://en.wikipedia.org/wiki/International_Bank_Account_Number for more information. KMyMoney keeps this field only for documentation purposes and does not use it otherwise. Qt::Horizontal QSizePolicy::Expanding 132 20 Qt::Vertical QSizePolicy::Expanding 20 40 KLineEdit QLineEdit
klineedit.h
KComboBox QComboBox
kcombobox.h
diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kinstitutionpage_p.h similarity index 60% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kinstitutionpage_p.h index 473078b58..bf9a59508 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kinstitutionpage_p.h @@ -1,49 +1,61 @@ /*************************************************************************** - userinfo.cpp + kinstitutionpage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDINSTITUTION_P_H +#define KNEWACCOUNTWIZARDINSTITUTION_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_kinstitutionpage.h" +#include "wizardpage_p.h" +#include "mymoneyinstitution.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); + class Wizard; + + class InstitutionPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(InstitutionPagePrivate) + + public: + InstitutionPagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KInstitutionPage) + { + } + + ~InstitutionPagePrivate() + { + delete ui; + } + + Ui::KInstitutionPage *ui; + QList m_list; + }; } -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/kloandetailspage.cpp b/kmymoney/wizards/newaccountwizard/kloandetailspage.cpp new file mode 100644 index 000000000..470f3a9f5 --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kloandetailspage.cpp @@ -0,0 +1,425 @@ +/*************************************************************************** + kloandetailspage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kloandetailspage.h" +#include "kloandetailspage_p.h" + +#include + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kgeneralloaninfopage.h" +#include "ui_kloandetailspage.h" + +#include "kmymoneyedit.h" +#include "kmymoneyfrequencycombo.h" +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "kgeneralloaninfopage.h" +#include "kgeneralloaninfopage_p.h" +#include "kloandetailspage_p.h" +#include "kloanpaymentpage.h" +#include "mymoneyenums.h" +#include "mymoneyexception.h" +#include "mymoneyfinancialcalculator.h" +#include "mymoneymoney.h" +#include "wizardpage.h" +#include "kguiutils.h" + +using namespace eMyMoney; + +namespace NewAccountWizard +{ + LoanDetailsPage::LoanDetailsPage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new LoanDetailsPagePrivate(wizard), StepPayments, this, wizard) + { + Q_D(LoanDetailsPage); + d->m_needCalculate = true; + d->ui->setupUi(this); + // force the balloon payment to zero (default) + d->ui->m_balloonAmount->setValue(MyMoneyMoney()); + // allow any precision for the interest rate + d->ui->m_interestRate->setPrecision(-1); + + connect(d->ui->m_paymentDue, static_cast(&QComboBox::activated), this, &LoanDetailsPage::slotValuesChanged); + + connect(d->ui->m_termAmount, static_cast(&QSpinBox::valueChanged), this, &LoanDetailsPage::slotValuesChanged); + connect(d->ui->m_termUnit, static_cast(&QComboBox::highlighted), this, &LoanDetailsPage::slotValuesChanged); + connect(d->ui->m_loanAmount, &KMyMoneyEdit::textChanged, this, &LoanDetailsPage::slotValuesChanged); + connect(d->ui->m_interestRate, &KMyMoneyEdit::textChanged, this, &LoanDetailsPage::slotValuesChanged); + connect(d->ui->m_paymentAmount, &KMyMoneyEdit::textChanged, this, &LoanDetailsPage::slotValuesChanged); + connect(d->ui->m_balloonAmount, &KMyMoneyEdit::textChanged, this, &LoanDetailsPage::slotValuesChanged); + + connect(d->ui->m_calculateButton, &QAbstractButton::clicked, this, &LoanDetailsPage::slotCalculate); + } + + LoanDetailsPage::~LoanDetailsPage() + { + } + + void LoanDetailsPage::enterPage() + { + Q_D(LoanDetailsPage); + // we need to remove a bunch of entries of the payment frequencies + d->ui->m_termUnit->clear(); + + d->m_mandatoryGroup->clear(); + if (!d->m_wizard->openingBalance().isZero()) { + d->m_mandatoryGroup->add(d->ui->m_loanAmount->lineedit()); + if (d->ui->m_loanAmount->lineedit()->text().length() == 0) { + d->ui->m_loanAmount->setValue(d->m_wizard->openingBalance().abs()); + } + } + + switch (d->m_wizard->d_func()->m_generalLoanInfoPage->d_func()->ui->m_paymentFrequency->currentItem()) { + default: + d->ui->m_termUnit->insertItem(i18n("Payments"), (int)Schedule::Occurrence::Once); + d->ui->m_termUnit->setCurrentItem((int)Schedule::Occurrence::Once); + break; + case Schedule::Occurrence::Monthly: + d->ui->m_termUnit->insertItem(i18n("Months"), (int)Schedule::Occurrence::Monthly); + d->ui->m_termUnit->insertItem(i18n("Years"), (int)Schedule::Occurrence::Yearly); + d->ui->m_termUnit->setCurrentItem((int)Schedule::Occurrence::Monthly); + break; + case Schedule::Occurrence::Yearly: + d->ui->m_termUnit->insertItem(i18n("Years"), (int)Schedule::Occurrence::Yearly); + d->ui->m_termUnit->setCurrentItem((int)Schedule::Occurrence::Yearly); + break; + } + } + + void LoanDetailsPage::slotValuesChanged() + { + Q_D(LoanDetailsPage); + d->m_needCalculate = true; + d->m_wizard->completeStateChanged(); + } + + void LoanDetailsPage::slotCalculate() + { + Q_D(LoanDetailsPage); + MyMoneyFinancialCalculator calc; + double val; + int PF, CF; + QString result; + bool moneyBorrowed = d->m_wizard->moneyBorrowed(); + bool moneyLend = !moneyBorrowed; + + // FIXME: for now, we only support interest calculation at the end of the period + calc.setBep(); + // FIXME: for now, we only support periodic compounding + calc.setDisc(); + + PF = d->m_wizard->d_func()->m_generalLoanInfoPage->d_func()->ui->m_paymentFrequency->eventsPerYear(); + CF = d->m_wizard->d_func()->m_generalLoanInfoPage->d_func()->ui->m_compoundFrequency->eventsPerYear(); + + if (PF == 0 || CF == 0) + return; + + calc.setPF(PF); + calc.setCF(CF); + + + if (!d->ui->m_loanAmount->lineedit()->text().isEmpty()) { + val = d->ui->m_loanAmount->value().abs().toDouble(); + if (moneyBorrowed) + val = -val; + calc.setPv(val); + } + + if (!d->ui->m_interestRate->lineedit()->text().isEmpty()) { + val = d->ui->m_interestRate->value().abs().toDouble(); + calc.setIr(val); + } + + if (!d->ui->m_paymentAmount->lineedit()->text().isEmpty()) { + val = d->ui->m_paymentAmount->value().abs().toDouble(); + if (moneyLend) + val = -val; + calc.setPmt(val); + } + + if (!d->ui->m_balloonAmount->lineedit()->text().isEmpty()) { + val = d->ui->m_balloonAmount->value().abs().toDouble(); + if (moneyLend) + val = -val; + calc.setFv(val); + } + + if (d->ui->m_termAmount->value() != 0) { + calc.setNpp(term()); + } + + // setup of parameters is done, now do the calculation + try { + if (d->ui->m_loanAmount->lineedit()->text().isEmpty()) { + // calculate the amount of the loan out of the other information + val = calc.presentValue(); + d->ui->m_loanAmount->loadText(MyMoneyMoney(static_cast(val)).abs().formatMoney(QString(), d->m_wizard->d_func()->precision())); + result = i18n("KMyMoney has calculated the amount of the loan as %1.", d->ui->m_loanAmount->lineedit()->text()); + + } else if (d->ui->m_interestRate->lineedit()->text().isEmpty()) { + // calculate the interest rate out of the other information + val = calc.interestRate(); + + d->ui->m_interestRate->loadText(MyMoneyMoney(static_cast(val)).abs().formatMoney(QString(), 3)); + result = i18n("KMyMoney has calculated the interest rate to %1%.", d->ui->m_interestRate->lineedit()->text()); + + } else if (d->ui->m_paymentAmount->lineedit()->text().isEmpty()) { + // calculate the periodical amount of the payment out of the other information + val = calc.payment(); + d->ui->m_paymentAmount->setValue(MyMoneyMoney(static_cast(val)).abs()); + // reset payment as it might have changed due to rounding + val = d->ui->m_paymentAmount->value().abs().toDouble(); + if (moneyLend) + val = -val; + calc.setPmt(val); + + result = i18n("KMyMoney has calculated a periodic payment of %1 to cover principal and interest.", d->ui->m_paymentAmount->lineedit()->text()); + + val = calc.futureValue(); + if ((moneyBorrowed && val < 0 && qAbs(val) >= qAbs(calc.payment())) + || (moneyLend && val > 0 && qAbs(val) >= qAbs(calc.payment()))) { + calc.setNpp(calc.npp() - 1); + // updateTermWidgets(calc.npp()); + val = calc.futureValue(); + MyMoneyMoney refVal(static_cast(val)); + d->ui->m_balloonAmount->loadText(refVal.abs().formatMoney(QString(), d->m_wizard->d_func()->precision())); + result += QString(" "); + result += i18n("The number of payments has been decremented and the balloon payment has been modified to %1.", d->ui->m_balloonAmount->lineedit()->text()); + } else if ((moneyBorrowed && val < 0 && qAbs(val) < qAbs(calc.payment())) + || (moneyLend && val > 0 && qAbs(val) < qAbs(calc.payment()))) { + d->ui->m_balloonAmount->loadText(MyMoneyMoney().formatMoney(QString(), d->m_wizard->d_func()->precision())); + } else { + MyMoneyMoney refVal(static_cast(val)); + d->ui->m_balloonAmount->loadText(refVal.abs().formatMoney(QString(), d->m_wizard->d_func()->precision())); + result += i18n("The balloon payment has been modified to %1.", d->ui->m_balloonAmount->lineedit()->text()); + } + + } else if (d->ui->m_termAmount->value() == 0) { + // calculate the number of payments out of the other information + val = calc.numPayments(); + if (val == 0) + throw MYMONEYEXCEPTION("incorrect fincancial calculation"); + + // if the number of payments has a fractional part, then we + // round it to the smallest integer and calculate the balloon payment + result = i18n("KMyMoney has calculated the term of your loan as %1. ", updateTermWidgets(qFloor(val))); + + if (val != qFloor(val)) { + calc.setNpp(qFloor(val)); + val = calc.futureValue(); + MyMoneyMoney refVal(static_cast(val)); + d->ui->m_balloonAmount->loadText(refVal.abs().formatMoney(QString(), d->m_wizard->d_func()->precision())); + result += i18n("The balloon payment has been modified to %1.", d->ui->m_balloonAmount->lineedit()->text()); + } + + } else { + // calculate the future value of the loan out of the other information + val = calc.futureValue(); + + // we differentiate between the following cases: + // a) the future value is greater than a payment + // b) the future value is less than a payment or the loan is overpaid + // c) all other cases + // + // a) means, we have paid more than we owed. This can't be + // b) means, we paid more than we owed but the last payment is + // less in value than regular payments. That means, that the + // future value is to be treated as (fully payed back) + // c) the loan is not payed back yet + if ((moneyBorrowed && val < 0 && qAbs(val) > qAbs(calc.payment())) + || (moneyLend && val > 0 && qAbs(val) > qAbs(calc.payment()))) { + // case a) + qDebug("Future Value is %f", val); + throw MYMONEYEXCEPTION("incorrect fincancial calculation"); + + } else if ((moneyBorrowed && val < 0 && qAbs(val) <= qAbs(calc.payment())) + || (moneyLend && val > 0 && qAbs(val) <= qAbs(calc.payment()))) { + // case b) + val = 0; + } + + MyMoneyMoney refVal(static_cast(val)); + result = i18n("KMyMoney has calculated a balloon payment of %1 for this loan.", refVal.abs().formatMoney(QString(), d->m_wizard->d_func()->precision())); + + if (!d->ui->m_balloonAmount->lineedit()->text().isEmpty()) { + if ((d->ui->m_balloonAmount->value().abs() - refVal.abs()).abs().toDouble() > 1) { + throw MYMONEYEXCEPTION("incorrect fincancial calculation"); + } + result = i18n("KMyMoney has successfully verified your loan information."); + } + d->ui->m_balloonAmount->loadText(refVal.abs().formatMoney(QString(), d->m_wizard->d_func()->precision())); + } + + } catch (const MyMoneyException &) { + KMessageBox::error(0, + i18n("You have entered mis-matching information. Please modify " + "your figures or leave one value empty " + "to let KMyMoney calculate it for you"), + i18n("Calculation error")); + return; + } + + result += i18n("\n\nAccept this or modify the loan information and recalculate."); + + KMessageBox::information(0, result, i18n("Calculation successful")); + d->m_needCalculate = false; + + // now update change + d->m_wizard->completeStateChanged(); + } + + int LoanDetailsPage::term() const + { + Q_D(const LoanDetailsPage); + int factor = 0; + + if (d->ui->m_termAmount->value() != 0) { + factor = 1; + switch (d->ui->m_termUnit->currentItem()) { + case Schedule::Occurrence::Yearly: // years + factor = 12; + // intentional fall through + + case Schedule::Occurrence::Monthly: // months + factor *= 30; + factor *= d->ui->m_termAmount->value(); + // factor now is the duration in days. we divide this by the + // payment frequency and get the number of payments + factor /= d->m_wizard->d_func()->m_generalLoanInfoPage->d_func()->ui->m_paymentFrequency->daysBetweenEvents(); + break; + + default: + qDebug("Unknown term unit %d in LoanDetailsPage::term(). Using payments.", (int)d->ui->m_termUnit->currentItem()); + // intentional fall through + + case Schedule::Occurrence::Once: // payments + factor = d->ui->m_termAmount->value(); + break; + } + } + return factor; + } + + QString LoanDetailsPage::updateTermWidgets(const double val) + { + Q_D(LoanDetailsPage); + long vl = qFloor(val); + + QString valString; + Schedule::Occurrence unit = d->ui->m_termUnit->currentItem(); + + if ((unit == Schedule::Occurrence::Monthly) + && ((vl % 12) == 0)) { + vl /= 12; + unit = Schedule::Occurrence::Yearly; + } + + switch (unit) { + case Schedule::Occurrence::Monthly: + valString = i18np("one month", "%1 months", vl); + d->ui->m_termUnit->setCurrentItem((int)Schedule::Occurrence::Monthly); + break; + case Schedule::Occurrence::Yearly: + valString = i18np("one year", "%1 years", vl); + d->ui->m_termUnit->setCurrentItem((int)Schedule::Occurrence::Yearly); + break; + default: + valString = i18np("one payment", "%1 payments", vl); + d->ui->m_termUnit->setCurrentItem((int)Schedule::Occurrence::Once); + break; + } + d->ui->m_termAmount->setValue(vl); + return valString; + } + + bool LoanDetailsPage::isComplete() const + { + Q_D(const LoanDetailsPage); + // bool rc = KMyMoneyWizardPage::isComplete(); + + int fieldCnt = 0; + + if (d->ui->m_loanAmount->lineedit()->text().length() > 0) { + fieldCnt++; + } + + if (d->ui->m_interestRate->lineedit()->text().length() > 0) { + fieldCnt++; + } + + if (d->ui->m_termAmount->value() != 0) { + fieldCnt++; + } + + if (d->ui->m_paymentAmount->lineedit()->text().length() > 0) { + fieldCnt++; + } + + if (d->ui->m_balloonAmount->lineedit()->text().length() > 0) { + fieldCnt++; + } + + d->ui->m_calculateButton->setEnabled(fieldCnt == 4 || (fieldCnt == 5 && d->m_needCalculate)); + + d->ui->m_calculateButton->setAutoDefault(false); + d->ui->m_calculateButton->setDefault(false); + if (d->m_needCalculate && fieldCnt == 4) { + d->m_wizard->d_func()->m_nextButton->setToolTip(i18n("Press Calculate to verify the values")); + d->ui->m_calculateButton->setAutoDefault(true); + d->ui->m_calculateButton->setDefault(true); + } else if (fieldCnt != 5) { + d->m_wizard->d_func()->m_nextButton->setToolTip(i18n("Not all details supplied")); + d->ui->m_calculateButton->setAutoDefault(true); + d->ui->m_calculateButton->setDefault(true); + } + d->m_wizard->d_func()->m_nextButton->setAutoDefault(!d->ui->m_calculateButton->autoDefault()); + d->m_wizard->d_func()->m_nextButton->setDefault(!d->ui->m_calculateButton->autoDefault()); + + return (fieldCnt == 5) && !d->m_needCalculate; + } + + QWidget* LoanDetailsPage::initialFocusWidget() const + { + Q_D(const LoanDetailsPage); + return d->ui->m_paymentDue; + } + + KMyMoneyWizardPage* LoanDetailsPage::nextPage() const + { + Q_D(const LoanDetailsPage); + return d->m_wizard->d_func()->m_loanPaymentPage; + } +} diff --git a/kmymoney/wizards/newaccountwizard/kloandetailspage.h b/kmymoney/wizards/newaccountwizard/kloandetailspage.h new file mode 100644 index 000000000..cd794e4bf --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kloandetailspage.h @@ -0,0 +1,80 @@ +/*************************************************************************** + kloandetailspage.h + ------------------- + begin : Tue Sep 25 2007 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KNEWACCOUNTWIZARDLOANDETAILSPAGE_H +#define KNEWACCOUNTWIZARDLOANDETAILSPAGE_H + +// ---------------------------------------------------------------------------- +// QT Includes + +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "wizardpage.h" + +namespace NewAccountWizard +{ + class Wizard; + + class LoanDetailsPagePrivate; + class LoanDetailsPage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(LoanDetailsPage) + + public: + explicit LoanDetailsPage(Wizard* parent); + ~LoanDetailsPage() override; + + void enterPage(); + KMyMoneyWizardPage* nextPage() const; + virtual bool isComplete() const; + + QWidget* initialFocusWidget() const override; + + /** + * This method returns the number of payments depending on + * the settings of m_termAmount and m_termUnit widgets + */ + int term() const; + + private: + /** + * This method is used to update the term widgets + * according to the length of the given @a term. + * The term is also converted into a string and returned. + */ + QString updateTermWidgets(const double term); + + private slots: + void slotValuesChanged(); + void slotCalculate(); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, LoanDetailsPage) + friend class Wizard; + friend class AccountSummaryPage; + friend class LoanPaymentPage; + }; +} // namespace + +#endif diff --git a/kmymoney/wizards/newaccountwizard/kloandetailspagedecl.ui b/kmymoney/wizards/newaccountwizard/kloandetailspage.ui similarity index 99% rename from kmymoney/wizards/newaccountwizard/kloandetailspagedecl.ui rename to kmymoney/wizards/newaccountwizard/kloandetailspage.ui index 4413e2b03..1fbfd29df 100644 --- a/kmymoney/wizards/newaccountwizard/kloandetailspagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/kloandetailspage.ui @@ -1,278 +1,278 @@ - KLoanDetailsPageDecl - + KLoanDetailsPage + 0 0 592 434 Qt::NoFocus Now enter the details for your loan. You can leave one of the fields empty and KMyMoney will calculate it when you press the <b>Calculate</b> button. Before you can continue with the next page you also need to press <b>Calculate</b> so that KMyMoney can check the logical correctness of the values you have supplied. true 20 70 QSizePolicy::Expanding Qt::Vertical The interest rate gets calculated false when the payment is received when the payment is due Loan amount false true Enter the amount of the loan in this field. If you want to calculate this field out of the other parameters, please leave it empty. If the field is marked as required (colored background) you have informed KMyMoney about the fact that there were already some payments towards the loan. In this case, please enter the ending balance of your last statement. Interest rate false Please enter the interest rate (as a percentage) or leave the field empty to calculate it. Term false 999 Please enter the term of this loan or enter 0 to calculate it. The term is the time that is required to fully repay the loan. This time might be different from the time your loan contract is signed for. Payment (principal and interest) false Please enter the amount you pay for principal and interest or leave the field empty to calculate it. Balloon payment false Please enter the amount of a final amortization payment or leave the field empty to calculate it. 71 20 QSizePolicy::Expanding Qt::Horizontal Calculate Press this button to calculate/verify your loan details. Pressing this button calculates a possibly missing parameter for your loan or verifies that the values entered match. If something is not correct you will receive information about it. 20 16 QSizePolicy::Expanding Qt::Vertical 27 21 QSizePolicy::Expanding Qt::Horizontal 20 16 QSizePolicy::Expanding Qt::Vertical KComboBox QComboBox
kcombobox.h
QSpinBox QSpinBox
knuminput.h
KMyMoneyFrequencyCombo QWidget
kmymoneyfrequencycombo.h
1
diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kloandetailspage_p.h similarity index 62% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kloandetailspage_p.h index 473078b58..456030f70 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kloandetailspage_p.h @@ -1,49 +1,60 @@ /*************************************************************************** - userinfo.cpp + kloandetailspage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDLOANDETAILSPAGE_P_H +#define KNEWACCOUNTWIZARDLOANDETAILSPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_kloandetailspage.h" +#include "wizardpage_p.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); + class Wizard; + + class LoanDetailsPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(LoanDetailsPagePrivate) + + public: + LoanDetailsPagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KLoanDetailsPage) + { + } + + ~LoanDetailsPagePrivate() + { + delete ui; + } + + Ui::KLoanDetailsPage *ui; + bool m_needCalculate; + }; } -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/kloanpaymentpage.cpp b/kmymoney/wizards/newaccountwizard/kloanpaymentpage.cpp new file mode 100644 index 000000000..07d1da368 --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kloanpaymentpage.cpp @@ -0,0 +1,152 @@ +/*************************************************************************** + kloanpaymentpage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kloanpaymentpage.h" +#include "kloanpaymentpage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kloanpaymentpage.h" + +#include "kmymoneyedit.h" +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "kloandetailspage.h" +#include "kloandetailspage_p.h" +#include "kloanpaymentpage_p.h" +#include "kloanschedulepage.h" +#include "ksplittransactiondlg.h" +#include "mymoneyaccount.h" +#include "mymoneysecurity.h" +#include "mymoneysplit.h" +#include "mymoneytransaction.h" +#include "wizardpage.h" + +namespace NewAccountWizard +{ + LoanPaymentPage::LoanPaymentPage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new LoanPaymentPagePrivate(wizard), StepFees, this, wizard) + { + Q_D(LoanPaymentPage); + d->ui->setupUi(this); + d->phonyAccount = MyMoneyAccount(QLatin1String("Phony-ID"), MyMoneyAccount()); + + d->phonySplit.setAccountId(d->phonyAccount.id()); + d->phonySplit.setValue(MyMoneyMoney()); + d->phonySplit.setShares(MyMoneyMoney()); + + d->additionalFeesTransaction.addSplit(d->phonySplit); + + connect(d->ui->m_additionalFeesButton, &QAbstractButton::clicked, this, &LoanPaymentPage::slotAdditionalFees); + } + + LoanPaymentPage::~LoanPaymentPage() + { + } + + MyMoneyMoney LoanPaymentPage::basePayment() const + { + Q_D(const LoanPaymentPage); + return d->m_wizard->d_func()->m_loanDetailsPage->d_func()->ui->m_paymentAmount->value(); + } + + MyMoneyMoney LoanPaymentPage::additionalFees() const + { + Q_D(const LoanPaymentPage); + return d->additionalFees; + } + + void LoanPaymentPage::additionalFeesSplits(QList& list) + { + Q_D(LoanPaymentPage); + list.clear(); + + QList::ConstIterator it; + for (it = d->additionalFeesTransaction.splits().constBegin(); it != d->additionalFeesTransaction.splits().constEnd(); ++it) { + if ((*it).accountId() != d->phonyAccount.id()) { + list << (*it); + } + } + } + + void LoanPaymentPage::updateAmounts() + { + Q_D(LoanPaymentPage); + d->ui->m_additionalFees->setText(d->additionalFees.formatMoney(d->m_wizard->d_func()->currency().tradingSymbol(), d->m_wizard->d_func()->precision())); + d->ui->m_totalPayment->setText((basePayment() + d->additionalFees).formatMoney(d->m_wizard->d_func()->currency().tradingSymbol(), d->m_wizard->d_func()->precision())); + } + + void LoanPaymentPage::enterPage() + { + Q_D(LoanPaymentPage); + const MyMoneySecurity& currency = d->m_wizard->d_func()->currency(); + + d->ui->m_basePayment->setText(basePayment().formatMoney(currency.tradingSymbol(), d->m_wizard->d_func()->precision())); + d->phonyAccount.setCurrencyId(currency.id()); + d->additionalFeesTransaction.setCommodity(currency.id()); + + updateAmounts(); + } + + void LoanPaymentPage::slotAdditionalFees() + { + Q_D(LoanPaymentPage); + QMap priceInfo; + QPointer dlg = new KSplitTransactionDlg(d->additionalFeesTransaction, d->phonySplit, d->phonyAccount, false, !d->m_wizard->moneyBorrowed(), MyMoneyMoney(), priceInfo); + + // connect(dlg, SIGNAL(newCategory(MyMoneyAccount&)), this, SIGNAL(newCategory(MyMoneyAccount&))); + + if (dlg->exec() == QDialog::Accepted) { + d->additionalFeesTransaction = dlg->transaction(); + // sum up the additional fees + QList::ConstIterator it; + + d->additionalFees = MyMoneyMoney(); + for (it = d->additionalFeesTransaction.splits().constBegin(); it != d->additionalFeesTransaction.splits().constEnd(); ++it) { + if ((*it).accountId() != d->phonyAccount.id()) { + d->additionalFees += (*it).shares(); + } + } + updateAmounts(); + } + + delete dlg; + } + + KMyMoneyWizardPage* LoanPaymentPage::nextPage() const + { + Q_D(const LoanPaymentPage); + return d->m_wizard->d_func()->m_loanSchedulePage; + } + +} diff --git a/kmymoney/wizards/newaccountwizard/kloanpaymentpage.h b/kmymoney/wizards/newaccountwizard/kloanpaymentpage.h new file mode 100644 index 000000000..70463fd90 --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kloanpaymentpage.h @@ -0,0 +1,85 @@ +/*************************************************************************** + kloanpaymentpage.h + ------------------- + begin : Tue Sep 25 2007 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KNEWACCOUNTWIZARDLOANPAYMENTPAGE_H +#define KNEWACCOUNTWIZARDLOANPAYMENTPAGE_H + +// ---------------------------------------------------------------------------- +// QT Includes + +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "wizardpage.h" + +class MyMoneyMoney; +class MyMoneySplit; + +namespace NewAccountWizard +{ + class Wizard; + + class LoanPaymentPagePrivate; + class LoanPaymentPage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(LoanPaymentPage) + + public: + explicit LoanPaymentPage(Wizard* parent); + ~LoanPaymentPage() override; + + KMyMoneyWizardPage* nextPage() const; + + void enterPage(); + + /** + * This method returns the sum of the additional fees + */ + MyMoneyMoney additionalFees() const; + + /** + * This method returns the base payment, that's principal and interest + */ + MyMoneyMoney basePayment() const; + + /** + * This method returns the splits that make up the additional fees in @p list. + * @note The splits may contain assigned ids which the caller must remove before + * adding the splits to a MyMoneyTransaction object. + */ + void additionalFeesSplits(QList& list); + + protected slots: + void slotAdditionalFees(); + + protected: + void updateAmounts(); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, LoanPaymentPage) + friend class Wizard; + friend class AccountSummaryPage; + }; +} // namespace + +#endif diff --git a/kmymoney/wizards/newaccountwizard/kloanpaymentpagedecl.ui b/kmymoney/wizards/newaccountwizard/kloanpaymentpage.ui similarity index 98% rename from kmymoney/wizards/newaccountwizard/kloanpaymentpagedecl.ui rename to kmymoney/wizards/newaccountwizard/kloanpaymentpage.ui index 98a7c6f89..d9bfb4863 100644 --- a/kmymoney/wizards/newaccountwizard/kloanpaymentpagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/kloanpaymentpage.ui @@ -1,180 +1,180 @@ - KLoanPaymentPageDecl - + KLoanPaymentPage + 0 0 525 373 Qt::NoFocus Now enter the information required for the periodic loan payments. If your regular payments contains any additional fees, click on the <b>Additional fees</b> button to enter them. true 63 21 QSizePolicy::Expanding Qt::Horizontal Principal + Interest false true xxx Qt::AlignVCenter|Qt::AlignRight false + false Additional Fees true xxx Qt::AlignVCenter|Qt::AlignRight false = periodical payments false true xxx Qt::AlignVCenter|Qt::AlignRight false 62 21 QSizePolicy::Expanding Qt::Horizontal 20 20 QSizePolicy::Expanding Qt::Vertical diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kloanpaymentpage_p.h similarity index 55% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kloanpaymentpage_p.h index 473078b58..598f415a0 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kloanpaymentpage_p.h @@ -1,49 +1,67 @@ /*************************************************************************** - userinfo.cpp + kloanpaymentpage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDLOANPAYMENTPAGE_P_H +#define KNEWACCOUNTWIZARDLOANPAYMENTPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_kloanpaymentpage.h" +#include "wizardpage_p.h" +#include "mymoneyaccount.h" +#include "mymoneymoney.h" +#include "mymoneysplit.h" +#include "mymoneytransaction.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); -} + class Wizard; -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; + class LoanPaymentPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(LoanPaymentPagePrivate) + + public: + LoanPaymentPagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KLoanPaymentPage) + { + } + + ~LoanPaymentPagePrivate() + { + delete ui; + } + + Ui::KLoanPaymentPage *ui; + MyMoneyAccount phonyAccount; + MyMoneySplit phonySplit; + MyMoneyTransaction additionalFeesTransaction; + MyMoneyMoney additionalFees; + }; } + +#endif diff --git a/kmymoney/wizards/newaccountwizard/kloanpayoutpage.cpp b/kmymoney/wizards/newaccountwizard/kloanpayoutpage.cpp new file mode 100644 index 000000000..a0da720fa --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kloanpayoutpage.cpp @@ -0,0 +1,173 @@ +/*************************************************************************** + kloanpayoutpage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kloanpayoutpage.h" +#include "kloanpayoutpage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kaccounttypepage.h" +#include "ui_kloanpayoutpage.h" + +#include +#include "icons.h" +#include "kmymoneyaccountselector.h" +#include "kmymoneycategory.h" +#include "kmymoneydateinput.h" +#include "kmymoneywizardpage.h" +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "kaccountsummarypage.h" +#include "kaccounttypepage.h" +#include "kaccounttypepage_p.h" +#include "kloanpayoutpage_p.h" +#include "mymoneyaccount.h" +#include "mymoneyenums.h" +#include "mymoneyfile.h" +#include "wizardpage.h" + +using namespace NewAccountWizard; +using namespace Icons; +using namespace eMyMoney; + +namespace NewAccountWizard +{ + LoanPayoutPage::LoanPayoutPage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new LoanPayoutPagePrivate(wizard), StepPayout, this, wizard) + { + Q_D(LoanPayoutPage); + d->ui->setupUi(this); + d->m_mandatoryGroup->add(d->ui->m_assetAccount->lineEdit()); + d->m_mandatoryGroup->add(d->ui->m_loanAccount->lineEdit()); + + KGuiItem createAssetButtenItem(i18n("&Create..."), + QIcon::fromTheme(g_Icons[Icon::DocumentNew]), + i18n("Create a new asset account"), + i18n("If the asset account does not yet exist, press this button to create it.")); + KGuiItem::assign(d->ui->m_createAssetButton, createAssetButtenItem); + d->ui->m_createAssetButton->setToolTip(createAssetButtenItem.toolTip()); + d->ui->m_createAssetButton->setWhatsThis(createAssetButtenItem.whatsThis()); + connect(d->ui->m_createAssetButton, &QAbstractButton::clicked, this, &LoanPayoutPage::slotCreateAssetAccount); + + connect(d->ui->m_noPayoutTransaction, &QAbstractButton::toggled, this, &LoanPayoutPage::slotButtonsToggled); + connect(d->ui->m_refinanceLoan, &QAbstractButton::toggled, this, &LoanPayoutPage::slotButtonsToggled); + + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &LoanPayoutPage::slotLoadWidgets); + slotLoadWidgets(); + } + + LoanPayoutPage::~LoanPayoutPage() + { + } + + void LoanPayoutPage::slotButtonsToggled() + { + Q_D(LoanPayoutPage); + // we don't go directly, as the order of the emission of signals to slots is + // not defined. Using a single shot timer postpones the call of m_mandatoryGroup::changed() + // until the next round of the main loop so we can be sure to see all relevant changes + // that happened in the meantime (eg. widgets are enabled and disabled) + QTimer::singleShot(0, d->m_mandatoryGroup, SLOT(changed())); + } + + void LoanPayoutPage::slotCreateAssetAccount() + { + Q_D(LoanPayoutPage); + MyMoneyAccount acc; + acc.setAccountType(Account::Asset); + acc.setOpeningDate(d->m_wizard->d_func()->m_accountTypePage->d_func()->ui->m_openingDate->date()); + + emit d->m_wizard->createAccount(acc); + + if (!acc.id().isEmpty()) { + d->ui->m_assetAccount->setSelectedItem(acc.id()); + } + } + + void LoanPayoutPage::slotLoadWidgets() + { + Q_D(LoanPayoutPage); + AccountSet set; + set.addAccountGroup(Account::Asset); + set.load(d->ui->m_assetAccount->selector()); + + set.clear(); + set.addAccountType(Account::Loan); + set.load(d->ui->m_loanAccount->selector()); + } + + void LoanPayoutPage::enterPage() + { + Q_D(LoanPayoutPage); + // only allow to create new asset accounts for liability loans + d->ui->m_createAssetButton->setEnabled(d->m_wizard->moneyBorrowed()); + d->ui->m_refinanceLoan->setEnabled(d->m_wizard->moneyBorrowed()); + if (!d->m_wizard->moneyBorrowed()) { + d->ui->m_refinanceLoan->setChecked(false); + } + d->ui->m_payoutDetailFrame->setDisabled(d->ui->m_noPayoutTransaction->isChecked()); + } + + KMyMoneyWizardPage* LoanPayoutPage::nextPage() const + { + Q_D(const LoanPayoutPage); + return d->m_wizard->d_func()->m_accountSummaryPage; + } + + QWidget* LoanPayoutPage::initialFocusWidget() const + { + Q_D(const LoanPayoutPage); + return d->ui->m_noPayoutTransaction; + } + + bool LoanPayoutPage::isComplete() const + { + Q_D(const LoanPayoutPage); + return KMyMoneyWizardPage::isComplete() | d->ui->m_noPayoutTransaction->isChecked(); + } + + QString LoanPayoutPage::payoutAccountId() const + { + Q_D(const LoanPayoutPage); + if (d->ui->m_refinanceLoan->isChecked()) { + return d->ui->m_loanAccount->selectedItem(); + } else { + return d->ui->m_assetAccount->selectedItem(); + } + } + +} diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kloanpayoutpage.h similarity index 56% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kloanpayoutpage.h index 473078b58..c4c7c2ddd 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kloanpayoutpage.h @@ -1,49 +1,69 @@ /*************************************************************************** - userinfo.cpp + kloanpayoutpage.h ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDPAYOUT_H +#define KNEWACCOUNTWIZARDPAYOUT_H // ---------------------------------------------------------------------------- // QT Includes +#include + // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" - +#include "wizardpage.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); -} + class Wizard; -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} + class LoanPayoutPagePrivate; + class LoanPayoutPage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(LoanPayoutPage) + + public: + explicit LoanPayoutPage(Wizard* parent); + ~LoanPayoutPage() override; + + void enterPage(); + virtual bool isComplete() const; + + KMyMoneyWizardPage* nextPage() const; + + QWidget* initialFocusWidget() const override; + + QString payoutAccountId() const; + + private slots: + void slotLoadWidgets(); + void slotCreateAssetAccount(); + void slotButtonsToggled(); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, LoanPayoutPage) + friend class Wizard; + friend class AccountSummaryPage; + }; +} // namespace + +#endif diff --git a/kmymoney/wizards/newaccountwizard/kloanpayoutpagedecl.ui b/kmymoney/wizards/newaccountwizard/kloanpayoutpage.ui similarity index 98% rename from kmymoney/wizards/newaccountwizard/kloanpayoutpagedecl.ui rename to kmymoney/wizards/newaccountwizard/kloanpayoutpage.ui index 989212b91..2f27822e6 100644 --- a/kmymoney/wizards/newaccountwizard/kloanpayoutpagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/kloanpayoutpage.ui @@ -1,191 +1,191 @@ - KLoanPayoutPageDecl - + KLoanPayoutPage + 0 0 600 384 Qt::NoFocus If this loan is for an asset, such as a car or a house, you can create the asset account now. An asset account represents the total value of an asset. The money from this loan will be transferred into the asset account you create or select. If this loan is a 'consumer loan' (money to use however you want), you can use a checking account instead. true Do not create payout transaction QFrame::NoFrame QFrame::Raised 0 Refinance existing loan Check this if you are refinancing a loan that already exists in KMyMoney Asset Account false 1 0 1 0 Create Loan account false false 1 0 1 0 Date of payment false 40 20 QSizePolicy::Expanding Qt::Horizontal 20 20 QSizePolicy::Expanding Qt::Vertical m_noPayoutTransaction toggled(bool) m_payoutDetailFrame setDisabled(bool) m_refinanceLoan toggled(bool) m_assetAccount setDisabled(bool) m_refinanceLoan toggled(bool) m_loanAccount setEnabled(bool) m_refinanceLoan toggled(bool) m_createAssetButton setDisabled(bool) diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kloanpayoutpage_p.h similarity index 63% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kloanpayoutpage_p.h index 473078b58..458fbbf0c 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kloanpayoutpage_p.h @@ -1,49 +1,59 @@ /*************************************************************************** - userinfo.cpp + kloanpayoutpage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDPAYOUT_P_H +#define KNEWACCOUNTWIZARDPAYOUT_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_kloanpayoutpage.h" +#include "wizardpage_p.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); + class Wizard; + + class LoanPayoutPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(LoanPayoutPagePrivate) + + public: + LoanPayoutPagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KLoanPayoutPage) + { + } + + ~LoanPayoutPagePrivate() + { + delete ui; + } + + Ui::KLoanPayoutPage *ui; + }; } -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/kloanschedulepage.cpp b/kmymoney/wizards/newaccountwizard/kloanschedulepage.cpp new file mode 100644 index 000000000..8fbe54899 --- /dev/null +++ b/kmymoney/wizards/newaccountwizard/kloanschedulepage.cpp @@ -0,0 +1,138 @@ +/*************************************************************************** + kloanschedulepage.cpp + ------------------- + begin : Tue Sep 25 2006 + copyright : (C) 2007 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kloanschedulepage.h" +#include "kloanschedulepage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kgeneralloaninfopage.h" +#include "ui_kloanschedulepage.h" + +#include +#include "kmymoneyaccountselector.h" +#include "kmymoneycategory.h" +#include "kmymoneydateinput.h" +#include "knewaccountwizard.h" +#include "knewaccountwizard_p.h" +#include "kaccountsummarypage.h" +#include "kgeneralloaninfopage.h" +#include "kgeneralloaninfopage_p.h" +#include "kloanpayoutpage.h" +#include "mymoneyaccount.h" +#include "mymoneyfile.h" +#include "mymoneymoney.h" +#include "wizardpage.h" +#include "mymoneyenums.h" + +using namespace NewAccountWizard; +using namespace Icons; +using namespace eMyMoney; + +namespace NewAccountWizard +{ + LoanSchedulePage::LoanSchedulePage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new LoanSchedulePagePrivate(wizard), StepSchedule, this, wizard) + { + Q_D(const LoanSchedulePage); + d->ui->setupUi(this); + d->m_mandatoryGroup->add(d->ui->m_interestCategory->lineEdit()); + d->m_mandatoryGroup->add(d->ui->m_paymentAccount->lineEdit()); + connect(d->ui->m_interestCategory, &KMyMoneyCombo::createItem, this, &LoanSchedulePage::slotCreateCategory); + connect(MyMoneyFile::instance(), &MyMoneyFile::dataChanged, this, &LoanSchedulePage::slotLoadWidgets); + } + + LoanSchedulePage::~LoanSchedulePage() + { + } + + void LoanSchedulePage::slotCreateCategory(const QString& name, QString& id) + { + Q_D(LoanSchedulePage); + MyMoneyAccount acc, parent; + acc.setName(name); + + if (d->m_wizard->moneyBorrowed()) + parent = MyMoneyFile::instance()->expense(); + else + parent = MyMoneyFile::instance()->income(); + + emit d->m_wizard->createCategory(acc, parent); + + // return id + id = acc.id(); + } + + QDate LoanSchedulePage::firstPaymentDueDate() const + { + Q_D(const LoanSchedulePage); + if (d->ui->m_firstPaymentDueDate->isEnabled()) + return d->ui->m_firstPaymentDueDate->date(); + return d->m_wizard->d_func()->m_generalLoanInfoPage->d_func()->ui->m_firstPaymentDate->date(); + } + + QWidget* LoanSchedulePage::initialFocusWidget() const + { + Q_D(const LoanSchedulePage); + return d->ui->m_interestCategory; + } + + void LoanSchedulePage::enterPage() + { + Q_D(LoanSchedulePage); + d->ui->m_interestCategory->setFocus(); + d->ui->m_firstPaymentDueDate->setDisabled(d->m_wizard->d_func()->m_generalLoanInfoPage->recordAllPayments()); + slotLoadWidgets(); + } + + void LoanSchedulePage::slotLoadWidgets() + { + Q_D(LoanSchedulePage); + AccountSet set; + if (d->m_wizard->moneyBorrowed()) + set.addAccountGroup(Account::Expense); + else + set.addAccountGroup(Account::Income); + set.load(d->ui->m_interestCategory->selector()); + + set.clear(); + set.addAccountGroup(Account::Asset); + set.load(d->ui->m_paymentAccount->selector()); + } + + KMyMoneyWizardPage* LoanSchedulePage::nextPage() const + { + Q_D(const LoanSchedulePage); + // if the balance widget of the general loan info page is enabled and + // the value is not zero, then the payout already happened and we don't + // aks for it. + if (d->m_wizard->openingBalance().isZero()) + return d->m_wizard->d_func()->m_loanPayoutPage; + return d->m_wizard->d_func()->m_accountSummaryPage; + } +} diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kloanschedulepage.h similarity index 54% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kloanschedulepage.h index 473078b58..560ecd4eb 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kloanschedulepage.h @@ -1,49 +1,72 @@ /*************************************************************************** - userinfo.cpp + kloanschedulepage.h ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDLOANSCHEDULEPAGE_H +#define KNEWACCOUNTWIZARDLOANSCHEDULEPAGE_H // ---------------------------------------------------------------------------- // QT Includes +#include + // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "wizardpage.h" +class QDate; -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); -} + class Wizard; -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} + class LoanSchedulePagePrivate; + class LoanSchedulePage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(LoanSchedulePage) + + public: + explicit LoanSchedulePage(Wizard* parent); + ~LoanSchedulePage() override; + + void enterPage(); + + KMyMoneyWizardPage* nextPage() const; + + /** + * This method returns the due date of the first payment to be recorded. + */ + QDate firstPaymentDueDate() const; + + QWidget* initialFocusWidget() const override; + + private slots: + void slotLoadWidgets(); + void slotCreateCategory(const QString& name, QString& id); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, LoanSchedulePage) + friend class Wizard; + friend class AccountSummaryPage; + }; +} // namespace + +#endif diff --git a/kmymoney/wizards/newaccountwizard/kloanschedulepagedecl.ui b/kmymoney/wizards/newaccountwizard/kloanschedulepage.ui similarity index 98% rename from kmymoney/wizards/newaccountwizard/kloanschedulepagedecl.ui rename to kmymoney/wizards/newaccountwizard/kloanschedulepage.ui index e1907d35d..c613fe8d1 100644 --- a/kmymoney/wizards/newaccountwizard/kloanschedulepagedecl.ui +++ b/kmymoney/wizards/newaccountwizard/kloanschedulepage.ui @@ -1,141 +1,141 @@ - KLoanSchedulePageDecl - + KLoanSchedulePage + 0 0 545 370 Qt::NoFocus KMyMoney creates a schedule for this payment and reminds you whenever a payment must be made. Please select the account to/from which payments will be made and the category the interest will be assigned to.<p> If you selected to record all payments this date has already been supplied. If you selected to record only this years payments, then the <b>First payment due date</b> is the date of the first payment made in this year. true Interest category false The category the interest part of the payment will be assigned to. If you borrow money you usually have to pay interest, so this should be an expense category. If you lend the money, you receive the interest. In this case, select an income category here. Payment account false Select the account from which you make your periodical payments or where you receive regular payments in case you lend the money. In most cases, this is a checking account. First payment due on false 61 20 QSizePolicy::Expanding Qt::Horizontal 41 20 QSizePolicy::Preferred Qt::Horizontal 20 21 QSizePolicy::Expanding Qt::Vertical diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/newaccountwizard/kloanschedulepage_p.h similarity index 62% copy from kmymoney/wizards/wizardpages/userinfo.cpp copy to kmymoney/wizards/newaccountwizard/kloanschedulepage_p.h index 473078b58..28986b774 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/newaccountwizard/kloanschedulepage_p.h @@ -1,49 +1,59 @@ /*************************************************************************** - userinfo.cpp + kloanschedulepage.cpp ------------------- - begin : Fri Jun 1 2007 + begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#include "userinfo.h" +#ifndef KNEWACCOUNTWIZARDLOANSCHEDULEPAGE_P_H +#define KNEWACCOUNTWIZARDLOANSCHEDULEPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "mymoneypayee.h" +#include "ui_kloanschedulepage.h" +#include "wizardpage_p.h" -UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) +namespace NewAccountWizard { - m_userNameEdit->setFocus(); + class Wizard; + + class LoanSchedulePagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(LoanSchedulePagePrivate) + + public: + LoanSchedulePagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KLoanSchedulePage) + { + } + + ~LoanSchedulePagePrivate() + { + delete ui; + } + + Ui::KLoanSchedulePage *ui; + }; } -MyMoneyPayee UserInfo::user() const -{ - MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); - return user; -} +#endif diff --git a/kmymoney/wizards/newaccountwizard/knewaccountwizard.cpp b/kmymoney/wizards/newaccountwizard/knewaccountwizard.cpp index 5a22b5c2a..407dfdf44 100644 --- a/kmymoney/wizards/newaccountwizard/knewaccountwizard.cpp +++ b/kmymoney/wizards/newaccountwizard/knewaccountwizard.cpp @@ -1,1675 +1,378 @@ /*************************************************************************** knewaccountwizard.cpp ------------------- begin : Tue Sep 25 2006 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "knewaccountwizard.h" #include "knewaccountwizard_p.h" // ---------------------------------------------------------------------------- // QT Includes #include -#include #include -#include -#include -#include // ---------------------------------------------------------------------------- // KDE Includes #include #include -#include // ---------------------------------------------------------------------------- // Project Includes +#include "kaccountsummarypage.h" +#include "kaccounttypepage.h" +#include "kbrokeragepage.h" +#include "kcreditcardschedulepage.h" +#include "kgeneralloaninfopage.h" +#include "khierarchypage.h" +#include "kinstitutionpage.h" +#include "kloandetailspage.h" +#include "kloanpaymentpage.h" +#include "kloanpayoutpage.h" +#include "kloanschedulepage.h" + +#include "kaccounttypepage_p.h" +#include "kbrokeragepage_p.h" +#include "kcreditcardschedulepage_p.h" +#include "kgeneralloaninfopage_p.h" +#include "kinstitutionpage_p.h" +#include "kloandetailspage_p.h" +#include "kloanpayoutpage_p.h" +#include "kloanschedulepage_p.h" + #include "kmymoneycurrencyselector.h" -#include "kmymoneyaccountselector.h" -#include "mymoneyfinancialcalculator.h" #include "kcurrencycalculator.h" -#include "kmymoneyglobalsettings.h" -#include -#include "mymoneyutils.h" -#include "ksplittransactiondlg.h" -#include "kequitypriceupdatedlg.h" -#include "accountsmodel.h" -#include "accountsproxymodel.h" -#include "models.h" -#include "modelenums.h" -#include "icons.h" #include "mymoneyfile.h" #include "mymoneyinstitution.h" #include "mymoneyaccountloan.h" -#include "mymoneypayee.h" #include "mymoneyprice.h" #include "mymoneysplit.h" #include "mymoneytransaction.h" using namespace NewAccountWizard; using namespace Icons; using namespace eMyMoney; namespace NewAccountWizard { -enum steps { - StepInstitution = 1, - StepAccount, - StepBroker, - StepDetails, - StepPayments, - StepFees, - StepSchedule, - StepPayout, - StepParentAccount, - StepFinish -}; - -Wizard::Wizard(QWidget *parent, bool modal, Qt::WindowFlags flags) - : KMyMoneyWizard(parent, modal, flags) -{ - setTitle(i18n("KMyMoney New Account Setup")); - addStep(i18n("Institution")); - addStep(i18n("Account")); - addStep(i18n("Broker")); - addStep(i18n("Details")); - addStep(i18n("Payments")); - addStep(i18n("Fees")); - addStep(i18n("Schedule")); - addStep(i18n("Payout")); - addStep(i18n("Parent Account")); - addStep(i18nc("Finish the wizard", "Finish")); - setStepHidden(StepBroker); - setStepHidden(StepSchedule); - setStepHidden(StepPayout); - setStepHidden(StepDetails); - setStepHidden(StepPayments); - setStepHidden(StepFees); - - m_institutionPage = new InstitutionPage(this); - m_accountTypePage = new AccountTypePage(this); - // Investment Pages - m_brokeragepage = new BrokeragePage(this); - // Credit Card Pages - m_schedulePage = new CreditCardSchedulePage(this); - // Loan Pages - m_generalLoanInfoPage = new GeneralLoanInfoPage(this); - m_loanDetailsPage = new LoanDetailsPage(this); - m_loanPaymentPage = new LoanPaymentPage(this); - m_loanSchedulePage = new LoanSchedulePage(this); - m_loanPayoutPage = new LoanPayoutPage(this); - // Not a loan page - m_hierarchyPage = new HierarchyPage(this); - // Finish - m_accountSummaryPage = new AccountSummaryPage(this); - - setFirstPage(m_institutionPage); -} - -void Wizard::setAccount(const MyMoneyAccount& acc) -{ - m_account = acc; - m_accountTypePage->setAccount(m_account); - - if (!acc.institutionId().isEmpty()) { - m_institutionPage->selectExistingInstitution(acc.institutionId()); - } -} - -const MyMoneySecurity& Wizard::currency() const -{ - return m_accountTypePage->currency(); -} - -MyMoneyMoney Wizard::interestRate() const -{ - return m_loanDetailsPage->m_interestRate->value() / MyMoneyMoney(100, 1); -} - -int Wizard::precision() const -{ - return MyMoneyMoney::denomToPrec(currency().smallestAccountFraction()); -} - -const MyMoneyAccount& Wizard::account() -{ - m_account = MyMoneyAccountLoan(); - m_account.setName(m_accountTypePage->m_accountName->text()); - m_account.setOpeningDate(m_accountTypePage->m_openingDate->date()); - m_account.setAccountType(m_accountTypePage->accountType()); - m_account.setInstitutionId(m_institutionPage->institution().id()); - m_account.setNumber(m_institutionPage->m_accountNumber->text()); - m_account.setValue("iban", m_institutionPage->m_iban->text()); - if (m_accountTypePage->m_preferredAccount->isChecked()) - m_account.setValue("PreferredAccount", "Yes"); - else - m_account.deletePair("PreferredAccount"); - - m_account.setCurrencyId(currency().id()); - if (m_account.isLoan()) { - // in case we lend the money we adjust the account type - if (!moneyBorrowed()) - m_account.setAccountType(Account::AssetLoan); - m_account.setLoanAmount(m_loanDetailsPage->m_loanAmount->value()); - m_account.setInterestRate(m_loanSchedulePage->firstPaymentDueDate(), m_loanDetailsPage->m_interestRate->value()); - m_account.setInterestCalculation(m_loanDetailsPage->m_paymentDue->currentIndex() == 0 ? MyMoneyAccountLoan::paymentReceived : MyMoneyAccountLoan::paymentDue); - m_account.setFixedInterestRate(m_generalLoanInfoPage->m_interestType->currentIndex() == 0); - m_account.setFinalPayment(m_loanDetailsPage->m_balloonAmount->value()); - m_account.setTerm(m_loanDetailsPage->term()); - m_account.setPeriodicPayment(m_loanDetailsPage->m_paymentAmount->value()); - m_account.setPayee(m_generalLoanInfoPage->m_payee->selectedItem()); - m_account.setInterestCompounding((int)m_generalLoanInfoPage->m_compoundFrequency->currentItem()); - - if (!m_account.fixedInterestRate()) { - m_account.setNextInterestChange(m_generalLoanInfoPage->m_interestChangeDateEdit->date()); - m_account.setInterestChangeFrequency(m_generalLoanInfoPage->m_interestFrequencyAmountEdit->value(), m_generalLoanInfoPage->m_interestFrequencyUnitEdit->currentIndex()); + Wizard::Wizard(QWidget *parent, bool modal, Qt::WindowFlags flags) + : KMyMoneyWizard(*new WizardPrivate(this), parent, modal, flags) + { + Q_D(Wizard); + setTitle(i18n("KMyMoney New Account Setup")); + addStep(i18n("Institution")); + addStep(i18n("Account")); + addStep(i18n("Broker")); + addStep(i18n("Details")); + addStep(i18n("Payments")); + addStep(i18n("Fees")); + addStep(i18n("Schedule")); + addStep(i18n("Payout")); + addStep(i18n("Parent Account")); + addStep(i18nc("Finish the wizard", "Finish")); + d->setStepHidden(StepBroker); + d->setStepHidden(StepSchedule); + d->setStepHidden(StepPayout); + d->setStepHidden(StepDetails); + d->setStepHidden(StepPayments); + d->setStepHidden(StepFees); + + d->m_institutionPage = new InstitutionPage(this); + d->m_accountTypePage = new AccountTypePage(this); + // Investment Pages + d->m_brokeragepage = new BrokeragePage(this); + // Credit Card Pages + d->m_schedulePage = new CreditCardSchedulePage(this); + // Loan Pages + d->m_generalLoanInfoPage = new GeneralLoanInfoPage(this); + d->m_loanDetailsPage = new LoanDetailsPage(this); + d->m_loanPaymentPage = new LoanPaymentPage(this); + d->m_loanSchedulePage = new LoanSchedulePage(this); + d->m_loanPayoutPage = new LoanPayoutPage(this); + // Not a loan page + d->m_hierarchyPage = new HierarchyPage(this); + // Finish + d->m_accountSummaryPage = new AccountSummaryPage(this); + + d->setFirstPage(d->m_institutionPage); + } + + Wizard::~Wizard() + { + } + + void Wizard::setAccount(const MyMoneyAccount& acc) + { + Q_D(Wizard); + d->m_account = acc; + d->m_accountTypePage->setAccount(d->m_account); + + if (!acc.institutionId().isEmpty()) { + d->m_institutionPage->selectExistingInstitution(acc.institutionId()); } } - return m_account; -} - -MyMoneyTransaction Wizard::payoutTransaction() -{ - MyMoneyTransaction t; - if (m_account.isLoan() // we're creating a loan - && openingBalance().isZero() // and don't have an opening balance - && !m_loanPayoutPage->m_noPayoutTransaction->isChecked()) { // and the user wants to have a payout transaction - t.setPostDate(m_loanPayoutPage->m_payoutDate->date()); - t.setCommodity(m_account.currencyId()); - MyMoneySplit s; - s.setAccountId(m_account.id()); - s.setShares(m_loanDetailsPage->m_loanAmount->value()); - if (moneyBorrowed()) - s.setShares(-s.shares()); - s.setValue(s.shares()); - t.addSplit(s); - - s.clearId(); - s.setValue(-s.value()); - s.setAccountId(m_loanPayoutPage->payoutAccountId()); - MyMoneyMoney shares; - KCurrencyCalculator::setupSplitPrice(shares, t, s, QMap(), this); - s.setShares(shares); - t.addSplit(s); - } - return t; -} - -const MyMoneyAccount& Wizard::parentAccount() -{ - return m_accountTypePage->allowsParentAccount() - ? m_hierarchyPage->parentAccount() - : (m_accountTypePage->accountType() == Account::Loan - ? m_generalLoanInfoPage->parentAccount() - : m_accountTypePage->parentAccount()); -} - -MyMoneyAccount Wizard::brokerageAccount() const -{ - MyMoneyAccount account; - if (m_account.accountType() == Account::Investment - && m_brokeragepage->m_createBrokerageButton->isChecked()) { - account.setName(m_account.brokerageName()); - account.setAccountType(Account::Checkings); - account.setInstitutionId(m_account.institutionId()); - account.setOpeningDate(m_account.openingDate()); - account.setCurrencyId(m_brokeragepage->m_brokerageCurrency->security().id()); - if (m_brokeragepage->m_accountNumber->isEnabled() && !m_brokeragepage->m_accountNumber->text().isEmpty()) - account.setNumber(m_brokeragepage->m_accountNumber->text()); - if (m_brokeragepage->m_iban->isEnabled() && !m_brokeragepage->m_iban->text().isEmpty()) - account.setValue("iban", m_brokeragepage->m_iban->text()); - } - return account; -} - -const MyMoneySchedule& Wizard::schedule() -{ - m_schedule = MyMoneySchedule(); - if (!m_account.id().isEmpty()) { - if (m_schedulePage->m_reminderCheckBox->isChecked() && (m_account.accountType() == Account::CreditCard)) { - m_schedule.setName(m_schedulePage->m_name->text()); - m_schedule.setType(Schedule::Type::Transfer); - m_schedule.setPaymentType(static_cast(m_schedulePage->m_method->currentItem())); - m_schedule.setFixed(false); - m_schedule.setOccurrencePeriod(Schedule::Occurrence::Monthly); - m_schedule.setOccurrenceMultiplier(1); - MyMoneyTransaction t; + MyMoneyMoney Wizard::interestRate() const + { + Q_D(const Wizard); + return d->m_loanDetailsPage->d_func()->ui->m_interestRate->value() / MyMoneyMoney(100, 1); + } + + + + const MyMoneyAccount& Wizard::account() + { + Q_D(Wizard); + d->m_account = MyMoneyAccountLoan(); + d->m_account.setName(d->m_accountTypePage->d_func()->ui->m_accountName->text()); + d->m_account.setOpeningDate(d->m_accountTypePage->d_func()->ui->m_openingDate->date()); + d->m_account.setAccountType(d->m_accountTypePage->accountType()); + d->m_account.setInstitutionId(d->m_institutionPage->institution().id()); + d->m_account.setNumber(d->m_institutionPage->d_func()->ui->m_accountNumber->text()); + d->m_account.setValue("iban", d->m_institutionPage->d_func()->ui->m_iban->text()); + if (d->m_accountTypePage->d_func()->ui->m_preferredAccount->isChecked()) + d->m_account.setValue("PreferredAccount", "Yes"); + else + d->m_account.deletePair("PreferredAccount"); + + d->m_account.setCurrencyId(d->currency().id()); + if (d->m_account.isLoan()) { + // in case we lend the money we adjust the account type + if (!moneyBorrowed()) + d->m_account.setAccountType(Account::AssetLoan); + d->m_account.setLoanAmount(d->m_loanDetailsPage->d_func()->ui->m_loanAmount->value()); + d->m_account.setInterestRate(d->m_loanSchedulePage->firstPaymentDueDate(), d->m_loanDetailsPage->d_func()->ui->m_interestRate->value()); + d->m_account.setInterestCalculation(d->m_loanDetailsPage->d_func()->ui->m_paymentDue->currentIndex() == 0 ? MyMoneyAccountLoan::paymentReceived : MyMoneyAccountLoan::paymentDue); + d->m_account.setFixedInterestRate(d->m_generalLoanInfoPage->d_func()->ui->m_interestType->currentIndex() == 0); + d->m_account.setFinalPayment(d->m_loanDetailsPage->d_func()->ui->m_balloonAmount->value()); + d->m_account.setTerm(d->m_loanDetailsPage->term()); + d->m_account.setPeriodicPayment(d->m_loanDetailsPage->d_func()->ui->m_paymentAmount->value()); + d->m_account.setPayee(d->m_generalLoanInfoPage->d_func()->ui->m_payee->selectedItem()); + d->m_account.setInterestCompounding((int)d->m_generalLoanInfoPage->d_func()->ui->m_compoundFrequency->currentItem()); + + if (!d->m_account.fixedInterestRate()) { + d->m_account.setNextInterestChange(d->m_generalLoanInfoPage->d_func()->ui->m_interestChangeDateEdit->date()); + d->m_account.setInterestChangeFrequency(d->m_generalLoanInfoPage->d_func()->ui->m_interestFrequencyAmountEdit->value(), d->m_generalLoanInfoPage->d_func()->ui->m_interestFrequencyUnitEdit->currentIndex()); + } + } + return d->m_account; + } + + MyMoneyTransaction Wizard::payoutTransaction() + { + Q_D(Wizard); + MyMoneyTransaction t; + if (d->m_account.isLoan() // we're creating a loan + && openingBalance().isZero() // and don't have an opening balance + && !d->m_loanPayoutPage->d_func()->ui->m_noPayoutTransaction->isChecked()) { // and the user wants to have a payout transaction + t.setPostDate(d->m_loanPayoutPage->d_func()->ui->m_payoutDate->date()); + t.setCommodity(d->m_account.currencyId()); MyMoneySplit s; - s.setPayeeId(m_schedulePage->m_payee->selectedItem()); - s.setAccountId(m_schedulePage->m_paymentAccount->selectedItem()); - s.setMemo(i18n("Credit card payment")); - s.setShares(-m_schedulePage->m_amount->value()); + s.setAccountId(d->m_account.id()); + s.setShares(d->m_loanDetailsPage->d_func()->ui->m_loanAmount->value()); + if (moneyBorrowed()) + s.setShares(-s.shares()); s.setValue(s.shares()); t.addSplit(s); s.clearId(); - s.setAccountId(m_account.id()); - s.setShares(m_schedulePage->m_amount->value()); - s.setValue(s.shares()); + s.setValue(-s.value()); + s.setAccountId(d->m_loanPayoutPage->payoutAccountId()); + MyMoneyMoney shares; + KCurrencyCalculator::setupSplitPrice(shares, t, s, QMap(), this); + s.setShares(shares); t.addSplit(s); + } + return t; + } + + const MyMoneyAccount& Wizard::parentAccount() + { + Q_D(Wizard); + return d->m_accountTypePage->allowsParentAccount() + ? d->m_hierarchyPage->parentAccount() + : (d->m_accountTypePage->accountType() == Account::Loan + ? d->m_generalLoanInfoPage->parentAccount() + : d->m_accountTypePage->parentAccount()); + } + + MyMoneyAccount Wizard::brokerageAccount() const + { + Q_D(const Wizard); + MyMoneyAccount account; + if (d->m_account.accountType() == Account::Investment + && d->m_brokeragepage->d_func()->ui->m_createBrokerageButton->isChecked()) { + account.setName(d->m_account.brokerageName()); + account.setAccountType(Account::Checkings); + account.setInstitutionId(d->m_account.institutionId()); + account.setOpeningDate(d->m_account.openingDate()); + account.setCurrencyId(d->m_brokeragepage->d_func()->ui->m_brokerageCurrency->security().id()); + if (d->m_brokeragepage->d_func()->ui->m_accountNumber->isEnabled() && !d->m_brokeragepage->d_func()->ui->m_accountNumber->text().isEmpty()) + account.setNumber(d->m_brokeragepage->d_func()->ui->m_accountNumber->text()); + if (d->m_brokeragepage->d_func()->ui->m_iban->isEnabled() && !d->m_brokeragepage->d_func()->ui->m_iban->text().isEmpty()) + account.setValue("iban", d->m_brokeragepage->d_func()->ui->m_iban->text()); + } + return account; + } + + const MyMoneySchedule& Wizard::schedule() + { + Q_D(Wizard); + d->m_schedule = MyMoneySchedule(); + + if (!d->m_account.id().isEmpty()) { + if (d->m_schedulePage->d_func()->ui->m_reminderCheckBox->isChecked() && (d->m_account.accountType() == Account::CreditCard)) { + d->m_schedule.setName(d->m_schedulePage->d_func()->ui->m_name->text()); + d->m_schedule.setType(Schedule::Type::Transfer); + d->m_schedule.setPaymentType(static_cast(d->m_schedulePage->d_func()->ui->m_method->currentItem())); + d->m_schedule.setFixed(false); + d->m_schedule.setOccurrencePeriod(Schedule::Occurrence::Monthly); + d->m_schedule.setOccurrenceMultiplier(1); + MyMoneyTransaction t; + MyMoneySplit s; + s.setPayeeId(d->m_schedulePage->d_func()->ui->m_payee->selectedItem()); + s.setAccountId(d->m_schedulePage->d_func()->ui->m_paymentAccount->selectedItem()); + s.setMemo(i18n("Credit card payment")); + s.setShares(-d->m_schedulePage->d_func()->ui->m_amount->value()); + s.setValue(s.shares()); + t.addSplit(s); - // setup the next due date - t.setPostDate(m_schedulePage->m_date->date()); - m_schedule.setTransaction(t); - - } else if (m_account.isLoan()) { - m_schedule.setName(i18n("Loan payment for %1", m_accountTypePage->m_accountName->text())); - m_schedule.setType(Schedule::Type::LoanPayment); - if (moneyBorrowed()) - m_schedule.setPaymentType(Schedule::PaymentType::DirectDebit); - else - m_schedule.setPaymentType(Schedule::PaymentType::DirectDeposit); - - m_schedule.setFixed(true); - m_schedule.setOccurrence(m_generalLoanInfoPage->m_paymentFrequency->currentItem()); + s.clearId(); + s.setAccountId(d->m_account.id()); + s.setShares(d->m_schedulePage->d_func()->ui->m_amount->value()); + s.setValue(s.shares()); + t.addSplit(s); - MyMoneyTransaction t; - t.setCommodity(m_account.currencyId()); - MyMoneySplit s; - // payment split - s.setPayeeId(m_generalLoanInfoPage->m_payee->selectedItem()); - s.setAccountId(m_loanSchedulePage->m_paymentAccount->selectedItem()); - s.setMemo(i18n("Loan payment")); - s.setValue(m_loanPaymentPage->basePayment() + m_loanPaymentPage->additionalFees()); - if (moneyBorrowed()) { - s.setValue(-s.value()); - } - s.setShares(s.value()); - if (m_account.id() != QLatin1String("Phony-ID")) { - // if the real account is already set perform the currency conversion if it's necessary - MyMoneyMoney paymentShares; - KCurrencyCalculator::setupSplitPrice(paymentShares, t, s, QMap(), this); - s.setShares(paymentShares); - } - t.addSplit(s); + // setup the next due date + t.setPostDate(d->m_schedulePage->d_func()->ui->m_date->date()); + d->m_schedule.setTransaction(t); - // principal split - s.clearId(); - s.setAccountId(m_account.id()); - s.setShares(MyMoneyMoney::autoCalc); - s.setValue(MyMoneyMoney::autoCalc); - s.setMemo(i18n("Amortization")); - s.setAction(MyMoneySplit::ActionAmortization); - t.addSplit(s); + } else if (d->m_account.isLoan()) { + d->m_schedule.setName(i18n("Loan payment for %1", d->m_accountTypePage->d_func()->ui->m_accountName->text())); + d->m_schedule.setType(Schedule::Type::LoanPayment); + if (moneyBorrowed()) + d->m_schedule.setPaymentType(Schedule::PaymentType::DirectDebit); + else + d->m_schedule.setPaymentType(Schedule::PaymentType::DirectDeposit); + + d->m_schedule.setFixed(true); + d->m_schedule.setOccurrence(d->m_generalLoanInfoPage->d_func()->ui->m_paymentFrequency->currentItem()); + + MyMoneyTransaction t; + t.setCommodity(d->m_account.currencyId()); + MyMoneySplit s; + // payment split + s.setPayeeId(d->m_generalLoanInfoPage->d_func()->ui->m_payee->selectedItem()); + s.setAccountId(d->m_loanSchedulePage->d_func()->ui->m_paymentAccount->selectedItem()); + s.setMemo(i18n("Loan payment")); + s.setValue(d->m_loanPaymentPage->basePayment() + d->m_loanPaymentPage->additionalFees()); + if (moneyBorrowed()) { + s.setValue(-s.value()); + } + s.setShares(s.value()); + if (d->m_account.id() != QLatin1String("Phony-ID")) { + // if the real account is already set perform the currency conversion if it's necessary + MyMoneyMoney paymentShares; + KCurrencyCalculator::setupSplitPrice(paymentShares, t, s, QMap(), this); + s.setShares(paymentShares); + } + t.addSplit(s); - // interest split - //only add if interest is above zero - if (!m_loanDetailsPage->m_interestRate->value().isZero()) { + // principal split s.clearId(); - s.setAccountId(m_loanSchedulePage->m_interestCategory->selectedItem()); + s.setAccountId(d->m_account.id()); s.setShares(MyMoneyMoney::autoCalc); s.setValue(MyMoneyMoney::autoCalc); - s.setMemo(i18n("Interest")); - s.setAction(MyMoneySplit::ActionInterest); + s.setMemo(i18n("Amortization")); + s.setAction(MyMoneySplit::ActionAmortization); t.addSplit(s); - } - // additional fee splits - QList additionalSplits; - m_loanPaymentPage->additionalFeesSplits(additionalSplits); - QList::const_iterator it; - MyMoneyMoney factor(moneyBorrowed() ? 1 : -1, 1); + // interest split + //only add if interest is above zero + if (!d->m_loanDetailsPage->d_func()->ui->m_interestRate->value().isZero()) { + s.clearId(); + s.setAccountId(d->m_loanSchedulePage->d_func()->ui->m_interestCategory->selectedItem()); + s.setShares(MyMoneyMoney::autoCalc); + s.setValue(MyMoneyMoney::autoCalc); + s.setMemo(i18n("Interest")); + s.setAction(MyMoneySplit::ActionInterest); + t.addSplit(s); + } - for (it = additionalSplits.constBegin(); it != additionalSplits.constEnd(); ++it) { - s = (*it); - s.clearId(); - s.setShares(s.shares() * factor); - s.setValue(s.value() * factor); - t.addSplit(s); - } + // additional fee splits + QList additionalSplits; + d->m_loanPaymentPage->additionalFeesSplits(additionalSplits); + QList::const_iterator it; + MyMoneyMoney factor(moneyBorrowed() ? 1 : -1, 1); + + for (it = additionalSplits.constBegin(); it != additionalSplits.constEnd(); ++it) { + s = (*it); + s.clearId(); + s.setShares(s.shares() * factor); + s.setValue(s.value() * factor); + t.addSplit(s); + } - // setup the next due date - t.setPostDate(m_loanSchedulePage->firstPaymentDueDate()); - m_schedule.setTransaction(t); + // setup the next due date + t.setPostDate(d->m_loanSchedulePage->firstPaymentDueDate()); + d->m_schedule.setTransaction(t); + } } + return d->m_schedule; } - return m_schedule; -} - -MyMoneyMoney Wizard::openingBalance() const -{ - // equity accounts don't have an opening balance - if (m_accountTypePage->accountType() == Account::Equity) - return MyMoneyMoney(); - if (m_accountTypePage->accountType() == Account::Loan) { - if (m_generalLoanInfoPage->recordAllPayments()) + MyMoneyMoney Wizard::openingBalance() const + { + Q_D(const Wizard); + // equity accounts don't have an opening balance + if (d->m_accountTypePage->accountType() == Account::Equity) return MyMoneyMoney(); - if (moneyBorrowed()) - return -(m_generalLoanInfoPage->m_openingBalance->value()); - return m_generalLoanInfoPage->m_openingBalance->value(); - } - return m_accountTypePage->m_openingBalance->value(); -} -MyMoneyPrice Wizard::conversionRate() const -{ - if (MyMoneyFile::instance()->baseCurrency().id() == m_accountTypePage->m_currencyComboBox->security().id()) + if (d->m_accountTypePage->accountType() == Account::Loan) { + if (d->m_generalLoanInfoPage->recordAllPayments()) + return MyMoneyMoney(); + if (moneyBorrowed()) + return -(d->m_generalLoanInfoPage->d_func()->ui->m_openingBalance->value()); + return d->m_generalLoanInfoPage->d_func()->ui->m_openingBalance->value(); + } + return d->m_accountTypePage->d_func()->ui->m_openingBalance->value(); + } + + MyMoneyPrice Wizard::conversionRate() const + { + Q_D(const Wizard); + if (MyMoneyFile::instance()->baseCurrency().id() == d->m_accountTypePage->d_func()->ui->m_currencyComboBox->security().id()) + return MyMoneyPrice(MyMoneyFile::instance()->baseCurrency().id(), + d->m_accountTypePage->d_func()->ui->m_currencyComboBox->security().id(), + d->m_accountTypePage->d_func()->ui->m_openingDate->date(), + MyMoneyMoney::ONE, + i18n("User")); return MyMoneyPrice(MyMoneyFile::instance()->baseCurrency().id(), - m_accountTypePage->m_currencyComboBox->security().id(), - m_accountTypePage->m_openingDate->date(), - MyMoneyMoney::ONE, + d->m_accountTypePage->d_func()->ui->m_currencyComboBox->security().id(), + d->m_accountTypePage->d_func()->ui->m_openingDate->date(), + d->m_accountTypePage->d_func()->ui->m_conversionRate->value(), i18n("User")); - return MyMoneyPrice(MyMoneyFile::instance()->baseCurrency().id(), - m_accountTypePage->m_currencyComboBox->security().id(), - m_accountTypePage->m_openingDate->date(), - m_accountTypePage->m_conversionRate->value(), - i18n("User")); -} - -bool Wizard::moneyBorrowed() const -{ - return m_generalLoanInfoPage->m_loanDirection->currentIndex() == 0; -} - -class InstitutionPage::Private -{ -public: - QList m_list; -}; - -InstitutionPage::InstitutionPage(Wizard* wizard) : - KInstitutionPageDecl(wizard), - WizardPage(StepInstitution, this, wizard), - d(new Private()) -{ - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotLoadWidgets())); - connect(m_newInstitutionButton, SIGNAL(clicked()), this, SLOT(slotNewInstitution())); - connect(m_institutionComboBox, SIGNAL(activated(int)), this, SLOT(slotSelectInstitution(int))); - - slotLoadWidgets(); - m_institutionComboBox->setCurrentItem(0); - slotSelectInstitution(0); -} - -InstitutionPage::~InstitutionPage() -{ - delete d; -} - -void InstitutionPage::slotLoadWidgets() -{ - m_institutionComboBox->clear(); - - d->m_list.clear(); - MyMoneyFile::instance()->institutionList(d->m_list); - qSort(d->m_list); - - QList::const_iterator it_l; - m_institutionComboBox->addItem(QString()); - for (it_l = d->m_list.constBegin(); it_l != d->m_list.constEnd(); ++it_l) { - m_institutionComboBox->addItem((*it_l).name()); - } -} - -void InstitutionPage::slotNewInstitution() -{ - MyMoneyInstitution institution; - - emit m_wizard->createInstitution(institution); - - if (!institution.id().isEmpty()) { - QList::const_iterator it_l; - int i = 0; - for (it_l = d->m_list.constBegin(); it_l != d->m_list.constEnd(); ++it_l) { - if ((*it_l).id() == institution.id()) { - // select the item and remember that the very first one is the empty item - m_institutionComboBox->setCurrentIndex(i + 1); - slotSelectInstitution(i + 1); - m_accountNumber->setFocus(); - break; - } - ++i; - } - } -} - -void InstitutionPage::slotSelectInstitution(const int index) -{ - m_accountNumber->setEnabled(index != 0); - m_iban->setEnabled(index != 0); -} - -void InstitutionPage::selectExistingInstitution(const QString& id) -{ - for (int i = 0; i < d->m_list.length(); ++i) { - if (d->m_list[i].id() == id) { - m_institutionComboBox->setCurrentIndex(i + 1); - slotSelectInstitution(i + 1); - break; - } - } -} - -const MyMoneyInstitution& InstitutionPage::institution() const -{ - static MyMoneyInstitution emptyInstitution; - if (m_institutionComboBox->currentIndex() == 0) - return emptyInstitution; - - return d->m_list[m_institutionComboBox->currentIndex()-1]; -} - -KMyMoneyWizardPage* InstitutionPage::nextPage() const -{ - return m_wizard->m_accountTypePage; -} - -AccountTypePage::AccountTypePage(Wizard* wizard) : - KAccountTypePageDecl(wizard), - WizardPage(StepAccount, this, wizard), - m_showPriceWarning(true) -{ - m_typeSelection->insertItem(i18n("Checking"), (int)Account::Checkings); - m_typeSelection->insertItem(i18n("Savings"), (int)Account::Savings); - m_typeSelection->insertItem(i18n("Credit Card"), (int)Account::CreditCard); - m_typeSelection->insertItem(i18n("Cash"), (int)Account::Cash); - m_typeSelection->insertItem(i18n("Loan"), (int)Account::Loan); - m_typeSelection->insertItem(i18n("Investment"), (int)Account::Investment); - m_typeSelection->insertItem(i18n("Asset"), (int)Account::Asset); - m_typeSelection->insertItem(i18n("Liability"), (int)Account::Liability); - if (KMyMoneyGlobalSettings::expertMode()) { - m_typeSelection->insertItem(i18n("Equity"), (int)Account::Equity); - } - - m_typeSelection->setCurrentItem((int)Account::Checkings); - - m_currencyComboBox->setSecurity(MyMoneyFile::instance()->baseCurrency()); - - m_mandatoryGroup->add(m_accountName); - m_mandatoryGroup->add(m_conversionRate->lineedit()); - - m_conversionRate->setValue(MyMoneyMoney::ONE); - slotUpdateCurrency(); - - connect(m_typeSelection, SIGNAL(itemSelected(int)), this, SLOT(slotUpdateType(int))); - connect(m_currencyComboBox, SIGNAL(activated(int)), this, SLOT(slotUpdateCurrency())); - connect(m_conversionRate, SIGNAL(textChanged(QString)), this, SLOT(slotUpdateConversionRate(QString))); - connect(m_conversionRate, SIGNAL(valueChanged(QString)), this, SLOT(slotPriceWarning())); - connect(m_onlineQuote, SIGNAL(clicked()), this, SLOT(slotGetOnlineQuote())); -} - -void AccountTypePage::slotUpdateType(int i) -{ - hideShowPages(static_cast(i)); - m_openingBalance->setDisabled(static_cast(i) == Account::Equity); -} - -void AccountTypePage::hideShowPages(Account accountType) const -{ - bool hideSchedulePage = (accountType != Account::CreditCard) - && (accountType != Account::Loan); - bool hideLoanPage = (accountType != Account::Loan); - m_wizard->setStepHidden(StepDetails, hideLoanPage); - m_wizard->setStepHidden(StepPayments, hideLoanPage); - m_wizard->setStepHidden(StepFees, hideLoanPage); - m_wizard->setStepHidden(StepSchedule, hideSchedulePage); - m_wizard->setStepHidden(StepPayout, (accountType != Account::Loan)); - m_wizard->setStepHidden(StepBroker, accountType != Account::Investment); - m_wizard->setStepHidden(StepParentAccount, accountType == Account::Loan); - // Force an update of the steps in case the list has changed - m_wizard->reselectStep(); -} - -KMyMoneyWizardPage* AccountTypePage::nextPage() const -{ - if (accountType() == Account::Loan) - return m_wizard->m_generalLoanInfoPage; - if (accountType() == Account::CreditCard) - return m_wizard->m_schedulePage; - if (accountType() == Account::Investment) - return m_wizard->m_brokeragepage; - return m_wizard->m_hierarchyPage; -} - -void AccountTypePage::slotUpdateCurrency() -{ - MyMoneyAccount acc; - acc.setAccountType(accountType()); - - m_openingBalance->setPrecision(MyMoneyMoney::denomToPrec(acc.fraction(currency()))); - - bool show = m_currencyComboBox->security().id() != MyMoneyFile::instance()->baseCurrency().id(); - m_conversionLabel->setVisible(show); - m_conversionRate->setVisible(show); - m_conversionExample->setVisible(show); - m_onlineQuote->setVisible(show); - m_conversionRate->setEnabled(show); // make sure to include/exclude in mandatoryGroup - m_conversionRate->setPrecision(m_currencyComboBox->security().pricePrecision()); - m_mandatoryGroup->changed(); - slotUpdateConversionRate(m_conversionRate->lineedit()->text()); -} - -void AccountTypePage::slotGetOnlineQuote() -{ - QString id = MyMoneyFile::instance()->baseCurrency().id() + ' ' + m_currencyComboBox->security().id(); - QPointer dlg = new KEquityPriceUpdateDlg(this, id); - if (dlg->exec() == QDialog::Accepted) { - const MyMoneyPrice &price = dlg->price(id); - if (price.isValid()) { - m_conversionRate->setValue(price.rate(m_currencyComboBox->security().id())); - if (price.date() != m_openingDate->date()) { - priceWarning(true); - } - } - } - delete dlg; -} - -void AccountTypePage::slotPriceWarning() -{ - priceWarning(false); -} - -void AccountTypePage::priceWarning(bool always) -{ - if (m_showPriceWarning || always) { - KMessageBox::information(this, i18n("Please make sure to enter the correct conversion for the selected opening date. If you requested an online quote it might be provided for a different date."), i18n("Check date")); - } - m_showPriceWarning = false; -} - -void AccountTypePage::slotUpdateConversionRate(const QString& txt) -{ - m_conversionExample->setText(i18n("1 %1 equals %2", MyMoneyFile::instance()->baseCurrency().tradingSymbol(), MyMoneyMoney(txt).formatMoney(m_currencyComboBox->security().tradingSymbol(), m_currencyComboBox->security().pricePrecision()))); -} - -bool AccountTypePage::isComplete() const -{ - // check that the conversion rate is positive if enabled - bool rc = !m_conversionRate->isVisible() || (!m_conversionRate->value().isZero() && !m_conversionRate->value().isNegative()); - if (!rc) { - m_wizard->m_nextButton->setToolTip(i18n("Conversion rate is not positive")); - - } else { - rc = KMyMoneyWizardPage::isComplete(); - - if (!rc) { - m_wizard->m_nextButton->setToolTip(i18n("No account name supplied")); - } - } - hideShowPages(accountType()); - return rc; -} - -Account AccountTypePage::accountType() const -{ - return static_cast(m_typeSelection->currentItem()); -} - -const MyMoneySecurity& AccountTypePage::currency() const -{ - return m_currencyComboBox->security(); -} - -void AccountTypePage::setAccount(const MyMoneyAccount& acc) -{ - if (acc.accountType() != Account::Unknown) { - if (acc.accountType() == Account::AssetLoan) { - m_typeSelection->setCurrentItem((int)Account::Loan); - } else { - m_typeSelection->setCurrentItem((int)acc.accountType()); - } - } - m_openingDate->setDate(acc.openingDate()); - m_accountName->setText(acc.name()); -} - -const MyMoneyAccount& AccountTypePage::parentAccount() -{ - switch (accountType()) { - case Account::CreditCard: - case Account::Liability: - case Account::Loan: // Can be either but we return liability here - return MyMoneyFile::instance()->liability(); - break; - case Account::Equity: - return MyMoneyFile::instance()->equity(); - default: - break; - } - return MyMoneyFile::instance()->asset(); -} - -bool AccountTypePage::allowsParentAccount() const -{ - return accountType() != Account::Loan; -} - -BrokeragePage::BrokeragePage(Wizard* wizard) : - KBrokeragePageDecl(wizard), - WizardPage(StepBroker, this, wizard) -{ - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotLoadWidgets())); -} - -void BrokeragePage::slotLoadWidgets() -{ - m_brokerageCurrency->update(QString("x")); -} - -void BrokeragePage::enterPage() -{ - // assign the currency of the investment account to the - // brokerage account if nothing else has ever been selected - if (m_brokerageCurrency->security().id().isEmpty()) { - m_brokerageCurrency->setSecurity(m_wizard->m_accountTypePage->m_currencyComboBox->security()); - } - - // check if the institution relevant fields should be enabled or not - bool enabled = m_wizard->m_institutionPage->m_accountNumber->isEnabled(); - m_accountNumberLabel->setEnabled(enabled); - m_accountNumber->setEnabled(enabled); - m_ibanLabel->setEnabled(enabled); - m_iban->setEnabled(enabled); -} - -KMyMoneyWizardPage* BrokeragePage::nextPage() const -{ - return m_wizard->m_hierarchyPage; -} - -CreditCardSchedulePage::CreditCardSchedulePage(Wizard* wizard) : - KSchedulePageDecl(wizard), - WizardPage(StepSchedule, this, wizard) -{ - m_mandatoryGroup->add(m_name); - m_mandatoryGroup->add(m_payee); - m_mandatoryGroup->add(m_amount->lineedit()); - m_mandatoryGroup->add(m_paymentAccount); - connect(m_paymentAccount, SIGNAL(itemSelected(QString)), object(), SIGNAL(completeStateChanged())); - connect(m_payee, SIGNAL(itemSelected(QString)), object(), SIGNAL(completeStateChanged())); - connect(m_date, SIGNAL(dateChanged(QDate)), object(), SIGNAL(completeStateChanged())); - - connect(m_payee, SIGNAL(createItem(QString,QString&)), wizard, SIGNAL(createPayee(QString,QString&))); - - m_reminderCheckBox->setChecked(true); - connect(m_reminderCheckBox, SIGNAL(toggled(bool)), object(), SIGNAL(completeStateChanged())); - - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotLoadWidgets())); - - m_method->insertItem(i18n("Write check"), (int)Schedule::PaymentType::WriteChecque); -#if 0 - m_method->insertItem(i18n("Direct debit"), Schedule::PaymentType::DirectDebit); - m_method->insertItem(i18n("Bank transfer"), Schedule::PaymentType::BankTransfer); -#endif - m_method->insertItem(i18n("Standing order"), (int)Schedule::PaymentType::StandingOrder); - m_method->insertItem(i18n("Manual deposit"), (int)Schedule::PaymentType::ManualDeposit); - m_method->insertItem(i18n("Direct deposit"), (int)Schedule::PaymentType::DirectDeposit); - m_method->insertItem(i18nc("Other payment method", "Other"), (int)Schedule::PaymentType::Other); - m_method->setCurrentItem((int)Schedule::PaymentType::DirectDebit); - - slotLoadWidgets(); -} - -void CreditCardSchedulePage::enterPage() -{ - if (m_name->text().isEmpty()) - m_name->setText(i18n("Credit Card %1 monthly payment", m_wizard->m_accountTypePage->m_accountName->text())); -} - -bool CreditCardSchedulePage::isComplete() const -{ - bool rc = true; - QString msg = i18n("Finish entry and create account"); - if (m_reminderCheckBox->isChecked()) { - msg = i18n("Finish entry and create account and schedule"); - if (m_date->date() < m_wizard->m_accountTypePage->m_openingDate->date()) { - rc = false; - msg = i18n("Next due date is prior to opening date"); - } - if (m_paymentAccount->selectedItem().isEmpty()) { - rc = false; - msg = i18n("No account selected"); - } - if (m_amount->lineedit()->text().isEmpty()) { - rc = false; - msg = i18n("No amount for payment selected"); - } - if (m_payee->selectedItem().isEmpty()) { - rc = false; - msg = i18n("No payee for payment selected"); - } - if (m_name->text().isEmpty()) { - rc = false; - msg = i18n("No name assigned for schedule"); - } - } - m_wizard->m_finishButton->setToolTip(msg); - - return rc; -} - -void CreditCardSchedulePage::slotLoadWidgets() -{ - AccountSet set; - set.addAccountGroup(Account::Asset); - set.load(m_paymentAccount->selector()); - - m_payee->loadPayees(MyMoneyFile::instance()->payeeList()); -} - -KMyMoneyWizardPage* CreditCardSchedulePage::nextPage() const -{ - return m_wizard->m_hierarchyPage; -} - -GeneralLoanInfoPage::GeneralLoanInfoPage(Wizard* wizard) : - KGeneralLoanInfoPageDecl(wizard), - WizardPage(StepDetails, this, wizard), - m_firstTime(true) -{ - m_mandatoryGroup->add(m_payee); - - // remove the unsupported payment and compounding frequencies and setup default - m_paymentFrequency->removeItem((int)Schedule::Occurrence::Once); - m_paymentFrequency->removeItem((int)Schedule::Occurrence::EveryOtherYear); - m_paymentFrequency->setCurrentItem((int)Schedule::Occurrence::Monthly); - m_compoundFrequency->removeItem((int)Schedule::Occurrence::Once); - m_compoundFrequency->removeItem((int)Schedule::Occurrence::EveryOtherYear); - m_compoundFrequency->setCurrentItem((int)Schedule::Occurrence::Monthly); - - slotLoadWidgets(); - - connect(m_payee, SIGNAL(createItem(QString,QString&)), wizard, SIGNAL(createPayee(QString,QString&))); - connect(m_anyPayments, SIGNAL(activated(int)), object(), SIGNAL(completeStateChanged())); - connect(m_recordings, SIGNAL(activated(int)), object(), SIGNAL(completeStateChanged())); - - connect(m_interestType, SIGNAL(activated(int)), object(), SIGNAL(completeStateChanged())); - connect(m_interestChangeDateEdit, SIGNAL(dateChanged(QDate)), object(), SIGNAL(completeStateChanged())); - connect(m_openingBalance, SIGNAL(textChanged(QString)), object(), SIGNAL(completeStateChanged())); - - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotLoadWidgets())); -} - -KMyMoneyWizardPage* GeneralLoanInfoPage::nextPage() const -{ - return m_wizard->m_loanDetailsPage; -} - -bool GeneralLoanInfoPage::recordAllPayments() const -{ - bool rc = true; // all payments - if (m_recordings->isEnabled()) { - if (m_recordings->currentIndex() != 0) - rc = false; - } - return rc; -} - -void GeneralLoanInfoPage::enterPage() -{ - if (m_firstTime) { - // setup default dates to last of this month and one year on top - QDate firstDay(QDate::currentDate().year(), QDate::currentDate().month(), 1); - m_firstPaymentDate->setDate(firstDay.addMonths(1).addDays(-1)); - m_interestChangeDateEdit->setDate(m_firstPaymentDate->date().addYears(1));; - m_firstTime = false; - } -} - -bool GeneralLoanInfoPage::isComplete() const -{ - m_wizard->setStepHidden(StepPayout, !m_wizard->openingBalance().isZero()); - bool rc = KMyMoneyWizardPage::isComplete(); - if (!rc) { - m_wizard->m_nextButton->setToolTip(i18n("No payee supplied")); - } - - // fixup availability of items on this page - m_recordings->setDisabled(m_anyPayments->currentIndex() == 0); - - m_interestFrequencyAmountEdit->setDisabled(m_interestType->currentIndex() == 0); - m_interestFrequencyUnitEdit->setDisabled(m_interestType->currentIndex() == 0); - m_interestChangeDateEdit->setDisabled(m_interestType->currentIndex() == 0); - - m_openingBalance->setDisabled(recordAllPayments()); - - if (m_openingBalance->isEnabled() && m_openingBalance->lineedit()->text().length() == 0) { - rc = false; - m_wizard->m_nextButton->setToolTip(i18n("No opening balance supplied")); } - if (rc - && (m_interestType->currentIndex() != 0) - && (m_interestChangeDateEdit->date() <= m_firstPaymentDate->date())) { - rc = false; - m_wizard->m_nextButton->setToolTip(i18n("An interest change can only happen after the first payment")); + bool Wizard::moneyBorrowed() const + { + Q_D(const Wizard); + return d->m_generalLoanInfoPage->d_func()->ui->m_loanDirection->currentIndex() == 0; } - return rc; -} - -const MyMoneyAccount& GeneralLoanInfoPage::parentAccount() -{ - return (m_loanDirection->currentIndex() == 0) - ? MyMoneyFile::instance()->liability() - : MyMoneyFile::instance()->asset(); -} - -void GeneralLoanInfoPage::slotLoadWidgets() -{ - m_payee->loadPayees(MyMoneyFile::instance()->payeeList()); -} - -LoanDetailsPage::LoanDetailsPage(Wizard* wizard) : - KLoanDetailsPageDecl(wizard), - WizardPage(StepPayments, this, wizard), - m_needCalculate(true) -{ - // force the balloon payment to zero (default) - m_balloonAmount->setValue(MyMoneyMoney()); - // allow any precision for the interest rate - m_interestRate->setPrecision(-1); - - connect(m_paymentDue, SIGNAL(activated(int)), this, SLOT(slotValuesChanged())); - - connect(m_termAmount, SIGNAL(valueChanged(int)), this, SLOT(slotValuesChanged())); - connect(m_termUnit, SIGNAL(highlighted(int)), this, SLOT(slotValuesChanged())); - connect(m_loanAmount, SIGNAL(textChanged(QString)), this, SLOT(slotValuesChanged())); - connect(m_interestRate, SIGNAL(textChanged(QString)), this, SLOT(slotValuesChanged())); - connect(m_paymentAmount, SIGNAL(textChanged(QString)), this, SLOT(slotValuesChanged())); - connect(m_balloonAmount, SIGNAL(textChanged(QString)), this, SLOT(slotValuesChanged())); - - connect(m_calculateButton, SIGNAL(clicked()), this, SLOT(slotCalculate())); -} - -void LoanDetailsPage::enterPage() -{ - // we need to remove a bunch of entries of the payment frequencies - m_termUnit->clear(); - - m_mandatoryGroup->clear(); - if (!m_wizard->openingBalance().isZero()) { - m_mandatoryGroup->add(m_loanAmount->lineedit()); - if (m_loanAmount->lineedit()->text().length() == 0) { - m_loanAmount->setValue(m_wizard->openingBalance().abs()); - } - } - - switch (m_wizard->m_generalLoanInfoPage->m_paymentFrequency->currentItem()) { - default: - m_termUnit->insertItem(i18n("Payments"), (int)Schedule::Occurrence::Once); - m_termUnit->setCurrentItem((int)Schedule::Occurrence::Once); - break; - case Schedule::Occurrence::Monthly: - m_termUnit->insertItem(i18n("Months"), (int)Schedule::Occurrence::Monthly); - m_termUnit->insertItem(i18n("Years"), (int)Schedule::Occurrence::Yearly); - m_termUnit->setCurrentItem((int)Schedule::Occurrence::Monthly); - break; - case Schedule::Occurrence::Yearly: - m_termUnit->insertItem(i18n("Years"), (int)Schedule::Occurrence::Yearly); - m_termUnit->setCurrentItem((int)Schedule::Occurrence::Yearly); - break; - } -} - -void LoanDetailsPage::slotValuesChanged() -{ - m_needCalculate = true; - m_wizard->completeStateChanged(); -} - -void LoanDetailsPage::slotCalculate() -{ - MyMoneyFinancialCalculator calc; - double val; - int PF, CF; - QString result; - bool moneyBorrowed = m_wizard->moneyBorrowed(); - bool moneyLend = !moneyBorrowed; - - // FIXME: for now, we only support interest calculation at the end of the period - calc.setBep(); - // FIXME: for now, we only support periodic compounding - calc.setDisc(); - - PF = m_wizard->m_generalLoanInfoPage->m_paymentFrequency->eventsPerYear(); - CF = m_wizard->m_generalLoanInfoPage->m_compoundFrequency->eventsPerYear(); - - if (PF == 0 || CF == 0) - return; - - calc.setPF(PF); - calc.setCF(CF); - - - if (!m_loanAmount->lineedit()->text().isEmpty()) { - val = m_loanAmount->value().abs().toDouble(); - if (moneyBorrowed) - val = -val; - calc.setPv(val); - } - - if (!m_interestRate->lineedit()->text().isEmpty()) { - val = m_interestRate->value().abs().toDouble(); - calc.setIr(val); - } - - if (!m_paymentAmount->lineedit()->text().isEmpty()) { - val = m_paymentAmount->value().abs().toDouble(); - if (moneyLend) - val = -val; - calc.setPmt(val); - } - - if (!m_balloonAmount->lineedit()->text().isEmpty()) { - val = m_balloonAmount->value().abs().toDouble(); - if (moneyLend) - val = -val; - calc.setFv(val); - } - - if (m_termAmount->value() != 0) { - calc.setNpp(term()); - } - - // setup of parameters is done, now do the calculation - try { - if (m_loanAmount->lineedit()->text().isEmpty()) { - // calculate the amount of the loan out of the other information - val = calc.presentValue(); - m_loanAmount->loadText(MyMoneyMoney(static_cast(val)).abs().formatMoney(QString(), m_wizard->precision())); - result = i18n("KMyMoney has calculated the amount of the loan as %1.", m_loanAmount->lineedit()->text()); - - } else if (m_interestRate->lineedit()->text().isEmpty()) { - // calculate the interest rate out of the other information - val = calc.interestRate(); - - m_interestRate->loadText(MyMoneyMoney(static_cast(val)).abs().formatMoney(QString(), 3)); - result = i18n("KMyMoney has calculated the interest rate to %1%.", m_interestRate->lineedit()->text()); - - } else if (m_paymentAmount->lineedit()->text().isEmpty()) { - // calculate the periodical amount of the payment out of the other information - val = calc.payment(); - m_paymentAmount->setValue(MyMoneyMoney(static_cast(val)).abs()); - // reset payment as it might have changed due to rounding - val = m_paymentAmount->value().abs().toDouble(); - if (moneyLend) - val = -val; - calc.setPmt(val); - - result = i18n("KMyMoney has calculated a periodic payment of %1 to cover principal and interest.", m_paymentAmount->lineedit()->text()); - - val = calc.futureValue(); - if ((moneyBorrowed && val < 0 && qAbs(val) >= qAbs(calc.payment())) - || (moneyLend && val > 0 && qAbs(val) >= qAbs(calc.payment()))) { - calc.setNpp(calc.npp() - 1); - // updateTermWidgets(calc.npp()); - val = calc.futureValue(); - MyMoneyMoney refVal(static_cast(val)); - m_balloonAmount->loadText(refVal.abs().formatMoney(QString(), m_wizard->precision())); - result += QString(" "); - result += i18n("The number of payments has been decremented and the balloon payment has been modified to %1.", m_balloonAmount->lineedit()->text()); - } else if ((moneyBorrowed && val < 0 && qAbs(val) < qAbs(calc.payment())) - || (moneyLend && val > 0 && qAbs(val) < qAbs(calc.payment()))) { - m_balloonAmount->loadText(MyMoneyMoney().formatMoney(QString(), m_wizard->precision())); - } else { - MyMoneyMoney refVal(static_cast(val)); - m_balloonAmount->loadText(refVal.abs().formatMoney(QString(), m_wizard->precision())); - result += i18n("The balloon payment has been modified to %1.", m_balloonAmount->lineedit()->text()); - } - - } else if (m_termAmount->value() == 0) { - // calculate the number of payments out of the other information - val = calc.numPayments(); - if (val == 0) - throw MYMONEYEXCEPTION("incorrect fincancial calculation"); - - // if the number of payments has a fractional part, then we - // round it to the smallest integer and calculate the balloon payment - result = i18n("KMyMoney has calculated the term of your loan as %1. ", updateTermWidgets(qFloor(val))); - - if (val != qFloor(val)) { - calc.setNpp(qFloor(val)); - val = calc.futureValue(); - MyMoneyMoney refVal(static_cast(val)); - m_balloonAmount->loadText(refVal.abs().formatMoney(QString(), m_wizard->precision())); - result += i18n("The balloon payment has been modified to %1.", m_balloonAmount->lineedit()->text()); - } - - } else { - // calculate the future value of the loan out of the other information - val = calc.futureValue(); - - // we differentiate between the following cases: - // a) the future value is greater than a payment - // b) the future value is less than a payment or the loan is overpaid - // c) all other cases - // - // a) means, we have paid more than we owed. This can't be - // b) means, we paid more than we owed but the last payment is - // less in value than regular payments. That means, that the - // future value is to be treated as (fully payed back) - // c) the loan is not payed back yet - if ((moneyBorrowed && val < 0 && qAbs(val) > qAbs(calc.payment())) - || (moneyLend && val > 0 && qAbs(val) > qAbs(calc.payment()))) { - // case a) - qDebug("Future Value is %f", val); - throw MYMONEYEXCEPTION("incorrect fincancial calculation"); - - } else if ((moneyBorrowed && val < 0 && qAbs(val) <= qAbs(calc.payment())) - || (moneyLend && val > 0 && qAbs(val) <= qAbs(calc.payment()))) { - // case b) - val = 0; - } - - MyMoneyMoney refVal(static_cast(val)); - result = i18n("KMyMoney has calculated a balloon payment of %1 for this loan.", refVal.abs().formatMoney(QString(), m_wizard->precision())); - - if (!m_balloonAmount->lineedit()->text().isEmpty()) { - if ((m_balloonAmount->value().abs() - refVal.abs()).abs().toDouble() > 1) { - throw MYMONEYEXCEPTION("incorrect fincancial calculation"); - } - result = i18n("KMyMoney has successfully verified your loan information."); - } - m_balloonAmount->loadText(refVal.abs().formatMoney(QString(), m_wizard->precision())); - } - - } catch (const MyMoneyException &) { - KMessageBox::error(0, - i18n("You have entered mis-matching information. Please modify " - "your figures or leave one value empty " - "to let KMyMoney calculate it for you"), - i18n("Calculation error")); - return; - } - - result += i18n("\n\nAccept this or modify the loan information and recalculate."); - - KMessageBox::information(0, result, i18n("Calculation successful")); - m_needCalculate = false; - - // now update change - m_wizard->completeStateChanged(); -} - -int LoanDetailsPage::term() const -{ - int factor = 0; - - if (m_termAmount->value() != 0) { - factor = 1; - switch (m_termUnit->currentItem()) { - case Schedule::Occurrence::Yearly: // years - factor = 12; - // intentional fall through - - case Schedule::Occurrence::Monthly: // months - factor *= 30; - factor *= m_termAmount->value(); - // factor now is the duration in days. we divide this by the - // payment frequency and get the number of payments - factor /= m_wizard->m_generalLoanInfoPage->m_paymentFrequency->daysBetweenEvents(); - break; - - default: - qDebug("Unknown term unit %d in LoanDetailsPage::term(). Using payments.", (int)m_termUnit->currentItem()); - // intentional fall through - - case Schedule::Occurrence::Once: // payments - factor = m_termAmount->value(); - break; - } - } - return factor; -} - -QString LoanDetailsPage::updateTermWidgets(const double val) -{ - long vl = qFloor(val); - - QString valString; - Schedule::Occurrence unit = m_termUnit->currentItem(); - - if ((unit == Schedule::Occurrence::Monthly) - && ((vl % 12) == 0)) { - vl /= 12; - unit = Schedule::Occurrence::Yearly; - } - - switch (unit) { - case Schedule::Occurrence::Monthly: - valString = i18np("one month", "%1 months", vl); - m_termUnit->setCurrentItem((int)Schedule::Occurrence::Monthly); - break; - case Schedule::Occurrence::Yearly: - valString = i18np("one year", "%1 years", vl); - m_termUnit->setCurrentItem((int)Schedule::Occurrence::Yearly); - break; - default: - valString = i18np("one payment", "%1 payments", vl); - m_termUnit->setCurrentItem((int)Schedule::Occurrence::Once); - break; - } - m_termAmount->setValue(vl); - return valString; -} - -bool LoanDetailsPage::isComplete() const -{ - // bool rc = KMyMoneyWizardPage::isComplete(); - - int fieldCnt = 0; - - if (m_loanAmount->lineedit()->text().length() > 0) { - fieldCnt++; - } - - if (m_interestRate->lineedit()->text().length() > 0) { - fieldCnt++; - } - - if (m_termAmount->value() != 0) { - fieldCnt++; - } - - if (m_paymentAmount->lineedit()->text().length() > 0) { - fieldCnt++; - } - - if (m_balloonAmount->lineedit()->text().length() > 0) { - fieldCnt++; - } - - m_calculateButton->setEnabled(fieldCnt == 4 || (fieldCnt == 5 && m_needCalculate)); - - m_calculateButton->setAutoDefault(false); - m_calculateButton->setDefault(false); - if (m_needCalculate && fieldCnt == 4) { - m_wizard->m_nextButton->setToolTip(i18n("Press Calculate to verify the values")); - m_calculateButton->setAutoDefault(true); - m_calculateButton->setDefault(true); - } else if (fieldCnt != 5) { - m_wizard->m_nextButton->setToolTip(i18n("Not all details supplied")); - m_calculateButton->setAutoDefault(true); - m_calculateButton->setDefault(true); - } - m_wizard->m_nextButton->setAutoDefault(!m_calculateButton->autoDefault()); - m_wizard->m_nextButton->setDefault(!m_calculateButton->autoDefault()); - - return (fieldCnt == 5) && !m_needCalculate; -} - -KMyMoneyWizardPage* LoanDetailsPage::nextPage() const -{ - return m_wizard->m_loanPaymentPage; -} - - -class LoanPaymentPage::Private -{ -public: - MyMoneyAccount phonyAccount; - MyMoneySplit phonySplit; - MyMoneyTransaction additionalFeesTransaction; - MyMoneyMoney additionalFees; -}; - -LoanPaymentPage::LoanPaymentPage(Wizard* wizard) : - KLoanPaymentPageDecl(wizard), - WizardPage(StepFees, this, wizard), - d(new Private) -{ - d->phonyAccount = MyMoneyAccount(QLatin1String("Phony-ID"), MyMoneyAccount()); - - d->phonySplit.setAccountId(d->phonyAccount.id()); - d->phonySplit.setValue(MyMoneyMoney()); - d->phonySplit.setShares(MyMoneyMoney()); - - d->additionalFeesTransaction.addSplit(d->phonySplit); - - connect(m_additionalFeesButton, SIGNAL(clicked()), this, SLOT(slotAdditionalFees())); -} - -LoanPaymentPage::~LoanPaymentPage() -{ - delete d; -} - -MyMoneyMoney LoanPaymentPage::basePayment() const -{ - return m_wizard->m_loanDetailsPage->m_paymentAmount->value(); -} - -MyMoneyMoney LoanPaymentPage::additionalFees() const -{ - return d->additionalFees; -} - -void LoanPaymentPage::additionalFeesSplits(QList& list) -{ - list.clear(); - - QList::ConstIterator it; - for (it = d->additionalFeesTransaction.splits().constBegin(); it != d->additionalFeesTransaction.splits().constEnd(); ++it) { - if ((*it).accountId() != d->phonyAccount.id()) { - list << (*it); - } - } -} - -void LoanPaymentPage::updateAmounts() -{ - m_additionalFees->setText(d->additionalFees.formatMoney(m_wizard->currency().tradingSymbol(), m_wizard->precision())); - m_totalPayment->setText((basePayment() + d->additionalFees).formatMoney(m_wizard->currency().tradingSymbol(), m_wizard->precision())); -} - -void LoanPaymentPage::enterPage() -{ - const MyMoneySecurity& currency = m_wizard->currency(); - - m_basePayment->setText(basePayment().formatMoney(currency.tradingSymbol(), m_wizard->precision())); - d->phonyAccount.setCurrencyId(currency.id()); - d->additionalFeesTransaction.setCommodity(currency.id()); - - updateAmounts(); -} - -void LoanPaymentPage::slotAdditionalFees() -{ - QMap priceInfo; - QPointer dlg = new KSplitTransactionDlg(d->additionalFeesTransaction, d->phonySplit, d->phonyAccount, false, !m_wizard->moneyBorrowed(), MyMoneyMoney(), priceInfo); - - // connect(dlg, SIGNAL(newCategory(MyMoneyAccount&)), this, SIGNAL(newCategory(MyMoneyAccount&))); - - if (dlg->exec() == QDialog::Accepted) { - d->additionalFeesTransaction = dlg->transaction(); - // sum up the additional fees - QList::ConstIterator it; - - d->additionalFees = MyMoneyMoney(); - for (it = d->additionalFeesTransaction.splits().constBegin(); it != d->additionalFeesTransaction.splits().constEnd(); ++it) { - if ((*it).accountId() != d->phonyAccount.id()) { - d->additionalFees += (*it).shares(); - } - } - updateAmounts(); - } - - delete dlg; -} - -KMyMoneyWizardPage* LoanPaymentPage::nextPage() const -{ - return m_wizard->m_loanSchedulePage; -} - - -LoanSchedulePage::LoanSchedulePage(Wizard* wizard) : - KLoanSchedulePageDecl(wizard), - WizardPage(StepSchedule, this, wizard) -{ - m_mandatoryGroup->add(m_interestCategory->lineEdit()); - m_mandatoryGroup->add(m_paymentAccount->lineEdit()); - connect(m_interestCategory, SIGNAL(createItem(QString,QString&)), this, SLOT(slotCreateCategory(QString,QString&))); - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotLoadWidgets())); -} - -void LoanSchedulePage::slotCreateCategory(const QString& name, QString& id) -{ - MyMoneyAccount acc, parent; - acc.setName(name); - - if (m_wizard->moneyBorrowed()) - parent = MyMoneyFile::instance()->expense(); - else - parent = MyMoneyFile::instance()->income(); - - emit m_wizard->createCategory(acc, parent); - - // return id - id = acc.id(); -} - -QDate LoanSchedulePage::firstPaymentDueDate() const -{ - if (m_firstPaymentDueDate->isEnabled()) - return m_firstPaymentDueDate->date(); - return m_wizard->m_generalLoanInfoPage->m_firstPaymentDate->date(); -} - -void LoanSchedulePage::enterPage() -{ - m_interestCategory->setFocus(); - m_firstPaymentDueDate->setDisabled(m_wizard->m_generalLoanInfoPage->recordAllPayments()); - slotLoadWidgets(); -} - -void LoanSchedulePage::slotLoadWidgets() -{ - AccountSet set; - if (m_wizard->moneyBorrowed()) - set.addAccountGroup(Account::Expense); - else - set.addAccountGroup(Account::Income); - set.load(m_interestCategory->selector()); - - set.clear(); - set.addAccountGroup(Account::Asset); - set.load(m_paymentAccount->selector()); -} - -KMyMoneyWizardPage* LoanSchedulePage::nextPage() const -{ - // if the balance widget of the general loan info page is enabled and - // the value is not zero, then the payout already happened and we don't - // aks for it. - if (m_wizard->openingBalance().isZero()) - return m_wizard->m_loanPayoutPage; - return m_wizard->m_accountSummaryPage; -} - -LoanPayoutPage::LoanPayoutPage(Wizard* wizard) : - KLoanPayoutPageDecl(wizard), - WizardPage(StepPayout, this, wizard) -{ - m_mandatoryGroup->add(m_assetAccount->lineEdit()); - m_mandatoryGroup->add(m_loanAccount->lineEdit()); - - KGuiItem createAssetButtenItem(i18n("&Create..."), - QIcon::fromTheme(g_Icons[Icon::DocumentNew]), - i18n("Create a new asset account"), - i18n("If the asset account does not yet exist, press this button to create it.")); - KGuiItem::assign(m_createAssetButton, createAssetButtenItem); - m_createAssetButton->setToolTip(createAssetButtenItem.toolTip()); - m_createAssetButton->setWhatsThis(createAssetButtenItem.whatsThis()); - connect(m_createAssetButton, SIGNAL(clicked()), this, SLOT(slotCreateAssetAccount())); - - connect(m_noPayoutTransaction, SIGNAL(toggled(bool)), this, SLOT(slotButtonsToggled())); - connect(m_refinanceLoan, SIGNAL(toggled(bool)), this, SLOT(slotButtonsToggled())); - - connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotLoadWidgets())); - slotLoadWidgets(); -} - -void LoanPayoutPage::slotButtonsToggled() -{ - // we don't go directly, as the order of the emission of signals to slots is - // not defined. Using a single shot timer postpones the call of m_mandatoryGroup::changed() - // until the next round of the main loop so we can be sure to see all relevant changes - // that happened in the meantime (eg. widgets are enabled and disabled) - QTimer::singleShot(0, m_mandatoryGroup, SLOT(changed())); -} - -void LoanPayoutPage::slotCreateAssetAccount() -{ - MyMoneyAccount acc; - acc.setAccountType(Account::Asset); - acc.setOpeningDate(m_wizard->m_accountTypePage->m_openingDate->date()); - - emit m_wizard->createAccount(acc); - - if (!acc.id().isEmpty()) { - m_assetAccount->setSelectedItem(acc.id()); - } -} - -void LoanPayoutPage::slotLoadWidgets() -{ - AccountSet set; - set.addAccountGroup(Account::Asset); - set.load(m_assetAccount->selector()); - - set.clear(); - set.addAccountType(Account::Loan); - set.load(m_loanAccount->selector()); -} - -void LoanPayoutPage::enterPage() -{ - // only allow to create new asset accounts for liability loans - m_createAssetButton->setEnabled(m_wizard->moneyBorrowed()); - m_refinanceLoan->setEnabled(m_wizard->moneyBorrowed()); - if (!m_wizard->moneyBorrowed()) { - m_refinanceLoan->setChecked(false); - } - m_payoutDetailFrame->setDisabled(m_noPayoutTransaction->isChecked()); -} - -KMyMoneyWizardPage* LoanPayoutPage::nextPage() const -{ - return m_wizard->m_accountSummaryPage; -} - -bool LoanPayoutPage::isComplete() const -{ - return KMyMoneyWizardPage::isComplete() | m_noPayoutTransaction->isChecked(); -} - -QString LoanPayoutPage::payoutAccountId() const -{ - if (m_refinanceLoan->isChecked()) { - return m_loanAccount->selectedItem(); - } else { - return m_assetAccount->selectedItem(); - } -} - -HierarchyFilterProxyModel::HierarchyFilterProxyModel(QObject *parent) - : AccountsProxyModel(parent) -{ -} - -/** - * Filter the favorites accounts group. - */ -bool HierarchyFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const -{ - if (!source_parent.isValid()) { - auto accCol = m_mdlColumns->indexOf(eAccountsModel::Column::Account); - QVariant data = sourceModel()->index(source_row, accCol, source_parent).data((int)eAccountsModel::Role::ID); - if (data.isValid() && data.toString() == AccountsModel::favoritesAccountId) - return false; - } - return AccountsProxyModel::filterAcceptsRow(source_row, source_parent); -} - -/** - * Filter all but the first column. - */ -bool HierarchyFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const -{ - Q_UNUSED(source_parent) - if (source_column == 0) - return true; - return false; -} - -HierarchyPage::HierarchyPage(Wizard* wizard) : - KHierarchyPageDecl(wizard), - WizardPage(StepParentAccount, this, wizard), - m_filterProxyModel(nullptr) -{ - // the proxy filter model - m_filterProxyModel = new HierarchyFilterProxyModel(this); - m_filterProxyModel->setHideClosedAccounts(true); - m_filterProxyModel->setHideEquityAccounts(!KMyMoneyGlobalSettings::expertMode()); - m_filterProxyModel->addAccountGroup(QVector {Account::Asset, Account::Liability}); - auto const model = Models::instance()->accountsModel(); - m_filterProxyModel->setSourceModel(model); - m_filterProxyModel->setSourceColumns(model->getColumns()); - m_filterProxyModel->setDynamicSortFilter(true); - - m_parentAccounts->setModel(m_filterProxyModel); - m_parentAccounts->sortByColumn((int)eAccountsModel::Column::Account, Qt::AscendingOrder); - - connect(m_parentAccounts->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(parentAccountChanged())); -} - -void HierarchyPage::enterPage() -{ - // Ensure that the list reflects the Account Type - MyMoneyAccount topAccount = m_wizard->m_accountTypePage->parentAccount(); - m_filterProxyModel->clear(); - m_filterProxyModel->addAccountGroup(QVector {topAccount.accountGroup()}); - m_parentAccounts->expandAll(); -} - -KMyMoneyWizardPage* HierarchyPage::nextPage() const -{ - return m_wizard->m_accountSummaryPage; -} - -const MyMoneyAccount& HierarchyPage::parentAccount() -{ - QVariant data = m_parentAccounts->model()->data(m_parentAccounts->currentIndex(), (int)eAccountsModel::Role::Account); - if (data.isValid()) { - m_parentAccount = data.value(); - } else { - m_parentAccount = MyMoneyAccount(); - } - return m_parentAccount; -} - -bool HierarchyPage::isComplete() const -{ - return m_parentAccounts->currentIndex().isValid(); -} - -void HierarchyPage::parentAccountChanged() -{ - completeStateChanged(); -} - -AccountSummaryPage::AccountSummaryPage(Wizard* wizard) : - KAccountSummaryPageDecl(wizard), - WizardPage(StepFinish, this, wizard) -{ -} - -void AccountSummaryPage::enterPage() -{ - MyMoneyAccount acc = m_wizard->account(); - MyMoneySecurity sec = m_wizard->currency(); - acc.fraction(sec); - - // assign an id to the account inside the wizard which is required for a schedule - // get the schedule and clear the id again in the wizards object. - MyMoneyAccount tmp(QLatin1String("Phony-ID"), acc); - m_wizard->setAccount(tmp); - MyMoneySchedule sch = m_wizard->schedule(); - m_wizard->setAccount(acc); - - m_dataList->clear(); - - - - // Account data - m_dataList->setFontWeight(QFont::Bold); - m_dataList->append(i18n("Account information")); - m_dataList->setFontWeight(QFont::Normal); - m_dataList->append(i18nc("Account name", "Name: %1", acc.name())); - if (!acc.isLoan()) - m_dataList->append(i18n("Subaccount of %1", m_wizard->parentAccount().name())); - QString accTypeText; - if (acc.accountType() == Account::AssetLoan) - accTypeText = i18n("Loan"); - else - accTypeText = m_wizard->m_accountTypePage->m_typeSelection->currentText(); - m_dataList->append(i18n("Type: %1", accTypeText)); - - m_dataList->append(i18n("Currency: %1", m_wizard->currency().name())); - m_dataList->append(i18n("Opening date: %1", QLocale().toString(acc.openingDate()))); - if (m_wizard->currency().id() != MyMoneyFile::instance()->baseCurrency().id()) { - m_dataList->append(i18n("Conversion rate: %1", m_wizard->conversionRate().rate(QString()).formatMoney(QString(), m_wizard->currency().pricePrecision()))); - } - if (!acc.isLoan() || !m_wizard->openingBalance().isZero()) - m_dataList->append(i18n("Opening balance: %1", MyMoneyUtils::formatMoney(m_wizard->openingBalance(), acc, sec))); - - if (!m_wizard->m_institutionPage->institution().id().isEmpty()) { - m_dataList->append(i18n("Institution: %1", m_wizard->m_institutionPage->institution().name())); - if (!acc.number().isEmpty()) { - m_dataList->append(i18n("Number: %1", acc.number())); - } - if (!acc.value("iban").isEmpty()) { - m_dataList->append(i18n("IBAN: %1", acc.value("iban"))); - } - } - - if (acc.accountType() == Account::Investment) { - if (m_wizard->m_brokeragepage->m_createBrokerageButton->isChecked()) { - m_dataList->setFontWeight(QFont::Bold); - m_dataList->append(i18n("Brokerage Account")); - m_dataList->setFontWeight(QFont::Normal); - - m_dataList->append(i18nc("Account name", "Name: %1 (Brokerage)", acc.name())); - m_dataList->append(i18n("Currency: %1", m_wizard->m_brokeragepage->m_brokerageCurrency->security().name())); - if (m_wizard->m_brokeragepage->m_accountNumber->isEnabled() && !m_wizard->m_brokeragepage->m_accountNumber->text().isEmpty()) - m_dataList->append(i18n("Number: %1", m_wizard->m_brokeragepage->m_accountNumber->text())); - if (m_wizard->m_brokeragepage->m_iban->isEnabled() && !m_wizard->m_brokeragepage->m_iban->text().isEmpty()) - m_dataList->append(i18n("IBAN: %1", m_wizard->m_brokeragepage->m_iban->text())); - } - } - - // Loan - if (acc.isLoan()) { - m_dataList->setFontWeight(QFont::Bold); - m_dataList->append(i18n("Loan information")); - m_dataList->setFontWeight(QFont::Normal); - if (m_wizard->moneyBorrowed()) { - m_dataList->append(i18n("Amount borrowed: %1", m_wizard->m_loanDetailsPage->m_loanAmount->value().formatMoney(m_wizard->currency().tradingSymbol(), m_wizard->precision()))); - } else { - m_dataList->append(i18n("Amount lent: %1", m_wizard->m_loanDetailsPage->m_loanAmount->value().formatMoney(m_wizard->currency().tradingSymbol(), m_wizard->precision()))); - } - m_dataList->append(i18n("Interest rate: %1 %", m_wizard->m_loanDetailsPage->m_interestRate->value().formatMoney(QString(), -1))); - m_dataList->append(i18n("Interest rate is %1", m_wizard->m_generalLoanInfoPage->m_interestType->currentText())); - m_dataList->append(i18n("Principal and interest: %1", MyMoneyUtils::formatMoney(m_wizard->m_loanDetailsPage->m_paymentAmount->value(), acc, sec))); - m_dataList->append(i18n("Additional Fees: %1", MyMoneyUtils::formatMoney(m_wizard->m_loanPaymentPage->additionalFees(), acc, sec))); - m_dataList->append(i18n("Payment frequency: %1", m_wizard->m_generalLoanInfoPage->m_paymentFrequency->currentText())); - m_dataList->append(i18n("Payment account: %1", m_wizard->m_loanSchedulePage->m_paymentAccount->currentText())); - - if (!m_wizard->m_loanPayoutPage->m_noPayoutTransaction->isChecked() && m_wizard->openingBalance().isZero()) { - m_dataList->setFontWeight(QFont::Bold); - m_dataList->append(i18n("Payout information")); - m_dataList->setFontWeight(QFont::Normal); - if (m_wizard->m_loanPayoutPage->m_refinanceLoan->isChecked()) { - m_dataList->append(i18n("Refinance: %1", m_wizard->m_loanPayoutPage->m_loanAccount->currentText())); - } else { - if (m_wizard->moneyBorrowed()) - m_dataList->append(i18n("Transfer amount to %1", m_wizard->m_loanPayoutPage->m_assetAccount->currentText())); - else - m_dataList->append(i18n("Transfer amount from %1", m_wizard->m_loanPayoutPage->m_assetAccount->currentText())); - } - m_dataList->append(i18n("Payment date: %1 ", QLocale().toString(m_wizard->m_loanPayoutPage->m_payoutDate->date()))); - } - } - - // Schedule - if (!(sch == MyMoneySchedule())) { - m_dataList->setFontWeight(QFont::Bold); - m_dataList->append(i18n("Schedule information")); - m_dataList->setFontWeight(QFont::Normal); - m_dataList->append(i18nc("Schedule name", "Name: %1", sch.name())); - if (acc.accountType() == Account::CreditCard) { - MyMoneyAccount paymentAccount = MyMoneyFile::instance()->account(m_wizard->m_schedulePage->m_paymentAccount->selectedItem()); - m_dataList->append(i18n("Occurrence: Monthly")); - m_dataList->append(i18n("Paid from %1", paymentAccount.name())); - m_dataList->append(i18n("Pay to %1", m_wizard->m_schedulePage->m_payee->currentText())); - m_dataList->append(i18n("Amount: %1", MyMoneyUtils::formatMoney(m_wizard->m_schedulePage->m_amount->value(), acc, sec))); - m_dataList->append(i18n("First payment due on %1", QLocale().toString(sch.nextDueDate()))); - m_dataList->append(i18n("Payment method: %1", m_wizard->m_schedulePage->m_method->currentText())); - } - if (acc.isLoan()) { - m_dataList->append(i18n("Occurrence: %1", m_wizard->m_generalLoanInfoPage->m_paymentFrequency->currentText())); - m_dataList->append(i18n("Amount: %1", MyMoneyUtils::formatMoney(m_wizard->m_loanPaymentPage->basePayment() + m_wizard->m_loanPaymentPage->additionalFees(), acc, sec))); - m_dataList->append(i18n("First payment due on %1", QLocale().toString(m_wizard->m_loanSchedulePage->firstPaymentDueDate()))); - } - } -} } diff --git a/kmymoney/wizards/newaccountwizard/knewaccountwizard.h b/kmymoney/wizards/newaccountwizard/knewaccountwizard.h index 8045959bb..3be5d0780 100644 --- a/kmymoney/wizards/newaccountwizard/knewaccountwizard.h +++ b/kmymoney/wizards/newaccountwizard/knewaccountwizard.h @@ -1,188 +1,168 @@ /*************************************************************************** knewaccountwizard.h ------------------- begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KNEWACCOUNTWIZARD_H #define KNEWACCOUNTWIZARD_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // Project Includes #include "kmymoneywizard.h" -#include "mymoneyaccountloan.h" -#include "mymoneymoney.h" -#include "mymoneyschedule.h" +class MyMoneyMoney; class MyMoneyPrice; -class MyMoneySecurity; class MyMoneyInstitution; class MyMoneyTransaction; +class MyMoneySchedule; +class MyMoneyAccount; /** * @author Thomas Baumgart */ namespace NewAccountWizard { + enum steps { + StepInstitution = 1, + StepAccount, + StepBroker, + StepDetails, + StepPayments, + StepFees, + StepSchedule, + StepPayout, + StepParentAccount, + StepFinish + }; -class AccountTypePage; -class InstitutionPage; -class BrokeragePage; -class CreditCardSchedulePage; -class GeneralLoanInfoPage; -class LoanDetailsPage; -class LoanPaymentPage; -class LoanSchedulePage; -class LoanPayoutPage; -class HierarchyPage; -class AccountSummaryPage; - -/** + /** * @author Thomas Baumgart * * This class implements the new account wizard which is used to gather * the required information from the user to create a new account */ -class Wizard : public KMyMoneyWizard -{ - friend class AccountTypePage; - friend class InstitutionPage; - friend class BrokeragePage; - friend class CreditCardSchedulePage; - friend class GeneralLoanInfoPage; - friend class LoanDetailsPage; - friend class LoanPaymentPage; - friend class LoanSchedulePage; - friend class LoanPayoutPage; - friend class HierarchyPage; - friend class AccountSummaryPage; - - Q_OBJECT -public: - explicit Wizard(QWidget* parent = 0, bool modal = false, Qt::WindowFlags flags = 0); - - /** + class WizardPrivate; + class Wizard : public KMyMoneyWizard + { + friend class AccountTypePage; + friend class InstitutionPage; + friend class BrokeragePage; + friend class CreditCardSchedulePage; + friend class GeneralLoanInfoPage; + friend class LoanDetailsPage; + friend class LoanPaymentPage; + friend class LoanSchedulePage; + friend class LoanPayoutPage; + friend class HierarchyPage; + friend class AccountSummaryPage; + + Q_OBJECT + Q_DISABLE_COPY(Wizard) + + public: + explicit Wizard(QWidget *parent = nullptr, bool modal = false, Qt::WindowFlags flags = 0); + ~Wizard() override; + + /** * Returns the information about the account as entered by * the user. */ - const MyMoneyAccount& account(); + const MyMoneyAccount& account(); - /** + /** * Method to load the generated account information back into the widget */ - void setAccount(const MyMoneyAccount& acc); + void setAccount(const MyMoneyAccount& acc); - /** + /** * Returns the information about the parent account as entered by * the user. * @note For now it's either fixed as Asset or Liability. We will provide * user selected parent accounts later. */ - const MyMoneyAccount& parentAccount(); + const MyMoneyAccount& parentAccount(); - /** + /** * Returns information about the schedule. If the returned value * equals MyMoneySchedule() then the user did not select to create * a schedule. */ - const MyMoneySchedule& schedule(); + const MyMoneySchedule& schedule(); - /** + /** * This method returns the value of the opening balance * entered by the user */ - MyMoneyMoney openingBalance() const; + MyMoneyMoney openingBalance() const; - /** + /** * This method returns the interest rate as factor, ie an * interest rate of 6.5% will be returned as 0.065 */ - MyMoneyMoney interestRate() const; + MyMoneyMoney interestRate() const; - /** + /** * This method returns the payout transaction for loans. * If the account to be created is not a loan or no * payout transaction should be generated, this method * returns an emtpy transaction. */ - MyMoneyTransaction payoutTransaction(); + MyMoneyTransaction payoutTransaction(); - /** + /** * This method returns a MyMoneyAccount() object filled * with the data to create a brokerage account. If the * user selected not to create a brokerage account or * the account type is not able to create a brokerage * account, an empty MyMoneyAccount() object is returned. * * @note Make sure to call the account() method before you call this method. * Otherwise the returned object might contain unexpected results. */ - MyMoneyAccount brokerageAccount() const; + MyMoneyAccount brokerageAccount() const; - /** + /** * This method returns the conversion rate */ - MyMoneyPrice conversionRate() const; - -protected: - /** - * This method returns the currently selected currency for the account - */ - const MyMoneySecurity& currency() const; + MyMoneyPrice conversionRate() const; - /** - * This method returns the precision in digits for the selected currency. - * @sa currency() - */ - int precision() const; + signals: + void createInstitution(MyMoneyInstitution& institution); + void createAccount(MyMoneyAccount& account); + void createCategory(MyMoneyAccount&, const MyMoneyAccount&); - /** + protected: + /** * This method returns information about the selection of the user * if the loan is for borrowing or lending money. * * @retval true loan is for money borrowed * @retval false loan is for money lent */ - bool moneyBorrowed() const; - -signals: - void createInstitution(MyMoneyInstitution& institution); - void createAccount(MyMoneyAccount& account); - void createCategory(MyMoneyAccount&, const MyMoneyAccount&); - -private: - InstitutionPage* m_institutionPage; - AccountTypePage* m_accountTypePage; - BrokeragePage* m_brokeragepage; - CreditCardSchedulePage* m_schedulePage; - GeneralLoanInfoPage* m_generalLoanInfoPage; - LoanDetailsPage* m_loanDetailsPage; - LoanPaymentPage* m_loanPaymentPage; - LoanSchedulePage* m_loanSchedulePage; - LoanPayoutPage* m_loanPayoutPage; - HierarchyPage* m_hierarchyPage; - AccountSummaryPage* m_accountSummaryPage; - - MyMoneyAccountLoan m_account; - MyMoneySchedule m_schedule; -}; + bool moneyBorrowed() const; + + private: + Q_DECLARE_PRIVATE(Wizard) + }; } // namespace #endif diff --git a/kmymoney/wizards/newaccountwizard/knewaccountwizard_p.h b/kmymoney/wizards/newaccountwizard/knewaccountwizard_p.h index aef223b75..3738e4e90 100644 --- a/kmymoney/wizards/newaccountwizard/knewaccountwizard_p.h +++ b/kmymoney/wizards/newaccountwizard/knewaccountwizard_p.h @@ -1,455 +1,100 @@ /*************************************************************************** knewaccountwizard_p.h ------------------- begin : Tue Sep 25 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KNEWACCOUNTWIZARD_P_H #define KNEWACCOUNTWIZARD_P_H // ---------------------------------------------------------------------------- // QT Includes -#include -#include - // ---------------------------------------------------------------------------- // KDE Includes -#include -#include - // ---------------------------------------------------------------------------- // Project Includes -#include "kmymoneywizardpage.h" -#include -#include -#include -#include -#include -#include "accountsproxymodel.h" - -#include "ui_kinstitutionpagedecl.h" -#include "ui_kaccounttypepagedecl.h" -#include "ui_kbrokeragepagedecl.h" -#include "ui_kschedulepagedecl.h" -#include "ui_kgeneralloaninfopagedecl.h" -#include "ui_kloandetailspagedecl.h" -#include "ui_kloanpaymentpagedecl.h" -#include "ui_kloanschedulepagedecl.h" -#include "ui_kloanpayoutpagedecl.h" -#include "ui_khierarchypagedecl.h" -#include "ui_kaccountsummarypagedecl.h" - -class Wizard; -class MyMoneyInstitution; +#include "kmymoneywizard_p.h" +#include "knewaccountwizard.h" +#include "kaccounttypepage.h" +#include "mymoneyaccountloan.h" +#include "mymoneymoney.h" +#include "mymoneyschedule.h" +#include "mymoneysecurity.h" namespace NewAccountWizard { - - -class KInstitutionPageDecl : public QWidget, public Ui::KInstitutionPageDecl -{ -public: - KInstitutionPageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class InstitutionPage : public KInstitutionPageDecl, public WizardPage -{ - Q_OBJECT -public: - InstitutionPage(Wizard* parent); - ~InstitutionPage(); - KMyMoneyWizardPage* nextPage(void) const; - - QWidget* initialFocusWidget(void) const { - return m_institutionComboBox; - } - - /** - * Returns the information about an institution if entered by - * the user. If the id field is empty, then he did not enter - * such information. - */ - const MyMoneyInstitution& institution(void) const; - - void selectExistingInstitution(const QString& id); - -private slots: - void slotLoadWidgets(void); - void slotNewInstitution(void); - void slotSelectInstitution(int index); - -private: - /// \internal d-pointer class. - class Private; - /// \internal d-pointer instance. - Private* const d; -}; - - -class KAccountTypePageDecl : public QWidget, public Ui::KAccountTypePageDecl -{ -public: - KAccountTypePageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class AccountTypePage : public KAccountTypePageDecl, public WizardPage -{ - Q_OBJECT -public: - AccountTypePage(Wizard* parent); - virtual bool isComplete(void) const; - KMyMoneyWizardPage* nextPage(void) const; - - QWidget* initialFocusWidget(void) const { - return m_accountName; - } - - eMyMoney::Account accountType(void) const; - const MyMoneyAccount& parentAccount(void); - bool allowsParentAccount(void) const; - const MyMoneySecurity& currency(void) const; - - void setAccount(const MyMoneyAccount& acc); - -private: - void hideShowPages(eMyMoney::Account i) const; - void priceWarning(bool); - -private slots: - void slotUpdateType(int i); - void slotUpdateCurrency(void); - void slotUpdateConversionRate(const QString&); - void slotGetOnlineQuote(void); - void slotPriceWarning(void); - -private: - bool m_showPriceWarning; -}; - - -class KBrokeragePageDecl : public QWidget, public Ui::KBrokeragePageDecl -{ -public: - KBrokeragePageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class BrokeragePage : public KBrokeragePageDecl, public WizardPage -{ - Q_OBJECT -public: - BrokeragePage(Wizard* parent); - KMyMoneyWizardPage* nextPage(void) const; - void enterPage(void); - - QWidget* initialFocusWidget(void) const { - return m_createBrokerageButton; - } - -private slots: - void slotLoadWidgets(void); -}; - - -class KSchedulePageDecl : public QWidget, public Ui::KSchedulePageDecl -{ -public: - KSchedulePageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class CreditCardSchedulePage : public KSchedulePageDecl, public WizardPage -{ - Q_OBJECT -public: - CreditCardSchedulePage(Wizard* parent); - KMyMoneyWizardPage* nextPage(void) const; - virtual bool isComplete(void) const; - void enterPage(void); - - QWidget* initialFocusWidget(void) const { - return m_reminderCheckBox; - } - -private slots: - void slotLoadWidgets(void); -}; - - -class KGeneralLoanInfoPageDecl : public QWidget, public Ui::KGeneralLoanInfoPageDecl -{ -public: - KGeneralLoanInfoPageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class GeneralLoanInfoPage : public KGeneralLoanInfoPageDecl, public WizardPage -{ - Q_OBJECT -public: - GeneralLoanInfoPage(Wizard* parent); - KMyMoneyWizardPage* nextPage(void) const; - virtual bool isComplete(void) const; - void enterPage(void); - const MyMoneyAccount& parentAccount(void); - - QWidget* initialFocusWidget(void) const { - return m_loanDirection; - } - - /** - * Returns @p true if the user decided to record all payments, @p false otherwise. - */ - bool recordAllPayments(void) const; - -private slots: - void slotLoadWidgets(void); - -private: - bool m_firstTime; -}; - - -class KLoanDetailsPageDecl : public QWidget, public Ui::KLoanDetailsPageDecl -{ -public: - KLoanDetailsPageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class LoanDetailsPage : public KLoanDetailsPageDecl, public WizardPage -{ - Q_OBJECT -public: - LoanDetailsPage(Wizard* parent); - void enterPage(void); - KMyMoneyWizardPage* nextPage(void) const; - virtual bool isComplete(void) const; - - QWidget* initialFocusWidget(void) const { - return m_paymentDue; - } - - /** - * This method returns the number of payments depending on - * the settings of m_termAmount and m_termUnit widgets - */ - int term(void) const; - -private: - /** - * This method is used to update the term widgets - * according to the length of the given @a term. - * The term is also converted into a string and returned. - */ - QString updateTermWidgets(const double term); - -private: - bool m_needCalculate; - -private slots: - void slotValuesChanged(void); - void slotCalculate(void); -}; - - -class KLoanPaymentPageDecl : public QWidget, public Ui::KLoanPaymentPageDecl -{ -public: - KLoanPaymentPageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class LoanPaymentPage : public KLoanPaymentPageDecl, public WizardPage -{ - Q_OBJECT -public: - LoanPaymentPage(Wizard* parent); - ~LoanPaymentPage(); - - KMyMoneyWizardPage* nextPage(void) const; - - void enterPage(void); - - /** - * This method returns the sum of the additional fees - */ - MyMoneyMoney additionalFees(void) const; - - /** - * This method returns the base payment, that's principal and interest - */ - MyMoneyMoney basePayment(void) const; - - /** - * This method returns the splits that make up the additional fees in @p list. - * @note The splits may contain assigned ids which the caller must remove before - * adding the splits to a MyMoneyTransaction object. + class AccountTypePage; + class InstitutionPage; + class BrokeragePage; + class CreditCardSchedulePage; + class GeneralLoanInfoPage; + class LoanDetailsPage; + class LoanPaymentPage; + class LoanSchedulePage; + class LoanPayoutPage; + class HierarchyPage; + class AccountSummaryPage; + + class WizardPrivate : public KMyMoneyWizardPrivate + { + Q_DISABLE_COPY(WizardPrivate) + + public: + WizardPrivate(Wizard *qq): + KMyMoneyWizardPrivate(qq) + { + } + + ~WizardPrivate() + { + } + + /** + * This method returns the currently selected currency for the account */ - void additionalFeesSplits(QList& list); - -protected slots: - void slotAdditionalFees(void); - -protected: - void updateAmounts(void); - -private: - /// \internal d-pointer class. - class Private; - /// \internal d-pointer instance. - Private* const d; -}; - - -class KLoanSchedulePageDecl : public QWidget, public Ui::KLoanSchedulePageDecl -{ -public: - KLoanSchedulePageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class LoanSchedulePage : public KLoanSchedulePageDecl, public WizardPage -{ - Q_OBJECT -public: - LoanSchedulePage(Wizard* parent); - void enterPage(void); - - KMyMoneyWizardPage* nextPage(void) const; - - /** - * This method returns the due date of the first payment to be recorded. + const MyMoneySecurity& currency() const + { + return m_accountTypePage->currency(); + } + + /** + * This method returns the precision in digits for the selected currency. + * @sa currency() */ - QDate firstPaymentDueDate(void) const; - - QWidget* initialFocusWidget(void) const { - return m_interestCategory; - } - -private slots: - void slotLoadWidgets(void); - void slotCreateCategory(const QString& name, QString& id); -}; - - -class KLoanPayoutPageDecl : public QWidget, public Ui::KLoanPayoutPageDecl -{ -public: - KLoanPayoutPageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class LoanPayoutPage : public KLoanPayoutPageDecl, public WizardPage -{ - Q_OBJECT -public: - LoanPayoutPage(Wizard* parent); - void enterPage(void); - virtual bool isComplete(void) const; - - KMyMoneyWizardPage* nextPage(void) const; - - QWidget* initialFocusWidget(void) const { - return m_noPayoutTransaction; - } - - QString payoutAccountId(void) const; - -private slots: - void slotLoadWidgets(void); - void slotCreateAssetAccount(void); - void slotButtonsToggled(void); -}; - -class HierarchyFilterProxyModel : public AccountsProxyModel -{ - Q_OBJECT - -public: - HierarchyFilterProxyModel(QObject *parent = 0); - -protected: - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; - bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const; -}; - -class KHierarchyPageDecl : public QWidget, public Ui::KHierarchyPageDecl -{ -public: - KHierarchyPageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class HierarchyPage : public KHierarchyPageDecl, public WizardPage -{ - Q_OBJECT - -public: - HierarchyPage(Wizard* parent); - void enterPage(void); - KMyMoneyWizardPage* nextPage(void) const; - QWidget* initialFocusWidget(void) const { - return m_parentAccounts; - } - const MyMoneyAccount& parentAccount(void); - - bool isComplete(void) const; - -protected slots: - void parentAccountChanged(); - -private: - HierarchyFilterProxyModel *m_filterProxyModel; - MyMoneyAccount m_parentAccount; -}; - - -class KAccountSummaryPageDecl : public QWidget, public Ui::KAccountSummaryPageDecl -{ -public: - KAccountSummaryPageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class AccountSummaryPage : public KAccountSummaryPageDecl, public WizardPage -{ - Q_OBJECT -public: - AccountSummaryPage(Wizard* parent); - void enterPage(void); - QWidget* initialFocusWidget(void) const { - return m_dataList; - } -}; - + int precision() const + { + return MyMoneyMoney::denomToPrec(currency().smallestAccountFraction()); + } + + InstitutionPage* m_institutionPage; + AccountTypePage* m_accountTypePage; + BrokeragePage* m_brokeragepage; + CreditCardSchedulePage* m_schedulePage; + GeneralLoanInfoPage* m_generalLoanInfoPage; + LoanDetailsPage* m_loanDetailsPage; + LoanPaymentPage* m_loanPaymentPage; + LoanSchedulePage* m_loanSchedulePage; + LoanPayoutPage* m_loanPayoutPage; + HierarchyPage* m_hierarchyPage; + AccountSummaryPage* m_accountSummaryPage; + + MyMoneyAccountLoan m_account; + MyMoneySchedule m_schedule; + }; } // namespace #endif diff --git a/kmymoney/wizards/newinvestmentwizard/kinvestmentdetailswizardpage.cpp b/kmymoney/wizards/newinvestmentwizard/kinvestmentdetailswizardpage.cpp index e29cf2f74..82ab0bba0 100644 --- a/kmymoney/wizards/newinvestmentwizard/kinvestmentdetailswizardpage.cpp +++ b/kmymoney/wizards/newinvestmentwizard/kinvestmentdetailswizardpage.cpp @@ -1,151 +1,151 @@ /*************************************************************************** kinvestmentdetailswizardpage - description ------------------- begin : Sun Jun 27 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kinvestmentdetailswizardpage.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_kinvestmentdetailswizardpage.h" #include "mymoneymoney.h" #include "mymoneyfile.h" #include "mymoneysecurity.h" KInvestmentDetailsWizardPage::KInvestmentDetailsWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::KInvestmentDetailsWizardPage) { ui->setupUi(this); ui->m_fraction->setPrecision(0); ui->m_fraction->setValue(MyMoneyMoney(100, 1)); KMyMoneyMoneyValidator* fractionValidator = new KMyMoneyMoneyValidator(1, 100000, 0, this); ui->m_fraction->setValidator(fractionValidator); // load the price mode combo ui->m_priceMode->insertItem(i18nc("default price mode", "(default)"), 0); ui->m_priceMode->insertItem(i18n("Price per share"), 1); ui->m_priceMode->insertItem(i18n("Total for all shares"), 2); // load the widget with the available currencies ui->m_tradingCurrencyEdit->update(QString()); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("investmentName", ui->m_investmentName); connect(ui->m_investmentName, &QLineEdit::textChanged, this, &QWizardPage::completeChanged); registerField("investmentIdentification", ui->m_investmentIdentification); connect(ui->m_investmentIdentification, &QLineEdit::textChanged, this, &QWizardPage::completeChanged); registerField("investmentSymbol", ui->m_investmentSymbol); connect(ui->m_investmentSymbol, &QLineEdit::textChanged, this, &QWizardPage::completeChanged); registerField("tradingCurrencyEdit", ui->m_tradingCurrencyEdit, "security"); registerField("tradingMarket", ui->m_tradingMarket, "currentText", SIGNAL(currentIndexChanged(QString))); ui->m_roundingMethod->addItem(i18nc("Rounding method", "Round"), AlkValue::RoundRound); ui->m_roundingMethod->addItem(i18nc("Rounding method", "Ceil"), AlkValue::RoundCeil); ui->m_roundingMethod->addItem(i18nc("Rounding method", "Floor"), AlkValue::RoundFloor); ui->m_roundingMethod->addItem(i18nc("Rounding method", "Truncate"), AlkValue::RoundTruncate); registerField("roundingMethod", ui->m_roundingMethod, "currentData", SIGNAL(currentIndexChanged(int))); registerField("fraction", ui->m_fraction, "value", SIGNAL(textChanged())); connect(ui->m_fraction, &KMyMoneyEdit::textChanged, this, &QWizardPage::completeChanged); registerField("pricePrecision", ui->m_pricePrecision, "value", SIGNAL(valueChanged())); } KInvestmentDetailsWizardPage::~KInvestmentDetailsWizardPage() { delete ui; } /** * Set the values based on the @param security */ void KInvestmentDetailsWizardPage::init2(const MyMoneySecurity& security) { MyMoneySecurity tradingCurrency = MyMoneyFile::instance()->currency(security.tradingCurrency()); ui->m_investmentSymbol->setText(security.tradingSymbol()); ui->m_tradingMarket->setCurrentIndex(ui->m_tradingMarket->findText(security.tradingMarket(), Qt::MatchExactly)); if (security.roundingMethod() == AlkValue::RoundNever) ui->m_roundingMethod->setCurrentIndex(0); else ui->m_roundingMethod->setCurrentIndex(ui->m_roundingMethod->findData(security.roundingMethod())); ui->m_fraction->setValue(MyMoneyMoney(security.smallestAccountFraction(), 1)); ui->m_pricePrecision->setValue(security.pricePrecision()); ui->m_tradingCurrencyEdit->setSecurity(tradingCurrency); ui->m_investmentIdentification->setText(security.value("kmm-security-id")); } /** * Update the "Next" button */ bool KInvestmentDetailsWizardPage::isComplete() const { return (!ui->m_investmentName->text().isEmpty() && !ui->m_investmentSymbol->text().isEmpty() && !ui->m_fraction->value().isZero()); } int KInvestmentDetailsWizardPage::priceMode() const { return ui->m_priceMode->currentItem(); } void KInvestmentDetailsWizardPage::setCurrentPriceMode(int mode) { ui->m_priceMode->setCurrentItem(mode); } void KInvestmentDetailsWizardPage::loadName(const QString& name) { ui->m_investmentName->loadText(name); } void KInvestmentDetailsWizardPage::setName(const QString& name) { ui->m_investmentName->setText(name); } void KInvestmentDetailsWizardPage::setPriceModeEnabled(bool enabled) { ui->m_priceMode->setEnabled(enabled); } void KInvestmentDetailsWizardPage::setupInvestmentSymbol() { ui->m_investmentSymbol->setFocus(); - connect(ui->m_investmentSymbol, SIGNAL(lineChanged(QString)), this, SIGNAL(checkForExistingSymbol(QString))); + connect(ui->m_investmentSymbol, &KMyMoneyLineEdit::lineChanged, this, &KInvestmentDetailsWizardPage::checkForExistingSymbol); } diff --git a/kmymoney/wizards/newinvestmentwizard/knewinvestmentwizard.cpp b/kmymoney/wizards/newinvestmentwizard/knewinvestmentwizard.cpp index 6e4b0c7a1..b9909ddd3 100644 --- a/kmymoney/wizards/newinvestmentwizard/knewinvestmentwizard.cpp +++ b/kmymoney/wizards/newinvestmentwizard/knewinvestmentwizard.cpp @@ -1,287 +1,285 @@ /*************************************************************************** knewinvestmentwizard - description ------------------- begin : Sat Dec 4 2004 copyright : (C) 2004 by Thomas Baumgart email : kmymoney-devel@kde.org (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "knewinvestmentwizard.h" // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes #include #include #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_knewinvestmentwizard.h" #include "mymoneyaccount.h" #include "mymoneysecurity.h" #include "mymoneyfile.h" #include "webpricequote.h" #include "kmymoneyutils.h" -namespace Ui { class KNewInvestmentWizard; } - class KNewInvestmentWizardPrivate { Q_DISABLE_COPY(KNewInvestmentWizardPrivate) Q_DECLARE_PUBLIC(KNewInvestmentWizard) public: KNewInvestmentWizardPrivate(KNewInvestmentWizard *qq) : q_ptr(qq), ui(new Ui::KNewInvestmentWizard) { } ~KNewInvestmentWizardPrivate() { delete ui; } void init1() { Q_Q(KNewInvestmentWizard); ui->m_onlineUpdatePage->slotSourceChanged(false); // make sure, the back button does not clear fields q->setOption(QWizard::IndependentPages, true); // enable the help button q->setOption(q->HaveHelpButton, true); q->connect(q, &KNewInvestmentWizard::helpRequested, q, &KNewInvestmentWizard::slotHelp); m_createAccount = true; // Update label in case of edit if (!m_account.id().isEmpty()) { ui->m_investmentTypePage->setIntroLabelText(i18n("This wizard allows you to modify the selected investment.")); } if (!m_security.id().isEmpty()) { ui->m_investmentTypePage->setIntroLabelText(i18n("This wizard allows you to modify the selected security.")); } KMyMoneyUtils::updateWizardButtons(q); } void init2() { ui->m_investmentTypePage->init2(m_security); ui->m_investmentDetailsPage->init2(m_security); ui->m_onlineUpdatePage->init2(m_security); ui->m_onlineUpdatePage->slotCheckPage(m_security.value("kmm-online-source")); } KNewInvestmentWizard *q_ptr; Ui::KNewInvestmentWizard *ui; MyMoneyAccount m_account; MyMoneySecurity m_security; bool m_createAccount; }; KNewInvestmentWizard::KNewInvestmentWizard(QWidget *parent) : QWizard(parent), d_ptr(new KNewInvestmentWizardPrivate(this)) { Q_D(KNewInvestmentWizard); d->ui->setupUi(this); d->init1(); d->ui->m_onlineUpdatePage->slotCheckPage(QString()); d->ui->m_investmentDetailsPage->setupInvestmentSymbol(); connect(d->ui->m_investmentDetailsPage, &KInvestmentDetailsWizardPage::checkForExistingSymbol, this, &KNewInvestmentWizard::slotCheckForExistingSymbol); } KNewInvestmentWizard::KNewInvestmentWizard(const MyMoneyAccount& acc, QWidget *parent) : QWizard(parent), d_ptr(new KNewInvestmentWizardPrivate(this)) { Q_D(KNewInvestmentWizard); d->ui->setupUi(this); d->m_account = acc; setWindowTitle(i18n("Investment detail wizard")); d->init1(); // load the widgets with the data setName(d->m_account.name()); d->m_security = MyMoneyFile::instance()->security(d->m_account.currencyId()); d->init2(); int priceMode = 0; if (!d->m_account.value("priceMode").isEmpty()) priceMode = d->m_account.value("priceMode").toInt(); d->ui->m_investmentDetailsPage->setCurrentPriceMode(priceMode); } KNewInvestmentWizard::KNewInvestmentWizard(const MyMoneySecurity& security, QWidget *parent) : QWizard(parent), d_ptr(new KNewInvestmentWizardPrivate(this)) { Q_D(KNewInvestmentWizard); d->ui->setupUi(this); d->m_security = security; setWindowTitle(i18n("Security detail wizard")); d->init1(); d->m_createAccount = false; // load the widgets with the data setName(security.name()); d->init2(); // no chance to change the price mode here d->ui->m_investmentDetailsPage->setCurrentPriceMode(0); d->ui->m_investmentDetailsPage->setPriceModeEnabled(false); } KNewInvestmentWizard::~KNewInvestmentWizard() { } void KNewInvestmentWizard::setName(const QString& name) { Q_D(KNewInvestmentWizard); d->ui->m_investmentDetailsPage->setName(name); } void KNewInvestmentWizard::slotCheckForExistingSymbol(const QString& symbol) { Q_D(KNewInvestmentWizard); Q_UNUSED(symbol); if (field("investmentName").toString().isEmpty()) { QList list = MyMoneyFile::instance()->securityList(); auto type = static_cast(field("securityType").toInt()); foreach (const MyMoneySecurity& it_s, list) { if (it_s.securityType() == type && it_s.tradingSymbol() == field("investmentSymbol").toString()) { d->m_security = MyMoneySecurity(); if (KMessageBox::questionYesNo(this, i18n("The selected symbol is already on file. Do you want to reuse the existing security?"), i18n("Security found")) == KMessageBox::Yes) { d->m_security = it_s; d->init2(); d->ui->m_investmentDetailsPage->loadName(d->m_security.name()); } break; } } } } void KNewInvestmentWizard::slotHelp() { KHelpClient::invokeHelp("details.investments.newinvestmentwizard"); } void KNewInvestmentWizard::createObjects(const QString& parentId) { Q_D(KNewInvestmentWizard); auto file = MyMoneyFile::instance(); auto type = static_cast(field("securityType").toInt()); auto roundingMethod = static_cast(field("roundingMethod").toInt()); MyMoneyFileTransaction ft; try { // update all relevant attributes only, if we create a stock // account and the security is unknown or we modifiy the security MyMoneySecurity newSecurity(d->m_security); newSecurity.setName(field("investmentName").toString()); newSecurity.setTradingSymbol(field("investmentSymbol").toString()); newSecurity.setTradingMarket(field("tradingMarket").toString()); newSecurity.setSmallestAccountFraction(field("fraction").value().formatMoney("", 0, false).toUInt()); newSecurity.setPricePrecision(MyMoneyMoney(field("pricePrecision").toUInt()).formatMoney("", 0, false).toUInt()); newSecurity.setTradingCurrency(field("tradingCurrencyEdit").value().id()); newSecurity.setSecurityType(type); newSecurity.setRoundingMethod(roundingMethod); newSecurity.deletePair("kmm-online-source"); newSecurity.deletePair("kmm-online-quote-system"); newSecurity.deletePair("kmm-online-factor"); newSecurity.deletePair("kmm-security-id"); if (!field("onlineSourceCombo").toString().isEmpty()) { if (field("useFinanceQuote").toBool()) { FinanceQuoteProcess p; newSecurity.setValue("kmm-online-quote-system", "Finance::Quote"); newSecurity.setValue("kmm-online-source", p.crypticName(field("onlineSourceCombo").toString())); } else { newSecurity.setValue("kmm-online-source", field("onlineSourceCombo").toString()); } } if (d->ui->m_onlineUpdatePage->isOnlineFactorEnabled() && (field("onlineFactor").value() != MyMoneyMoney::ONE)) newSecurity.setValue("kmm-online-factor", field("onlineFactor").value().toString()); if (!field("investmentIdentification").toString().isEmpty()) newSecurity.setValue("kmm-security-id", field("investmentIdentification").toString()); if (d->m_security.id().isEmpty() || newSecurity != d->m_security) { d->m_security = newSecurity; // add or update it if (d->m_security.id().isEmpty()) { file->addSecurity(d->m_security); } else { file->modifySecurity(d->m_security); } } if (d->m_createAccount) { // now that the security exists, we can add the account to store it d->m_account.setName(field("investmentName").toString()); if (d->m_account.accountType() == eMyMoney::Account::Unknown) d->m_account.setAccountType(eMyMoney::Account::Stock); d->m_account.setCurrencyId(d->m_security.id()); switch (d->ui->m_investmentDetailsPage->priceMode()) { case 0: d->m_account.deletePair("priceMode"); break; case 1: case 2: d->m_account.setValue("priceMode", QString("%1").arg(d->ui->m_investmentDetailsPage->priceMode())); break; } // update account's fraction in case its security fraction has changed // otherwise KMM restart is required because this won't happen automatically d->m_account.fraction(d->m_security); if (d->m_account.id().isEmpty()) { MyMoneyAccount parent = file->account(parentId); file->addAccount(d->m_account, parent); } else file->modifyAccount(d->m_account); } ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::detailedSorry(0, i18n("Unable to create all objects for the investment"), QString("%1 caugt in %2:%3").arg(e.what()).arg(e.file()).arg(e.line())); } } MyMoneyAccount KNewInvestmentWizard::account() const { Q_D(const KNewInvestmentWizard); return d->m_account; } diff --git a/kmymoney/wizards/newinvestmentwizard/knewinvestmentwizard.h b/kmymoney/wizards/newinvestmentwizard/knewinvestmentwizard.h index 2bd1246b1..7451e2277 100644 --- a/kmymoney/wizards/newinvestmentwizard/knewinvestmentwizard.h +++ b/kmymoney/wizards/newinvestmentwizard/knewinvestmentwizard.h @@ -1,90 +1,90 @@ /*************************************************************************** knewinvestmentwizard - description ------------------- begin : Sat Dec 4 2004 copyright : (C) 2004 by Thomas Baumgart email : Thomas Baumgart (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KNEWINVESTMENTWIZARD_H #define KNEWINVESTMENTWIZARD_H // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes class MyMoneyAccount; class MyMoneySecurity; /** * This class contains the implementation of the new investment wizard. * * @author Thomas Baumgart */ class KNewInvestmentWizardPrivate; class KNewInvestmentWizard : public QWizard { Q_OBJECT public: /** * Use this constructor for the creation of a new investment */ - explicit KNewInvestmentWizard(QWidget *parent = 0); + explicit KNewInvestmentWizard(QWidget *parent = nullptr); /** * Use this constructor for the modification of an existing investment */ - explicit KNewInvestmentWizard(const MyMoneyAccount& acc, QWidget *parent = 0); + explicit KNewInvestmentWizard(const MyMoneyAccount& acc, QWidget *parent = nullptr); /** * Use this constructor for the modification of an existing security */ - explicit KNewInvestmentWizard(const MyMoneySecurity& sec, QWidget *parent = 0); + explicit KNewInvestmentWizard(const MyMoneySecurity& sec, QWidget *parent = nullptr); ~KNewInvestmentWizard(); /** * This method sets the name in the name widget. */ void setName(const QString& name); /** * Depending on the constructor used, this method either * creates all necessary objects for the investment or updates * them. * * @param parentId id of parent account for the investment */ void createObjects(const QString& parentId); MyMoneyAccount account() const; protected slots: void slotCheckForExistingSymbol(const QString&); void slotHelp(); private: Q_DISABLE_COPY(KNewInvestmentWizard) Q_DECLARE_PRIVATE(KNewInvestmentWizard) const QScopedPointer d_ptr; }; #endif diff --git a/kmymoney/wizards/newloanwizard/additionalfeeswizardpage.cpp b/kmymoney/wizards/newloanwizard/additionalfeeswizardpage.cpp index 023a482e7..eb99a7693 100644 --- a/kmymoney/wizards/newloanwizard/additionalfeeswizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/additionalfeeswizardpage.cpp @@ -1,98 +1,98 @@ /*************************************************************************** konlineupdatewizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "additionalfeeswizardpage.h" // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes #include #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_additionalfeeswizardpage.h" #include "knewloanwizard.h" #include "knewloanwizard_p.h" #include "ksplittransactiondlg.h" #include "mymoneyfile.h" #include "mymoneyaccount.h" #include "mymoneymoney.h" AdditionalFeesWizardPage::AdditionalFeesWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::AdditionalFeesWizardPage) { ui->setupUi(this); registerField("additionalCost", ui->m_additionalCost, "text"); registerField("periodicPayment", ui->m_periodicPayment, "text"); registerField("basePayment", ui->m_basePayment, "text"); // load button icons KGuiItem additionalFeeButtonItem(i18n("&Additional fees..."), 0, //QIcon::fromTheme("document-new"), i18n("Enter additional fees"), i18n("Use this to add any additional fees other than principal and interest contained in your periodical payments.")); KGuiItem::assign(ui->m_additionalFeeButton, additionalFeeButtonItem); - connect(ui->m_additionalFeeButton, SIGNAL(clicked()), this, SLOT(slotAdditionalFees())); + connect(ui->m_additionalFeeButton, &QAbstractButton::clicked, this, &AdditionalFeesWizardPage::slotAdditionalFees); } AdditionalFeesWizardPage::~AdditionalFeesWizardPage() { delete ui; } void AdditionalFeesWizardPage::slotAdditionalFees() { // KMessageBox::information(0, QString("Not yet implemented ... if you want to help, contact kmymoney-devel@kde.org"), QString("Development notice")); MyMoneyAccount account("Phony-ID", MyMoneyAccount()); QMap priceInfo; QPointer dlg = new KSplitTransactionDlg(qobject_cast(wizard())->d_func()->m_transaction, qobject_cast(wizard())->d_func()->m_split, account, false, !field("borrowButton").toBool(), MyMoneyMoney(), priceInfo); connect(dlg, SIGNAL(newCategory(MyMoneyAccount&)), this, SIGNAL(newCategory(MyMoneyAccount&))); if (dlg->exec() == QDialog::Accepted) { qobject_cast(wizard())->d_func()->m_transaction = dlg->transaction(); // sum up the additional fees MyMoneyMoney fees; foreach (const MyMoneySplit& it, qobject_cast(wizard())->d_func()->m_transaction.splits()) { if (it.accountId() != account.id()) { fees += it.value(); } } setField("additionalCost", fees.formatMoney(qobject_cast(wizard())->d_func()->m_account.fraction(MyMoneyFile::instance()->security(qobject_cast(wizard())->d_func()->m_account.currencyId())))); } delete dlg; updatePeriodicPayment(qobject_cast(wizard())->d_func()->m_account); } void AdditionalFeesWizardPage::updatePeriodicPayment(const MyMoneyAccount& account) { MyMoneyMoney base(ui->m_basePayment->text()); MyMoneyMoney add(ui->m_additionalCost->text()); ui->m_periodicPayment->setText((base + add).formatMoney(account.fraction(MyMoneyFile::instance()->security(account.currencyId())))); } diff --git a/kmymoney/wizards/newloanwizard/assetaccountwizardpage.cpp b/kmymoney/wizards/newloanwizard/assetaccountwizardpage.cpp index 43447a4e2..f18933c2c 100644 --- a/kmymoney/wizards/newloanwizard/assetaccountwizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/assetaccountwizardpage.cpp @@ -1,92 +1,92 @@ /*************************************************************************** assetaccountwizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "assetaccountwizardpage.h" // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes #include "ui_assetaccountwizardpage.h" #include #include // ---------------------------------------------------------------------------- // Project Includes #include "kmymoney.h" #include "icons/icons.h" using namespace Icons; AssetAccountWizardPage::AssetAccountWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::AssetAccountWizardPage) { ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("dontCreatePayoutCheckBox", ui->m_dontCreatePayoutCheckBox); registerField("paymentDate", ui->m_paymentDate, "date"); registerField("assetAccountEdit", ui->m_assetAccountEdit, "selectedItems"); - connect(ui->m_assetAccountEdit, SIGNAL(stateChanged()), this, SIGNAL(completeChanged())); - connect(ui->m_dontCreatePayoutCheckBox, SIGNAL(clicked()), this, SIGNAL(completeChanged())); + connect(ui->m_assetAccountEdit, &KMyMoneySelector::stateChanged, this, &QWizardPage::completeChanged); + connect(ui->m_dontCreatePayoutCheckBox, &QAbstractButton::clicked, this, &QWizardPage::completeChanged); // load button icons KGuiItem createAssetButtonItem(i18n("&Create..."), QIcon::fromTheme(g_Icons[Icon::DocumentNew]), i18n("Create a new asset account"), i18n("Use this to create a new account to which the initial payment should be made")); KGuiItem::assign(ui->m_createNewAssetButton, createAssetButtonItem); - connect(ui->m_createNewAssetButton, SIGNAL(clicked()), kmymoney, SLOT(slotAccountNew())); + connect(ui->m_createNewAssetButton, &QAbstractButton::clicked, kmymoney, static_cast(&KMyMoneyApp::slotAccountNew)); ui->m_assetAccountEdit->removeButtons(); ui->m_dontCreatePayoutCheckBox->setChecked(false); } AssetAccountWizardPage::~AssetAccountWizardPage() { delete ui; } /** * Update the "Next" button */ bool AssetAccountWizardPage::isComplete() const { if (ui->m_dontCreatePayoutCheckBox->isChecked()) { ui->m_assetAccountEdit->setEnabled(false); ui->m_paymentDate->setEnabled(false); ui->m_createNewAssetButton->setEnabled(false); return true; } else { ui->m_assetAccountEdit->setEnabled(true); ui->m_paymentDate->setEnabled(true); ui->m_createNewAssetButton->setEnabled(true); if (!ui->m_assetAccountEdit->selectedItems().isEmpty() && ui->m_paymentDate->date().isValid()) return true; } return false; } diff --git a/kmymoney/wizards/newloanwizard/effectivedatewizardpage.cpp b/kmymoney/wizards/newloanwizard/effectivedatewizardpage.cpp index 92b0b0210..3a4cf6de4 100644 --- a/kmymoney/wizards/newloanwizard/effectivedatewizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/effectivedatewizardpage.cpp @@ -1,69 +1,69 @@ /*************************************************************************** effectivedatewizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "effectivedatewizardpage.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_effectivedatewizardpage.h" #include "knewloanwizard.h" #include "mymoneyaccountloan.h" EffectiveDateWizardPage::EffectiveDateWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::EffectiveDateWizardPage) { ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("effectiveChangeDateEdit", ui->m_effectiveChangeDateEdit, "date", SIGNAL(dateChanged(QDate))); - connect(ui->m_effectiveChangeDateEdit, SIGNAL(dateChanged(QDate)), this, SIGNAL(completeChanged())); + connect(ui->m_effectiveChangeDateEdit, &KMyMoneyDateInput::dateChanged, this, &QWizardPage::completeChanged); } EffectiveDateWizardPage::~EffectiveDateWizardPage() { delete ui; } void EffectiveDateWizardPage::initializePage() { ui->m_effectiveDateLabel->setText(QString("\n") + i18n( "Please enter the date from which on the following changes will be effective. " "The date entered must be later than the opening date of this account (%1), but must " "not be in the future. The default will be today.", QLocale().toString(qobject_cast(wizard())->account().openingDate()))); } /** * Update the "Next" button */ bool EffectiveDateWizardPage::isComplete() const { return !(ui->m_effectiveChangeDateEdit->date() < qobject_cast(wizard())->account().openingDate() || ui->m_effectiveChangeDateEdit->date() > QDate::currentDate()); return true; } diff --git a/kmymoney/wizards/newloanwizard/firstpaymentwizardpage.cpp b/kmymoney/wizards/newloanwizard/firstpaymentwizardpage.cpp index 4e8221a58..2a14125dc 100644 --- a/kmymoney/wizards/newloanwizard/firstpaymentwizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/firstpaymentwizardpage.cpp @@ -1,77 +1,77 @@ /*************************************************************************** firstpaymentwizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "firstpaymentwizardpage.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_firstpaymentwizardpage.h" FirstPaymentWizardPage::FirstPaymentWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::FirstPaymentWizardPage) { ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("firstDueDateEdit", ui->m_firstDueDateEdit, "date"); - connect(ui->m_firstDueDateEdit, SIGNAL(dateChanged(QDate)), this, SIGNAL(completeChanged())); + connect(ui->m_firstDueDateEdit, &KMyMoneyDateInput::dateChanged, this, &QWizardPage::completeChanged); } FirstPaymentWizardPage::~FirstPaymentWizardPage() { delete ui; } /** * Update the "Next" button */ bool FirstPaymentWizardPage::isComplete() const { return ui->m_firstDueDateEdit->date().isValid(); } void FirstPaymentWizardPage::initializePage() { if (field("allPaymentsButton").toBool()) { ui->m_firstPaymentLabel->setText( QString("\n") + i18n("Please enter the date, the first payment for this loan was/is due.")); ui->m_firstPaymentNote->setText( i18n("Note: Consult the loan contract for details of the first due date. " "Keep in mind, that the first due date usually differs from the date " "the contract was signed")); } else if (field("thisYearPaymentButton").toBool()) { ui->m_firstPaymentLabel->setText( QString("\n") + i18n("Please enter the date, the first payment for this loan was/is due this year.")); ui->m_firstPaymentNote->setText( i18n("Note: You can easily figure out the date of the first payment " "if you consult the last statement of last year.")); } } diff --git a/kmymoney/wizards/newloanwizard/interestcategorywizardpage.cpp b/kmymoney/wizards/newloanwizard/interestcategorywizardpage.cpp index 122fe6f18..e3b9ea5c2 100644 --- a/kmymoney/wizards/newloanwizard/interestcategorywizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/interestcategorywizardpage.cpp @@ -1,113 +1,113 @@ /*************************************************************************** interestcategorywizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "interestcategorywizardpage.h" // ---------------------------------------------------------------------------- // QT Includes #include #include // ---------------------------------------------------------------------------- // KDE Includes #include #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_interestcategorywizardpage.h" #include "knewaccountdlg.h" #include "mymoneyfile.h" #include "mymoneyaccount.h" #include "icons/icons.h" #include "mymoneyexception.h" using namespace Icons; InterestCategoryWizardPage::InterestCategoryWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::InterestCategoryWizardPage) { ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("interestAccountEdit", ui->m_interestAccountEdit, "selectedItems"); - connect(ui->m_interestAccountEdit, SIGNAL(stateChanged()), this, SIGNAL(completeChanged())); + connect(ui->m_interestAccountEdit, &KMyMoneySelector::stateChanged, this, &QWizardPage::completeChanged); ui->m_interestAccountEdit->removeButtons(); // load button icons KGuiItem createCategoryButtonItem(i18n("&Create..."), QIcon::fromTheme(g_Icons[Icon::DocumentNew]), i18n("Create a new category"), i18n("Use this to open the new account editor")); KGuiItem::assign(ui->m_createCategoryButton, createCategoryButtonItem); - connect(ui->m_createCategoryButton, SIGNAL(clicked()), this, SLOT(slotCreateCategory())); + connect(ui->m_createCategoryButton, &QAbstractButton::clicked, this, &InterestCategoryWizardPage::slotCreateCategory); } InterestCategoryWizardPage::~InterestCategoryWizardPage() { delete ui; } /** * Update the "Next" button */ bool InterestCategoryWizardPage::isComplete() const { return ui->m_interestAccountEdit->selectedItems().count() > 0; } void InterestCategoryWizardPage::slotCreateCategory() { MyMoneyAccount acc, base; MyMoneyFile* file = MyMoneyFile::instance(); if (field("borrowButton").toBool()) { base = file->expense(); acc.setAccountType(eMyMoney::Account::Expense); } else { base = file->income(); acc.setAccountType(eMyMoney::Account::Income); } acc.setParentAccountId(base.id()); QPointer dlg = new KNewAccountDlg(acc, true, true, nullptr, QString()); if (dlg->exec() == QDialog::Accepted) { acc = dlg->account(); MyMoneyFileTransaction ft; try { QString id; id = file->createCategory(base, acc.name()); if (id.isEmpty()) throw MYMONEYEXCEPTION("failure while creating the account hierarchy"); ft.commit(); ui->m_interestAccountEdit->setSelected(id); } catch (const MyMoneyException &e) { KMessageBox::information(this, i18n("Unable to add account: %1", e.what())); } } delete dlg; } diff --git a/kmymoney/wizards/newloanwizard/interesteditwizardpage.cpp b/kmymoney/wizards/newloanwizard/interesteditwizardpage.cpp index e048c39c3..45fe54a58 100644 --- a/kmymoney/wizards/newloanwizard/interesteditwizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/interesteditwizardpage.cpp @@ -1,58 +1,58 @@ /*************************************************************************** interesteditwizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "interesteditwizardpage.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes #include "ui_interesteditwizardpage.h" InterestEditWizardPage::InterestEditWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::InterestEditWizardPage) { ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("newInterestRateEdit", ui->m_newInterestRateEdit, "value", SIGNAL(textChanged(QString))); - connect(ui->m_newInterestRateEdit, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged())); + connect(ui->m_newInterestRateEdit, &KMyMoneyEdit::textChanged, this, &QWizardPage::completeChanged); } InterestEditWizardPage::~InterestEditWizardPage() { delete ui; } /** * Update the "Next" button */ bool InterestEditWizardPage::isComplete() const { //FIXME: this only exists in the EditLoanWizard subclass return field("newPaymentEditValid").toBool() || ui->m_newInterestRateEdit->isValid(); } diff --git a/kmymoney/wizards/newloanwizard/knewloanwizard.cpp b/kmymoney/wizards/newloanwizard/knewloanwizard.cpp index b491205b8..4626a4b5d 100644 --- a/kmymoney/wizards/newloanwizard/knewloanwizard.cpp +++ b/kmymoney/wizards/newloanwizard/knewloanwizard.cpp @@ -1,237 +1,234 @@ /*************************************************************************** knewloanwizard.cpp - description ------------------- begin : Wed Oct 8 2003 copyright : (C) 2000-2003 by Michael Edwardes email : mte@users.sourceforge.net Javier Campos Morales Felix Rodriguez John C Thomas Baumgart Kevin Tambascio ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "knewloanwizard.h" #include "knewloanwizard_p.h" // ---------------------------------------------------------------------------- // QT Includes #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -#include "kmymoneydateinput.h" -#include "kmymoneyedit.h" #include "kmymoneyaccountselector.h" - #include "mymoneypayee.h" KNewLoanWizard::KNewLoanWizard(QWidget *parent) : QWizard(parent), d_ptr(new KNewLoanWizardPrivate(this)) { Q_D(KNewLoanWizard); d->init(); } KNewLoanWizard::KNewLoanWizard(KNewLoanWizardPrivate &dd, QWidget *parent) : QWizard(parent), d_ptr(&dd) { Q_D(KNewLoanWizard); d->init(); } KNewLoanWizard::~KNewLoanWizard() { } const MyMoneyAccountLoan KNewLoanWizard::account() const { Q_D(const KNewLoanWizard); return d->m_account; } int KNewLoanWizard::nextId() const { Q_D(const KNewLoanWizard); // Starting from the current page, look for the first enabled page // and return that value // If the end of the list is encountered first, then return -1. for (int i = currentId() + 1; i < d->m_pages.size() && i < pageIds().size(); ++i) { if (d->m_pages.testBit(i)) return pageIds()[i]; } return -1; } bool KNewLoanWizard::validateCurrentPage() { Q_D(KNewLoanWizard); auto dontLeavePage = false; KLocalizedString ks = ki18n( "The loan wizard is unable to calculate two different values for your loan " "at the same time. " "Please enter a value for the %1 on this page or backup to the page where the " "current value to be calculated is defined and fill in a value."); if (currentPage() == d->ui->m_lendBorrowPage) { // load the appropriate categories into the list d->loadAccountList(); } else if (currentPage() == d->ui->m_interestTypePage) { if (field("fixedInterestButton").toBool()) { d->m_pages.setBit(Page_PreviousPayments); if (field("previousPaymentButton").toBool()) d->m_pages.setBit(Page_RecordPayment); else d->m_pages.clearBit(Page_RecordPayment); d->m_pages.clearBit(Page_VariableInterestDate); } else { d->m_pages.clearBit(Page_PreviousPayments); d->m_pages.clearBit(Page_RecordPayment); d->m_pages.setBit(Page_VariableInterestDate); } } else if (currentPage() == d->ui->m_previousPaymentsPage) { if (field("previousPaymentButton").toBool()) { d->m_pages.setBit(Page_RecordPayment); } else if (field("noPreviousPaymentButton").toBool()) { d->m_pages.clearBit(Page_RecordPayment); } } else if (currentPage() == d->ui->m_loanAmountPage) { if (field("thisYearPaymentButton").toBool() && !field("loanAmountEditValid").toBool()) { dontLeavePage = true; KMessageBox::error(0, i18n("You selected, that payments have already been made towards this loan. " "This requires you to enter the loan amount exactly as found on your " "last statement."), i18n("Calculation error")); } else d->updateLoanAmount(); } else if (currentPage() == d->ui->m_interestPage) { if (!field("loanAmountEditValid").toBool() && !field("interestRateEditValid").toBool()) { dontLeavePage = true; KMessageBox::error(0, ks.subs(i18n("interest rate")).toString(), i18n("Calculation error")); } else d->updateInterestRate(); } else if (currentPage() == d->ui->m_durationPage) { if ((!field("loanAmountEditValid").toBool() || !field("interestRateEditValid").toBool()) && field("durationValueEdit").toInt() == 0) { dontLeavePage = true; KMessageBox::error(0, ks.subs(i18n("term")).toString(), i18n("Calculation error")); } else d->updateDuration(); } else if (currentPage() == d->ui->m_paymentPage) { if ((!field("loanAmountEditValid").toBool() || !field("interestRateEditValid").toBool() || field("durationValueEdit").toInt() == 0) && !field("paymentEditValid").toBool()) { dontLeavePage = true; KMessageBox::error(0, ks.subs(i18n("principal and interest")).toString(), i18n("Calculation error")); } else d->updatePayment(); } else if (currentPage() == d->ui->m_finalPaymentPage) { if ((!field("loanAmountEditValid").toBool() || !field("interestRateEditValid").toBool() || field("durationValueEdit").toInt() == 0 || !field("paymentEditValid").toBool()) && !field("finalPaymentEditValid").toBool()) { // if two fields are empty and one of them is the final payment // we assume the final payment to be 0 instead of presenting a dialog setField("finalPaymentEdit", QVariant::fromValue((MyMoneyMoney()))); } d->updateFinalPayment(); if (!d->calculateLoan()) { dontLeavePage = true; } else d->updateLoanInfo(); } else if (currentPage() == d->ui->m_schedulePage) { if (field("allPaymentsButton").toBool() || field("noPreviousPaymentButton").toBool()) { if (d->ui->m_assetAccountPage) d->m_pages.setBit(Page_AssetAccount); } else { if (d->ui->m_assetAccountPage) d->m_pages.clearBit(Page_AssetAccount); d->ui->m_assetAccountPage->ui->m_assetAccountEdit->slotDeselectAllAccounts(); } } if (!dontLeavePage) return true; else return false; } MyMoneySchedule KNewLoanWizard::schedule() const { MyMoneySchedule sched(field("nameEdit").toString(), eMyMoney::Schedule::Type::LoanPayment, eMyMoney::Schedule::Occurrence(field("paymentFrequencyUnitEdit").toInt()), 1, eMyMoney::Schedule::PaymentType::Other, QDate(), QDate(), false, false); Q_D(const KNewLoanWizard); MyMoneyTransaction t = d->transaction(); t.setPostDate(field("nextDueDateEdit").toDate()); sched.setTransaction(t); return sched; } void KNewLoanWizard::slotReloadEditWidgets() { Q_D(KNewLoanWizard); // load the various account widgets d->loadAccountList(); // reload payee widget auto payeeId = field("payeeEdit").toString(); //FIXME: port d->ui->m_namePage->ui->m_payeeEdit->loadPayees(MyMoneyFile::instance()->payeeList()); if (!payeeId.isEmpty()) { setField("payeeEdit", payeeId); } } QString KNewLoanWizard::initialPaymentAccount() const { if (field("dontCreatePayoutCheckBox").toBool()) { return QString(); } return field("assetAccountEdit").toStringList().first(); } QDate KNewLoanWizard::initialPaymentDate() const { if (field("dontCreatePayoutCheckBox").toBool()) { return QDate(); } return field("paymentDate").toDate(); } diff --git a/kmymoney/wizards/newloanwizard/loanamountwizardpage.cpp b/kmymoney/wizards/newloanwizard/loanamountwizardpage.cpp index 7eacaaf39..adaf528e5 100644 --- a/kmymoney/wizards/newloanwizard/loanamountwizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/loanamountwizardpage.cpp @@ -1,90 +1,90 @@ /*************************************************************************** loanamountwizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "loanamountwizardpage.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_loanamountwizardpage.h" LoanAmountWizardPage::LoanAmountWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::LoanAmountWizardPage) { ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("loanAmountEdit", ui->m_loanAmountEdit, "value", SIGNAL(textChanged())); registerField("loanAmountEditValid", ui->m_loanAmountEdit, "valid", SIGNAL(textChanged())); - connect(ui->m_loanAmountEdit, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged())); + connect(ui->m_loanAmountEdit, &KMyMoneyEdit::textChanged, this, &QWizardPage::completeChanged); registerField("loanAmount1", ui->m_loanAmount1, "text"); registerField("interestRate1", ui->m_interestRate1, "text"); registerField("duration1", ui->m_duration1, "text"); registerField("payment1", ui->m_payment1, "text"); registerField("balloon1", ui->m_balloon1, "text"); } LoanAmountWizardPage::~LoanAmountWizardPage() { delete ui; } /** * Update the "Next" button */ bool LoanAmountWizardPage::isComplete() const { return !(field("thisYearPaymentButton").toBool() && !ui->m_loanAmountEdit->isValid()); } void LoanAmountWizardPage::initializePage() { if (field("allPaymentsButton").toBool()) { ui->m_balanceLabel->setText( QString("\n") + i18n("Please enter the original loan amount in the field below or leave it " "empty to be calculated.")); } else if (field("thisYearPaymentButton").toBool()) { ui->m_balanceLabel->setText(QString("\n") + i18n("Please enter the remaining loan amount of last years final " "statement in the field below. You should not leave this field empty.")); } } void LoanAmountWizardPage::resetCalculator() { ui->m_loanAmount1->setText(QString()); ui->m_interestRate1->setText(QString()); ui->m_duration1->setText(QString()); ui->m_payment1->setText(QString()); ui->m_balloon1->setText(QString()); } diff --git a/kmymoney/wizards/newloanwizard/loanattributeswizardpage.cpp b/kmymoney/wizards/newloanwizard/loanattributeswizardpage.cpp index a9e6830a8..97f8e3fef 100644 --- a/kmymoney/wizards/newloanwizard/loanattributeswizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/loanattributeswizardpage.cpp @@ -1,117 +1,117 @@ /*************************************************************************** loanattributeswizardpage - description ------------------- begin : Mon Dec 30 2013 copyright : (C) 2013 by Jeremy Whiting email : jpwhiting@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "loanattributeswizardpage.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes #include #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_loanattributeswizardpage.h" #include "knewbankdlg.h" #include "mymoneyfile.h" #include "mymoneyinstitution.h" #include "mymoneyexception.h" LoanAttributesWizardPage::LoanAttributesWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::LoanAttributesWizardPage) { ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("institution", ui->m_qcomboboxInstitutions); - connect(ui->m_qcomboboxInstitutions, SIGNAL(currentIndexChanged(int)), this, SIGNAL(completeChanged())); - connect(ui->m_qbuttonNew, SIGNAL(clicked()), this, SLOT(slotNewClicked())); + connect(ui->m_qcomboboxInstitutions, static_cast(&QComboBox::currentIndexChanged), this, &QWizardPage::completeChanged); + connect(ui->m_qbuttonNew, &QAbstractButton::clicked, this, &LoanAttributesWizardPage::slotNewClicked); ui->m_qcomboboxInstitutions->clear(); // Are we forcing the user to use institutions? ui->m_qcomboboxInstitutions->addItem(i18n("(No Institution)")); try { MyMoneyFile *file = MyMoneyFile::instance(); QList list; file->institutionList(list); qSort(list); Q_FOREACH(const MyMoneyInstitution &institution, list) { ui->m_qcomboboxInstitutions->addItem(institution.name()); } } catch (const MyMoneyException &e) { qDebug("Exception in institution load: %s", qPrintable(e.what())); } } LoanAttributesWizardPage::~LoanAttributesWizardPage() { delete ui; } /** * Update the "Next" button */ bool LoanAttributesWizardPage::isComplete() const { return true; } void LoanAttributesWizardPage::initializePage() { } void LoanAttributesWizardPage::setInstitution(const QString &institutionName) { if (institutionName.isEmpty()) { ui->m_qcomboboxInstitutions->setCurrentItem(i18n("(No Institution)")); } else { ui->m_qcomboboxInstitutions->setCurrentItem(institutionName, false); } } void LoanAttributesWizardPage::slotNewClicked() { MyMoneyInstitution institution; QPointer dlg = new KNewBankDlg(institution, this); if (dlg->exec() && dlg != 0) { MyMoneyFileTransaction ft; try { MyMoneyFile *file = MyMoneyFile::instance(); institution = dlg->institution(); file->addInstitution(institution); ft.commit(); initializePage(); ui->m_qcomboboxInstitutions->setCurrentItem(institution.name(), false); } catch (const MyMoneyException &) { KMessageBox::information(this, i18n("Cannot add institution")); } } delete dlg; } diff --git a/kmymoney/wizards/newloanwizard/namewizardpage.cpp b/kmymoney/wizards/newloanwizard/namewizardpage.cpp index 126ca6ffd..77cd4f164 100644 --- a/kmymoney/wizards/newloanwizard/namewizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/namewizardpage.cpp @@ -1,69 +1,69 @@ /*************************************************************************** namewizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "namewizardpage.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_namewizardpage.h" NameWizardPage::NameWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::NameWizardPage) { ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("payeeEdit", ui->m_payeeEdit, "selectedItem", SIGNAL(itemSelected(QString))); - connect(ui->m_nameEdit, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged())); + connect(ui->m_nameEdit, &QLineEdit::textChanged, this, &QWizardPage::completeChanged); } NameWizardPage::~NameWizardPage() { delete ui; } /** * Update the "Next" button */ bool NameWizardPage::isComplete() const { return !ui->m_nameEdit->text().isEmpty(); } void NameWizardPage::initializePage() { if (field("borrowButton").toBool()) { ui->m_generalReceiverText->setText(i18n("To whom do you make payments?")); ui->m_receiverLabel->setText(i18n("Payments to")); } else if (field("lendButton").toBool()) { ui->m_generalReceiverText->setText(i18n("From whom do you expect payments?")); ui->m_receiverLabel->setText(i18n("Payments from")); } ui->m_nameEdit->setFocus(); } diff --git a/kmymoney/wizards/newloanwizard/paymenteditwizardpage.cpp b/kmymoney/wizards/newloanwizard/paymenteditwizardpage.cpp index 1af16d22a..8f2460c5d 100644 --- a/kmymoney/wizards/newloanwizard/paymenteditwizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/paymenteditwizardpage.cpp @@ -1,49 +1,49 @@ /*************************************************************************** paymenteditwizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "paymenteditwizardpage.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes #include "ui_paymenteditwizardpage.h" PaymentEditWizardPage::PaymentEditWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::PaymentEditWizardPage) { ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("newPaymentEdit", ui->m_newPaymentEdit, "value", SIGNAL(textChanged())); registerField("newPaymentEditValid", ui->m_newPaymentEdit, "valid", SIGNAL(textChanged())); - connect(ui->m_newPaymentEdit, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged())); + connect(ui->m_newPaymentEdit, &KMyMoneyEdit::textChanged, this, &QWizardPage::completeChanged); } PaymentEditWizardPage::~PaymentEditWizardPage() { delete ui; } diff --git a/kmymoney/wizards/newloanwizard/paymentfrequencywizardpage.cpp b/kmymoney/wizards/newloanwizard/paymentfrequencywizardpage.cpp index 420ef882b..4d29632dc 100644 --- a/kmymoney/wizards/newloanwizard/paymentfrequencywizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/paymentfrequencywizardpage.cpp @@ -1,47 +1,46 @@ /*************************************************************************** paymentfrequencywizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "paymentfrequencywizardpage.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes - // ---------------------------------------------------------------------------- // Project Includes #include "ui_paymentfrequencywizardpage.h" -#include "mymoneyschedule.h" +#include "mymoneyenums.h" PaymentFrequencyWizardPage::PaymentFrequencyWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::PaymentFrequencyWizardPage) { ui->setupUi(this); registerField("paymentFrequencyUnitEdit", ui->m_paymentFrequencyUnitEdit, "data", SIGNAL(currentDataChanged(QVariant))); ui->m_paymentFrequencyUnitEdit->setCurrentIndex(ui->m_paymentFrequencyUnitEdit->findData(QVariant((int)eMyMoney::Schedule::Occurrence::Monthly), Qt::UserRole, Qt::MatchExactly)); } PaymentFrequencyWizardPage::~PaymentFrequencyWizardPage() { delete ui; } diff --git a/kmymoney/wizards/newloanwizard/schedulewizardpage.cpp b/kmymoney/wizards/newloanwizard/schedulewizardpage.cpp index 35c6b4563..7a7ab9268 100644 --- a/kmymoney/wizards/newloanwizard/schedulewizardpage.cpp +++ b/kmymoney/wizards/newloanwizard/schedulewizardpage.cpp @@ -1,78 +1,78 @@ /*************************************************************************** schedulewizardpage - description ------------------- begin : Sun Jul 4 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "schedulewizardpage.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes #include "ui_schedulewizardpage.h" ScheduleWizardPage::ScheduleWizardPage(QWidget *parent) : QWizardPage(parent), ui(new Ui::ScheduleWizardPage) { ui->setupUi(this); // Register the fields with the QWizard and connect the // appropriate signals to update the "Next" button correctly registerField("nextDueDateEdit", ui->m_nextDueDateEdit, "date", SIGNAL(dateChanged(QDate))); registerField("paymentAccountEdit", ui->m_paymentAccountEdit, "selectedItems"); - connect(ui->m_nextDueDateEdit, SIGNAL(dateChanged(QDate)), this, SIGNAL(completeChanged())); - connect(ui->m_paymentAccountEdit, SIGNAL(stateChanged()), this, SIGNAL(completeChanged())); + connect(ui->m_nextDueDateEdit, &KMyMoneyDateInput::dateChanged, this, &QWizardPage::completeChanged); + connect(ui->m_paymentAccountEdit, &KMyMoneySelector::stateChanged, this, &QWizardPage::completeChanged); ui->m_paymentAccountEdit->removeButtons(); } ScheduleWizardPage::~ScheduleWizardPage() { delete ui; } /** * Update the "Next" button */ bool ScheduleWizardPage::isComplete() const { return ui->m_nextDueDateEdit->date().isValid() && ui->m_nextDueDateEdit->date() >= field("firstDueDateEdit").toDate() && ui->m_paymentAccountEdit->selectedItems().count() > 0; } void ScheduleWizardPage::initializePage() { ui->m_nextDueDateEdit->setEnabled(true); if (field("allPaymentsButton").toBool() || field("noPreviousPaymentButton").toBool()) { setField("nextDueDateEdit", field("firstDueDateEdit").toDate()); ui->m_nextDueDateEdit->setEnabled(false); } else { QDate nextPayment(QDate::currentDate().year(), 1, field("firstDueDateEdit").toDate().day()); setField("nextDueDateEdit", nextPayment); } if (field("nextDueDateEdit").toDate() < field("firstDueDateEdit").toDate()) { setField("nextDueDateEdit", field("firstDueDateEdit").toDate()); } } diff --git a/kmymoney/wizards/newuserwizard/CMakeLists.txt b/kmymoney/wizards/newuserwizard/CMakeLists.txt index 892848268..12841f01b 100644 --- a/kmymoney/wizards/newuserwizard/CMakeLists.txt +++ b/kmymoney/wizards/newuserwizard/CMakeLists.txt @@ -1,21 +1,29 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) set (libnewuserwizard_a_SOURCES knewuserwizard.cpp + kaccountpage.cpp + kcategoriespage.cpp + kcurrencypage.cpp + kfilepage.cpp + kgeneralpage.cpp + kintropage.cpp + kpreferencepage.cpp ) set (libnewuserwizard_a_UI - kaccountpagedecl.ui kcurrencypagedecl.ui kfilepagedecl.ui - kgeneralpagedecl.ui kintropagedecl.ui kpasswordpagedecl.ui - kpreferencepagedecl.ui + kaccountpage.ui kcurrencypage.ui + kfilepage.ui kgeneralpage.ui + kintropage.ui kpreferencepage.ui + kpasswordpage.ui ) # The handling of these ui files depends # on libkmymoney.so (the widgets library) ki18n_wrap_ui(libnewuserwizard_a_SOURCES ${libnewuserwizard_a_UI}) add_library(newuserwizard STATIC ${libnewuserwizard_a_SOURCES}) # TODO: clean dependencies -target_link_libraries(newuserwizard KF5::ConfigGui KF5::KIOWidgets KF5::TextWidgets KF5::Completion Qt5::Widgets Qt5::Sql Qt5::Xml Alkimia::alkimia) +target_link_libraries(newuserwizard kmymoneywizard KF5::ConfigGui KF5::KIOWidgets KF5::TextWidgets KF5::Completion KF5::ConfigWidgets Qt5::Widgets Qt5::Xml Alkimia::alkimia) add_dependencies(newuserwizard widgets wizardpages) diff --git a/kmymoney/wizards/newuserwizard/kaccountpage.cpp b/kmymoney/wizards/newuserwizard/kaccountpage.cpp new file mode 100644 index 000000000..f5091ef12 --- /dev/null +++ b/kmymoney/wizards/newuserwizard/kaccountpage.cpp @@ -0,0 +1,76 @@ +/*************************************************************************** + kaccountpage.cpp + ------------------- + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kaccountpage.h" +#include "kaccountpage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kaccountpage.h" + +#include "kmymoneydateinput.h" +#include "knewuserwizard.h" +#include "knewuserwizard_p.h" +#include "kcategoriespage.h" +#include "wizardpage.h" +#include "kguiutils.h" + +namespace NewUserWizard +{ + AccountPage::AccountPage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new AccountPagePrivate(wizard), stepCount, this, wizard) // don't inc. the step count here + { + Q_D(AccountPage); + d->ui->setupUi(this); + d->m_mandatoryGroup->add(d->ui->m_accountNameEdit); + connect(d->m_mandatoryGroup, static_cast(&KMandatoryFieldGroup::stateChanged), object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + connect(d->ui->m_haveCheckingAccountButton, &QAbstractButton::toggled, object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + d->ui->m_accountNameEdit->setFocus(); + d->ui->m_openingDateEdit->setDate(QDate(QDate::currentDate().year(), 1, 1)); + } + + AccountPage::~AccountPage() + { + } + + KMyMoneyWizardPage* AccountPage::nextPage() const + { + Q_D(const AccountPage); + return d->m_wizard->d_func()->m_categoriesPage; + } + + bool AccountPage::isComplete() const + { + Q_D(const AccountPage); + return !d->ui->m_haveCheckingAccountButton->isChecked() || d->m_mandatoryGroup->isEnabled(); + } + +} diff --git a/kmymoney/wizards/wizardpages/currency.h b/kmymoney/wizards/newuserwizard/kaccountpage.h similarity index 57% copy from kmymoney/wizards/wizardpages/currency.h copy to kmymoney/wizards/newuserwizard/kaccountpage.h index af1bb2ae6..838c7c465 100644 --- a/kmymoney/wizards/wizardpages/currency.h +++ b/kmymoney/wizards/newuserwizard/kaccountpage.h @@ -1,53 +1,61 @@ /*************************************************************************** - currency.h + kaccountpage.h ------------------- - begin : Fri Jun 1 2007 - copyright : (C) 2007 Thomas Baumgart + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef CURRENCY_H -#define CURRENCY_H +#ifndef KNEWUSERWIZARDACCOUNTPAGE_H +#define KNEWUSERWIZARDACCOUNTPAGE_H // ---------------------------------------------------------------------------- // QT Includes + #include // ---------------------------------------------------------------------------- // Project Includes -#include "ui_currencydecl.h" - -class MyMoneySecurity; +#include "wizardpage.h" -/** - * @author Thomas Baumgart - */ +class KMyMoneyWizardPage; -class CurrencyDecl : public QWidget, public Ui::CurrencyDecl +namespace NewUserWizard { -public: - CurrencyDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; -class Currency : public CurrencyDecl -{ - Q_OBJECT -public: - Currency(QWidget* parent = 0); - QTreeWidgetItem* insertCurrency(const MyMoneySecurity& sec); - void selectCurrency(const MyMoneySecurity& sec); - QString selectedCurrency() const; -}; + class Wizard; + + /** + * Wizard page collecting information about the checking account + */ + class AccountPagePrivate; + class AccountPage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(AccountPage) + + public: + explicit AccountPage(Wizard* parent); + ~AccountPage() override; + + KMyMoneyWizardPage* nextPage() const override; + + bool isComplete() const override; + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, AccountPage) + friend class Wizard; + friend class CurrencyPage; + }; +} // namespace #endif diff --git a/kmymoney/wizards/newuserwizard/kaccountpagedecl.ui b/kmymoney/wizards/newuserwizard/kaccountpage.ui similarity index 99% rename from kmymoney/wizards/newuserwizard/kaccountpagedecl.ui rename to kmymoney/wizards/newuserwizard/kaccountpage.ui index 470b87142..01b6b6ce5 100644 --- a/kmymoney/wizards/newuserwizard/kaccountpagedecl.ui +++ b/kmymoney/wizards/newuserwizard/kaccountpage.ui @@ -1,256 +1,256 @@ - KAccountPageDecl - + KAccountPage + 0 0 600 481 Qt::NoFocus A typical KMyMoney user maintains a checking account with some institution and uses it to receive money or pay bills. If this is not the case, please deselect the checkbox below and continue on the next page. true I have a checking account that I want to manage with KMyMoney QFrame::NoFrame QFrame::Plain 0 The name of the institution that issued the account. Each institution has a routing number. Enter it here. If uncertain, leave the field blank. You can modify it later. Name of the institution false Routing number false In general the institution that issued the account also issued a number for it. Enter it here. If uncertain, you can modify this entry later. Enter a descriptive name that will be used by KMyMoney to identify your checking account. Opening date false Enter the date from when on you plan to keep track of the transactions in that account. This is usually the date of the last statement. If uncertain, leave as is. 81 20 QSizePolicy::Expanding Qt::Horizontal Number of the account false Name of the account false Opening balance false xxx false false Enter the opening balance of the account. This is usually the ending balance of the last statement. If uncertain, leave as is. 200 20 QSizePolicy::Expanding Qt::Horizontal Qt::NoFocus The fields below allow you to enter some information about your checking account. Once this wizard finishes, the account will be created for you within KMyMoney. true 20 16 QSizePolicy::Expanding Qt::Vertical m_accountNameEdit m_accountNumberEdit m_openingDateEdit m_openingBalanceEdit m_institutionNameEdit m_institutionNumberEdit m_haveCheckingAccountButton m_haveCheckingAccountButton toggled(bool) m_accountDataFrame setEnabled(bool) diff --git a/kmymoney/widgets/kmymoneywizard_p.h b/kmymoney/wizards/newuserwizard/kaccountpage_p.h similarity index 62% copy from kmymoney/widgets/kmymoneywizard_p.h copy to kmymoney/wizards/newuserwizard/kaccountpage_p.h index 2e365e93c..08feca5fd 100644 --- a/kmymoney/widgets/kmymoneywizard_p.h +++ b/kmymoney/wizards/newuserwizard/kaccountpage_p.h @@ -1,55 +1,57 @@ /*************************************************************************** - kmymoneywizard_p.h + kaccountpage_p.h ------------------- - copyright : (C) 2006 by Thomas Baumagrt - email : ipwizard@users.sourceforge.net + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart + email : Thomas Baumgart (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef KMYMONEYWIZARD_P_H -#define KMYMONEYWIZARD_P_H +#ifndef KNEWUSERWIZARDACCOUNTPAGE_P_H +#define KNEWUSERWIZARDACCOUNTPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes -#include - // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -/** - * @author Thomas Baumgart (C) 2006 - * - * This class represents a helper object required - * to be able to use Qt's signal/slot mechanism within - * the KMyMoneyWizardPage object which cannot be - * derived from QObject directly. - */ -class KMyMoneyWizardPagePrivate : public QObject -{ - Q_OBJECT -public: - /** - * Constructor - */ - explicit KMyMoneyWizardPagePrivate(QObject* parent); - - void emitCompleteStateChanged(void); - -signals: - void completeStateChanged(void); -}; +#include "ui_kaccountpage.h" +#include "wizardpage_p.h" +namespace NewUserWizard +{ + class Wizard; + + class AccountPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(AccountPagePrivate) + + public: + AccountPagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KAccountPage) + { + } + + ~AccountPagePrivate() + { + delete ui; + } + + Ui::KAccountPage *ui; + }; +} #endif diff --git a/kmymoney/wizards/newuserwizard/kcategoriespage.cpp b/kmymoney/wizards/newuserwizard/kcategoriespage.cpp new file mode 100644 index 000000000..8d3715054 --- /dev/null +++ b/kmymoney/wizards/newuserwizard/kcategoriespage.cpp @@ -0,0 +1,76 @@ +/*************************************************************************** + kcategoriespage.cpp + ------------------- + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kcategoriespage.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_accounts.h" + +#include "kaccounttemplateselector.h" +#include "knewuserwizard.h" +#include "knewuserwizard_p.h" +#include "kpreferencepage.h" +#include "wizardpage_p.h" +#include "mymoneytemplate.h" + +namespace NewUserWizard +{ + class CategoriesPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(CategoriesPagePrivate) + + public: + CategoriesPagePrivate(QObject* parent) : + WizardPagePrivate(parent) + { + } + }; + + CategoriesPage::CategoriesPage(Wizard* wizard) : + Accounts(wizard), + WizardPage(*new CategoriesPagePrivate(wizard), stepCount++, this, wizard) + { + } + + CategoriesPage::~CategoriesPage() + { + } + + KMyMoneyWizardPage* CategoriesPage::nextPage() const + { + Q_D(const CategoriesPage); + return d->m_wizard->d_func()->m_preferencePage; + } + + QList CategoriesPage::selectedTemplates() const + { + Q_D(const CategoriesPage); + return ui->m_templateSelector->selectedTemplates(); + } + +} diff --git a/kmymoney/wizards/wizardpages/accounts.h b/kmymoney/wizards/newuserwizard/kcategoriespage.h similarity index 55% copy from kmymoney/wizards/wizardpages/accounts.h copy to kmymoney/wizards/newuserwizard/kcategoriespage.h index 574dd0f1e..c90a9ddcf 100644 --- a/kmymoney/wizards/wizardpages/accounts.h +++ b/kmymoney/wizards/newuserwizard/kcategoriespage.h @@ -1,51 +1,62 @@ /*************************************************************************** - accounts.h + kcategoriespage.h ------------------- - begin : Fri Jun 1 2007 - copyright : (C) 2007 Thomas Baumgart + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef ACCOUNTS_H -#define ACCOUNTS_H +#ifndef KNEWUSERWIZARDCATEGORIESPAGE_H +#define KNEWUSERWIZARDCATEGORIESPAGE_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // Project Includes -#include "ui_accountsdecl.h" +#include "wizardpage.h" +#include "accounts.h" -/** - * @author Thomas Baumgart - */ +class KMyMoneyWizardPage; +class MyMoneyTemplate; -class AccountsDecl : public QWidget, public Ui::AccountsDecl -{ -public: - AccountsDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; +template class QList; -class Accounts : public AccountsDecl +namespace NewUserWizard { - Q_OBJECT -public: - Accounts(QWidget* parent = 0); - -private: -}; - + class Wizard; + /** + * Wizard page collecting information about the account templates. + * + * @author Thomas Baumgart + */ + class CategoriesPagePrivate; + class CategoriesPage : public Accounts, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(CategoriesPage) + + public: + explicit CategoriesPage(Wizard* parent); + ~CategoriesPage() override; + + KMyMoneyWizardPage* nextPage() const override; + QList selectedTemplates() const; + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, CategoriesPage) + friend class Wizard; + }; +} // namespace #endif diff --git a/kmymoney/wizards/newuserwizard/kcurrencypage.cpp b/kmymoney/wizards/newuserwizard/kcurrencypage.cpp new file mode 100644 index 000000000..536ba8aba --- /dev/null +++ b/kmymoney/wizards/newuserwizard/kcurrencypage.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + kcurrencypage.cpp + ------------------- + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kcurrencypage.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "icons/icons.h" +#include "knewuserwizard.h" +#include "knewuserwizard_p.h" +#include "kaccountpage.h" +#include "kaccountpage_p.h" +#include "mymoneyfile.h" +#include "mymoneysecurity.h" +#include "ui_currency.h" +#include "ui_kaccountpage.h" +#include "wizardpage.h" + +using namespace Icons; + +namespace NewUserWizard +{ + class CurrencyPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(CurrencyPagePrivate) + + public: + CurrencyPagePrivate(QObject* parent) : + WizardPagePrivate(parent) + { + } + }; + + CurrencyPage::CurrencyPage(Wizard* wizard) : + Currency(wizard), + WizardPage(*new CurrencyPagePrivate(wizard), stepCount++, this, wizard) + { + Q_D(CurrencyPage); + QTreeWidgetItem *first = 0; + + QList list = MyMoneyFile::instance()->availableCurrencyList(); + QList::const_iterator it; + + QString localCurrency(QLocale().currencySymbol(QLocale::CurrencyIsoCode)); + QString baseCurrency = MyMoneyFile::instance()->baseCurrency().id(); + + + ui->m_currencyList->clear(); + for (it = list.constBegin(); it != list.constEnd(); ++it) { + QTreeWidgetItem* p = insertCurrency(*it); + if ((*it).id() == baseCurrency) { + first = p; + QIcon icon = QIcon::fromTheme(g_Icons[Icon::ViewBankAccount]); + p->setIcon(0, icon); + } else { + p->setIcon(0, QIcon()); + } + if (!first && (*it).id() == localCurrency) + first = p; + } + + QTreeWidgetItemIterator itemsIt = QTreeWidgetItemIterator(ui->m_currencyList, QTreeWidgetItemIterator::All); + + if (first == 0) + first = *itemsIt; + if (first != 0) { + ui->m_currencyList->setCurrentItem(first); + ui->m_currencyList->setItemSelected(first, true); + ui->m_currencyList->scrollToItem(first, QTreeView::PositionAtTop); + } + } + + CurrencyPage::~CurrencyPage() + { + } + + void CurrencyPage::enterPage() + { + Q_D(CurrencyPage); + ui->m_currencyList->setFocus(); + } + + KMyMoneyWizardPage* CurrencyPage::nextPage() const + { + Q_D(const CurrencyPage); + QString selCur = selectedCurrency(); + QList currencies = MyMoneyFile::instance()->availableCurrencyList(); + foreach (auto currency, currencies) { + if (selCur == currency.id()) { + d->m_wizard->d_func()->m_baseCurrency = currency; + break; + } + } + d->m_wizard->d_func()->m_accountPage->d_func()->ui->m_accountCurrencyLabel->setText(d->m_wizard->d_func()->m_baseCurrency.tradingSymbol()); + return d->m_wizard->d_func()->m_accountPage; + } + +} diff --git a/kmymoney/wizards/wizardpages/accounts.h b/kmymoney/wizards/newuserwizard/kcurrencypage.h similarity index 58% copy from kmymoney/wizards/wizardpages/accounts.h copy to kmymoney/wizards/newuserwizard/kcurrencypage.h index 574dd0f1e..012f92c5c 100644 --- a/kmymoney/wizards/wizardpages/accounts.h +++ b/kmymoney/wizards/newuserwizard/kcurrencypage.h @@ -1,51 +1,59 @@ /*************************************************************************** - accounts.h + kcurrencypage.h ------------------- - begin : Fri Jun 1 2007 - copyright : (C) 2007 Thomas Baumgart + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef ACCOUNTS_H -#define ACCOUNTS_H +#ifndef KNEWUSERWIZARDCURRENCYPAGE_H +#define KNEWUSERWIZARDCURRENCYPAGE_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // Project Includes -#include "ui_accountsdecl.h" +#include "wizardpage.h" +#include "currency.h" -/** - * @author Thomas Baumgart - */ - -class AccountsDecl : public QWidget, public Ui::AccountsDecl -{ -public: - AccountsDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; +class KMyMoneyWizardPage; -class Accounts : public AccountsDecl +namespace NewUserWizard { - Q_OBJECT -public: - Accounts(QWidget* parent = 0); - -private: -}; - + class Wizard; + /** + * Wizard page collecting information about the base currency + * + * @author Thomas Baumgart + */ + class CurrencyPagePrivate; + class CurrencyPage : public Currency, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(CurrencyPage) + + public: + explicit CurrencyPage(Wizard* parent); + ~CurrencyPage() override; + + void enterPage(); + KMyMoneyWizardPage* nextPage() const override; + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, CurrencyPage) + friend class Wizard; + }; +} // namespace #endif diff --git a/kmymoney/wizards/newuserwizard/kcurrencypagedecl.ui b/kmymoney/wizards/newuserwizard/kcurrencypage.ui similarity index 96% rename from kmymoney/wizards/newuserwizard/kcurrencypagedecl.ui rename to kmymoney/wizards/newuserwizard/kcurrencypage.ui index 9b0d6f22e..bb2d1b462 100644 --- a/kmymoney/wizards/newuserwizard/kcurrencypagedecl.ui +++ b/kmymoney/wizards/newuserwizard/kcurrencypage.ui @@ -1,80 +1,80 @@ - KCurrencyPageDecl - + KCurrencyPage + 0 0 626 186 Qt::NoFocus KMyMoney supports multiple currencies. Your reports will be based on a default currency which you can select here. The default for new accounts is also the currency you select here. true 61 21 QSizePolicy::Expanding Qt::Horizontal 51 21 QSizePolicy::Expanding Qt::Horizontal KMyMoneySecuritySelector QWidget
kmymoneycurrencyselector.h
1
diff --git a/kmymoney/wizards/newuserwizard/kfilepage.cpp b/kmymoney/wizards/newuserwizard/kfilepage.cpp new file mode 100644 index 000000000..8069a457b --- /dev/null +++ b/kmymoney/wizards/newuserwizard/kfilepage.cpp @@ -0,0 +1,105 @@ +/*************************************************************************** + kfilepage.cpp + ------------------- + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kfilepage.h" +#include "kfilepage_p.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_kfilepage.h" +#include "knewuserwizard.h" +#include "kguiutils.h" + +namespace NewUserWizard +{ + FilePage::FilePage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new FilePagePrivate(wizard), stepCount++, this, wizard) + { + Q_D(FilePage); + d->ui->setupUi(this); + d->m_mandatoryGroup->add(d->ui->m_dataFileEdit->lineEdit()); + connect(d->m_mandatoryGroup, static_cast(&KMandatoryFieldGroup::stateChanged), object(), &KMyMoneyWizardPagePrivate::completeStateChanged); + + KUser user; + QString folder = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); + if (folder.isEmpty() || !QDir().exists(folder)) + folder = QDir::homePath(); + d->ui->m_dataFileEdit->setStartDir(QUrl::fromLocalFile(folder)); + d->ui->m_dataFileEdit->setUrl(QUrl::fromLocalFile(folder + QLatin1Char('/') + user.loginName() + QLatin1String(".kmy"))); + d->ui->m_dataFileEdit->setFilter(i18n("*.kmy *.xml|KMyMoney files\n*|All files")); + d->ui->m_dataFileEdit->setMode(KFile::File); + } + + FilePage::~FilePage() + { + } + + bool FilePage::isComplete() const + { + Q_D(const FilePage); + //! @todo Allow to overwrite files + bool rc = d->m_mandatoryGroup->isEnabled(); + d->ui->m_existingFileLabel->hide(); + d->ui->m_finishLabel->show(); + if (rc) { + // if a filename is present, check that + // a) the file does not exist + // b) the directory does exist + // c) the file is stored locally (because we cannot check previous conditions if it is not) + const QUrl fullPath = d->ui->m_dataFileEdit->url(); + QFileInfo directory{fullPath.adjusted(QUrl::RemoveFilename).toLocalFile()}; + qDebug() << "Selected fileptah: " << fullPath << " " << directory.absoluteFilePath() << " dir: " << directory.isDir(); + rc = false; + if (!fullPath.isValid() || !fullPath.isLocalFile()) { + d->ui->m_dataFileEdit->setToolTip(i18n("The path has to be valid and cannot be on a remote location.")); + } else if (QFileInfo::exists(fullPath.toLocalFile())) { + d->ui->m_dataFileEdit->setToolTip(i18n("The file exists already. Please create a new file.")); + } else if (!directory.isDir()) { + d->ui->m_dataFileEdit->setToolTip(i18n("The destination directory does not exist or cannot be written to.")); + } else { + d->ui->m_dataFileEdit->setToolTip(""); + rc = true; + } + + d->ui->m_existingFileLabel->setHidden(rc); + d->ui->m_finishLabel->setVisible(rc); + } + return rc; + } + +} diff --git a/kmymoney/wizards/wizardpages/currency.h b/kmymoney/wizards/newuserwizard/kfilepage.h similarity index 62% copy from kmymoney/wizards/wizardpages/currency.h copy to kmymoney/wizards/newuserwizard/kfilepage.h index af1bb2ae6..7d1f66c61 100644 --- a/kmymoney/wizards/wizardpages/currency.h +++ b/kmymoney/wizards/newuserwizard/kfilepage.h @@ -1,53 +1,58 @@ /*************************************************************************** - currency.h + kfilepage.h ------------------- - begin : Fri Jun 1 2007 - copyright : (C) 2007 Thomas Baumgart + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef CURRENCY_H -#define CURRENCY_H +#ifndef KNEWUSERWIZARDFILEPAGE_H +#define KNEWUSERWIZARDFILEPAGE_H // ---------------------------------------------------------------------------- // QT Includes + #include // ---------------------------------------------------------------------------- // Project Includes -#include "ui_currencydecl.h" - -class MyMoneySecurity; +#include "wizardpage.h" -/** +namespace NewUserWizard +{ + class Wizard; + /** + * Wizard page to allow selecting the filename + * * @author Thomas Baumgart */ + class FilePagePrivate; + class FilePage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(FilePage) -class CurrencyDecl : public QWidget, public Ui::CurrencyDecl -{ -public: - CurrencyDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; -class Currency : public CurrencyDecl -{ - Q_OBJECT -public: - Currency(QWidget* parent = 0); - QTreeWidgetItem* insertCurrency(const MyMoneySecurity& sec); - void selectCurrency(const MyMoneySecurity& sec); - QString selectedCurrency() const; -}; + public: + explicit FilePage(Wizard* parent); + ~FilePage() override; + + bool isComplete() const override; + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, FilePage) + friend class Wizard; + }; + +} // namespace #endif diff --git a/kmymoney/wizards/newuserwizard/kfilepagedecl.ui b/kmymoney/wizards/newuserwizard/kfilepage.ui similarity index 97% rename from kmymoney/wizards/newuserwizard/kfilepagedecl.ui rename to kmymoney/wizards/newuserwizard/kfilepage.ui index b0cd379f7..df6f191e2 100644 --- a/kmymoney/wizards/newuserwizard/kfilepagedecl.ui +++ b/kmymoney/wizards/newuserwizard/kfilepage.ui @@ -1,92 +1,92 @@ - KFilePageDecl - + KFilePage + 0 0 602 350 Qt::NoFocus KMyMoney will store your financial data in a file on the disk. A standard filename within your user environment will be the default. This is just provided for convenience and you can choose any other location here. true Qt::Vertical QSizePolicy::Expanding 20 30 Either the currently selected file exists or the selected directory does not exist. Please make sure, that <ul> <li>the selected directory exists and</li> <li>the filename is not currently used in this directory.</li> </ul> Qt::RichText true Qt::NoFocus This finishes the setup of your KMyMoney environment. You can now press the Finish button and start using KMyMoney to record your financial transactions. Qt::RichText true KUrlRequester QFrame
kurlrequester.h
diff --git a/kmymoney/widgets/kmymoneywizard_p.h b/kmymoney/wizards/newuserwizard/kfilepage_p.h similarity index 63% copy from kmymoney/widgets/kmymoneywizard_p.h copy to kmymoney/wizards/newuserwizard/kfilepage_p.h index 2e365e93c..0b1b997da 100644 --- a/kmymoney/widgets/kmymoneywizard_p.h +++ b/kmymoney/wizards/newuserwizard/kfilepage_p.h @@ -1,55 +1,57 @@ /*************************************************************************** - kmymoneywizard_p.h + kfilepage_p.h ------------------- - copyright : (C) 2006 by Thomas Baumagrt - email : ipwizard@users.sourceforge.net + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart + email : Thomas Baumgart (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef KMYMONEYWIZARD_P_H -#define KMYMONEYWIZARD_P_H +#ifndef KNEWUSERWIZARDFILEPAGE_P_H +#define KNEWUSERWIZARDFILEPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes -#include - // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -/** - * @author Thomas Baumgart (C) 2006 - * - * This class represents a helper object required - * to be able to use Qt's signal/slot mechanism within - * the KMyMoneyWizardPage object which cannot be - * derived from QObject directly. - */ -class KMyMoneyWizardPagePrivate : public QObject -{ - Q_OBJECT -public: - /** - * Constructor - */ - explicit KMyMoneyWizardPagePrivate(QObject* parent); - - void emitCompleteStateChanged(void); - -signals: - void completeStateChanged(void); -}; +#include "ui_kfilepage.h" +#include "wizardpage_p.h" +namespace NewUserWizard +{ + class Wizard; + + class FilePagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(FilePagePrivate) + + public: + FilePagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KFilePage) + { + } + + ~FilePagePrivate() + { + delete ui; + } + + Ui::KFilePage *ui; + }; +} #endif diff --git a/kmymoney/wizards/newuserwizard/kgeneralpage.cpp b/kmymoney/wizards/newuserwizard/kgeneralpage.cpp new file mode 100644 index 000000000..1eb38b956 --- /dev/null +++ b/kmymoney/wizards/newuserwizard/kgeneralpage.cpp @@ -0,0 +1,114 @@ +/*************************************************************************** + kgeneralpage.cpp + ------------------- + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart + email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kgeneralpage.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "userinfo.h" +#include "ui_userinfo.h" + +#include "knewuserwizard.h" +#include "knewuserwizard_p.h" + +#include "mymoneycontact.h" +#include "kcurrencypage.h" + +class KMyMoneyWizardPage; + +namespace NewUserWizard +{ + class GeneralPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(GeneralPagePrivate) + + public: + GeneralPagePrivate(QObject* parent) : + WizardPagePrivate(parent) + { + } + + MyMoneyContact *m_contact; + }; + + GeneralPage::GeneralPage(Wizard* wizard) : + UserInfo(wizard), + WizardPage(*new GeneralPagePrivate(wizard), stepCount++, this, wizard) + { + Q_D(GeneralPage); + d->m_contact = new MyMoneyContact(this); + ui->m_userNameEdit->setFocus(); + + ui->m_loadAddressButton->setEnabled(d->m_contact->ownerExists()); + connect(ui->m_loadAddressButton, &QAbstractButton::clicked, this, &GeneralPage::slotLoadFromAddressBook); + } + + GeneralPage::~GeneralPage() + { + } + + void GeneralPage::slotLoadFromAddressBook() + { + Q_D(GeneralPage); + ui->m_userNameEdit->setText(d->m_contact->ownerFullName()); + ui->m_emailEdit->setText(d->m_contact->ownerEmail()); + if (ui->m_emailEdit->text().isEmpty()) { + KMessageBox::sorry(this, i18n("Unable to load data, because no contact has been associated with the owner of the standard address book."), i18n("Address book import")); + return; + } + ui->m_loadAddressButton->setEnabled(false); + connect(d->m_contact, &MyMoneyContact::contactFetched, this, &GeneralPage::slotContactFetched); + d->m_contact->fetchContact(ui->m_emailEdit->text()); + } + + void GeneralPage::slotContactFetched(const ContactData &identity) + { + Q_D(GeneralPage); + ui->m_loadAddressButton->setEnabled(true); + if (identity.email.isEmpty()) + return; + ui->m_telephoneEdit->setText(identity.phoneNumber); + QString sep; + if (!identity.country.isEmpty() && !identity.region.isEmpty()) + sep = " / "; + ui->m_countyEdit->setText(QString("%1%2%3").arg(identity.country, sep, identity.region)); + ui->m_postcodeEdit->setText(identity.postalCode); + ui->m_townEdit->setText(identity.locality); + ui->m_streetEdit->setText(identity.street); + } + + KMyMoneyWizardPage* GeneralPage::nextPage() const + { + Q_D(const GeneralPage); + return d->m_wizard->d_func()->m_currencyPage; + } + +} diff --git a/kmymoney/wizards/wizardpages/accounts.h b/kmymoney/wizards/newuserwizard/kgeneralpage.h similarity index 55% copy from kmymoney/wizards/wizardpages/accounts.h copy to kmymoney/wizards/newuserwizard/kgeneralpage.h index 574dd0f1e..1ed3f7c19 100644 --- a/kmymoney/wizards/wizardpages/accounts.h +++ b/kmymoney/wizards/newuserwizard/kgeneralpage.h @@ -1,51 +1,63 @@ /*************************************************************************** - accounts.h + kgeneralpage.h ------------------- - begin : Fri Jun 1 2007 - copyright : (C) 2007 Thomas Baumgart + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef ACCOUNTS_H -#define ACCOUNTS_H +#ifndef KNEWUSERWIZARDGENERALPAGE_H +#define KNEWUSERWIZARDGENERALPAGE_H // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // Project Includes -#include "ui_accountsdecl.h" +#include "wizardpage.h" +#include "userinfo.h" -/** - * @author Thomas Baumgart - */ - -class AccountsDecl : public QWidget, public Ui::AccountsDecl -{ -public: - AccountsDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; +class KMyMoneyWizardPage; +class ContactData; -class Accounts : public AccountsDecl +namespace NewUserWizard { - Q_OBJECT -public: - Accounts(QWidget* parent = 0); - -private: -}; - + class Wizard; + /** + * Wizard page collecting information about the user + * + * @author Thomas Baumgart + */ + class GeneralPagePrivate; + class GeneralPage : public UserInfo, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(GeneralPage) + + public: + explicit GeneralPage(Wizard* parent); + ~GeneralPage() override; + + KMyMoneyWizardPage* nextPage() const override; + + protected slots: + void slotLoadFromAddressBook(); + void slotContactFetched(const ContactData &identity); + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, GeneralPage) + friend class Wizard; + }; +} // namespace #endif diff --git a/kmymoney/wizards/newuserwizard/kgeneralpagedecl.ui b/kmymoney/wizards/newuserwizard/kgeneralpage.ui similarity index 99% rename from kmymoney/wizards/newuserwizard/kgeneralpagedecl.ui rename to kmymoney/wizards/newuserwizard/kgeneralpage.ui index b0dfcc22d..464e19d28 100644 --- a/kmymoney/wizards/newuserwizard/kgeneralpagedecl.ui +++ b/kmymoney/wizards/newuserwizard/kgeneralpage.ui @@ -1,237 +1,237 @@ - KGeneralPageDecl - + KGeneralPage + 0 0 600 415 Please enter some information about yourself.<br><br> This information will be seen and used only by you. The information is used to personalize KMyMoney, to encrypt your file, etc. true 25 0 QFrame::NoFrame QFrame::Plain 100 0 County/State: false 100 0 Street: false 100 0 Email: false Your name: false 100 0 Telephone: false 100 0 Town: false 100 0 Zip code false Load from Addressbook 61 20 QSizePolicy::Expanding Qt::Horizontal 25 0 QFrame::NoFrame QFrame::Plain KLineEdit QLineEdit
klineedit.h
diff --git a/kmymoney/widgets/kmymoneywizard_p.h b/kmymoney/wizards/newuserwizard/kintropage.cpp similarity index 52% copy from kmymoney/widgets/kmymoneywizard_p.h copy to kmymoney/wizards/newuserwizard/kintropage.cpp index 2e365e93c..1156f5c87 100644 --- a/kmymoney/widgets/kmymoneywizard_p.h +++ b/kmymoney/wizards/newuserwizard/kintropage.cpp @@ -1,55 +1,77 @@ /*************************************************************************** - kmymoneywizard_p.h + kintropage.cpp ------------------- - copyright : (C) 2006 by Thomas Baumagrt - email : ipwizard@users.sourceforge.net + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart + email : Thomas Baumgart (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef KMYMONEYWIZARD_P_H -#define KMYMONEYWIZARD_P_H +#include "kintropage.h" // ---------------------------------------------------------------------------- // QT Includes -#include - // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -/** - * @author Thomas Baumgart (C) 2006 - * - * This class represents a helper object required - * to be able to use Qt's signal/slot mechanism within - * the KMyMoneyWizardPage object which cannot be - * derived from QObject directly. - */ -class KMyMoneyWizardPagePrivate : public QObject +#include "ui_kintropage.h" + +#include "knewuserwizard.h" +#include "knewuserwizard_p.h" +#include "kgeneralpage.h" + +class KMyMoneyWizardPage; + +namespace NewUserWizard { - Q_OBJECT -public: - /** - * Constructor - */ - explicit KMyMoneyWizardPagePrivate(QObject* parent); + class IntroPagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(IntroPagePrivate) + + public: + IntroPagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KIntroPage) + { + } + + ~IntroPagePrivate() + { + delete ui; + } + + Ui::KIntroPage *ui; + }; + + IntroPage::IntroPage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new IntroPagePrivate(wizard), stepCount++, this, wizard) + { + Q_D(IntroPage); + d->ui->setupUi(this); + } - void emitCompleteStateChanged(void); + IntroPage::~IntroPage() + { + } -signals: - void completeStateChanged(void); -}; + KMyMoneyWizardPage* IntroPage::nextPage() const + { + Q_D(const IntroPage); + return d->m_wizard->d_func()->m_generalPage; + } -#endif +} diff --git a/kmymoney/wizards/wizardpages/currency.h b/kmymoney/wizards/newuserwizard/kintropage.h similarity index 62% copy from kmymoney/wizards/wizardpages/currency.h copy to kmymoney/wizards/newuserwizard/kintropage.h index af1bb2ae6..67bd6636c 100644 --- a/kmymoney/wizards/wizardpages/currency.h +++ b/kmymoney/wizards/newuserwizard/kintropage.h @@ -1,53 +1,55 @@ /*************************************************************************** - currency.h + kintropage.h ------------------- - begin : Fri Jun 1 2007 - copyright : (C) 2007 Thomas Baumgart + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef CURRENCY_H -#define CURRENCY_H +#ifndef KNEWUSERWIZARDINTROPAGE_H +#define KNEWUSERWIZARDINTROPAGE_H // ---------------------------------------------------------------------------- // QT Includes + #include // ---------------------------------------------------------------------------- // Project Includes -#include "ui_currencydecl.h" - -class MyMoneySecurity; +#include "wizardpage.h" -/** - * @author Thomas Baumgart - */ +class KMyMoneyWizardPage; -class CurrencyDecl : public QWidget, public Ui::CurrencyDecl +namespace NewUserWizard { -public: - CurrencyDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; -class Currency : public CurrencyDecl -{ - Q_OBJECT -public: - Currency(QWidget* parent = 0); - QTreeWidgetItem* insertCurrency(const MyMoneySecurity& sec); - void selectCurrency(const MyMoneySecurity& sec); - QString selectedCurrency() const; -}; + class Wizard; + + class IntroPagePrivate; + class IntroPage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(IntroPage) + + public: + explicit IntroPage(Wizard* parent); + ~IntroPage() override; + + KMyMoneyWizardPage* nextPage() const override; + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, IntroPage) + friend class Wizard; + }; +} // namespace #endif diff --git a/kmymoney/wizards/newuserwizard/kintropagedecl.ui b/kmymoney/wizards/newuserwizard/kintropage.ui similarity index 96% rename from kmymoney/wizards/newuserwizard/kintropagedecl.ui rename to kmymoney/wizards/newuserwizard/kintropage.ui index 7197191a8..d09c251ce 100644 --- a/kmymoney/wizards/newuserwizard/kintropagedecl.ui +++ b/kmymoney/wizards/newuserwizard/kintropage.ui @@ -1,67 +1,67 @@ - KIntroPageDecl - + KIntroPage + 0 0 600 415 16 true Welcome to KMyMoney! Qt::AlignCenter false You have started KMyMoney for the first time on this computer. Before this program can help you to manage your finances, it needs to collect some data from you.<p> On the next few pages you will be guided through the steps necessary to setup the program. This will happen only once. true 20 41 QSizePolicy::Expanding Qt::Vertical diff --git a/kmymoney/wizards/newuserwizard/knewuserwizard.cpp b/kmymoney/wizards/newuserwizard/knewuserwizard.cpp index b06716086..6584dd6e9 100644 --- a/kmymoney/wizards/newuserwizard/knewuserwizard.cpp +++ b/kmymoney/wizards/newuserwizard/knewuserwizard.cpp @@ -1,362 +1,164 @@ /*************************************************************************** knewuserwizard.cpp ------------------- begin : Sat Feb 18 2006 copyright : (C) 2006 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "knewuserwizard.h" #include "knewuserwizard_p.h" // ---------------------------------------------------------------------------- // QT Includes -#include #include -#include -#include -#include #include -#include // ---------------------------------------------------------------------------- // KDE Includes #include -#include -#include // ---------------------------------------------------------------------------- // Project Includes +#include "kaccountpage.h" +#include "kaccountpage_p.h" +#include "kcategoriespage.h" +#include "kcurrencypage.h" +#include "kfilepage.h" +#include "kfilepage_p.h" +#include "kgeneralpage.h" +#include "kintropage.h" +#include "kpreferencepage.h" +#include "kpreferencepage_p.h" + #include "mymoneysecurity.h" -#include "mymoneyfile.h" -#include #include "mymoneypayee.h" #include "mymoneymoney.h" #include "mymoneyinstitution.h" #include "mymoneyaccount.h" #include "kmymoneydateinput.h" #include "kmymoneyedit.h" -#include #include "kmymoneyglobalsettings.h" -#include "icons/icons.h" - -using namespace Icons; +#include "mymoneytemplate.h" namespace NewUserWizard { - -static int stepCount; - -Wizard::Wizard(QWidget *parent, bool modal, Qt::WindowFlags flags) : - KMyMoneyWizard(parent, modal, flags), - m_introPage(0) -{ - bool isFirstTime = KMyMoneyGlobalSettings::firstTimeRun(); - - stepCount = 1; - - setTitle(i18n("KMyMoney New File Setup")); - if (isFirstTime) - addStep(i18nc("New file wizard introduction", "Introduction")); - addStep(i18n("Personal Data")); - addStep(i18n("Select Currency")); - addStep(i18n("Select Accounts")); - addStep(i18n("Set preferences")); - addStep(i18nc("Finish the wizard", "Finish")); - - if (isFirstTime) - m_introPage = new IntroPage(this); - m_generalPage = new GeneralPage(this); - m_currencyPage = new CurrencyPage(this); - m_accountPage = new AccountPage(this); - m_categoriesPage = new CategoriesPage(this); - m_preferencePage = new PreferencePage(this); - m_filePage = new FilePage(this); - - m_accountPage->m_haveCheckingAccountButton->setChecked(true); - if (isFirstTime) - setFirstPage(m_introPage); - else - setFirstPage(m_generalPage); - - setHelpContext("firsttime-3"); -} - -MyMoneyPayee Wizard::user() const -{ - return m_generalPage->user(); -} - -QUrl Wizard::url() const -{ - return m_filePage->m_dataFileEdit->url(); -} - -MyMoneyInstitution Wizard::institution() const -{ - MyMoneyInstitution inst; - if (m_accountPage->m_haveCheckingAccountButton->isChecked()) { - if (m_accountPage->m_institutionNameEdit->text().length()) { - inst.setName(m_accountPage->m_institutionNameEdit->text()); - if (m_accountPage->m_institutionNumberEdit->text().length()) - inst.setSortcode(m_accountPage->m_institutionNumberEdit->text()); - } + int stepCount = 0; + + Wizard::Wizard(QWidget *parent, bool modal, Qt::WindowFlags flags) : + KMyMoneyWizard(*new WizardPrivate(this), parent, modal, flags) + { + Q_D(Wizard); + bool isFirstTime = KMyMoneyGlobalSettings::firstTimeRun(); + + stepCount = 1; + + setTitle(i18n("KMyMoney New File Setup")); + if (isFirstTime) + addStep(i18nc("New file wizard introduction", "Introduction")); + addStep(i18n("Personal Data")); + addStep(i18n("Select Currency")); + addStep(i18n("Select Accounts")); + addStep(i18n("Set preferences")); + addStep(i18nc("Finish the wizard", "Finish")); + + if (isFirstTime) + d->m_introPage = new IntroPage(this); + d->m_generalPage = new GeneralPage(this); + d->m_currencyPage = new CurrencyPage(this); + d->m_accountPage = new AccountPage(this); + d->m_categoriesPage = new CategoriesPage(this); + d->m_preferencePage = new PreferencePage(this); + d->m_filePage = new FilePage(this); + + d->m_accountPage->d_func()->ui->m_haveCheckingAccountButton->setChecked(true); + if (isFirstTime) + d->setFirstPage(d->m_introPage); + else + d->setFirstPage(d->m_generalPage); + + setHelpContext("firsttime-3"); } - return inst; -} -MyMoneyAccount Wizard::account() const -{ - MyMoneyAccount acc; - if (m_accountPage->m_haveCheckingAccountButton->isChecked()) { - acc.setName(m_accountPage->m_accountNameEdit->text()); - if (m_accountPage->m_accountNumberEdit->text().length()) - acc.setNumber(m_accountPage->m_accountNumberEdit->text()); - acc.setOpeningDate(m_accountPage->m_openingDateEdit->date()); - acc.setCurrencyId(m_baseCurrency.id()); - acc.setAccountType(eMyMoney::Account::Checkings); + Wizard::~Wizard() + { } - return acc; -} - -MyMoneyMoney Wizard::openingBalance() const -{ - return m_accountPage->m_openingBalanceEdit->value(); -} - -MyMoneySecurity Wizard::baseCurrency() const -{ - return m_baseCurrency; -} - -QList Wizard::templates() const -{ - return m_categoriesPage->selectedTemplates(); -} - -bool Wizard::startSettingsAfterFinished() const -{ - return m_preferencePage->m_openConfigAfterFinished->checkState() == Qt::Checked; -} - -IntroPage::IntroPage(Wizard* wizard) : - KIntroPageDecl(wizard), - WizardPage(stepCount++, this, wizard) -{ -} -KMyMoneyWizardPage* IntroPage::nextPage() const -{ - return m_wizard->m_generalPage; -} - -GeneralPage::GeneralPage(Wizard* wizard) : - UserInfo(wizard), - WizardPage(stepCount++, this, wizard), - m_contact(new MyMoneyContact(this)) -{ - m_userNameEdit->setFocus(); - - m_loadAddressButton->setEnabled(m_contact->ownerExists()); - connect(m_loadAddressButton, SIGNAL(clicked()), this, SLOT(slotLoadFromAddressBook())); -} - -void GeneralPage::slotLoadFromAddressBook() -{ - m_userNameEdit->setText(m_contact->ownerFullName()); - m_emailEdit->setText(m_contact->ownerEmail()); - if (m_emailEdit->text().isEmpty()) { - KMessageBox::sorry(this, i18n("Unable to load data, because no contact has been associated with the owner of the standard address book."), i18n("Address book import")); - return; + MyMoneyPayee Wizard::user() const + { + Q_D(const Wizard); + return d->m_generalPage->user(); } - m_loadAddressButton->setEnabled(false); - connect(m_contact, SIGNAL(contactFetched(ContactData)), this, SLOT(slotContactFetched(ContactData))); - m_contact->fetchContact(m_emailEdit->text()); -} - -void GeneralPage::slotContactFetched(const ContactData &identity) -{ - m_loadAddressButton->setEnabled(true); - if (identity.email.isEmpty()) - return; - m_telephoneEdit->setText(identity.phoneNumber); - QString sep; - if (!identity.country.isEmpty() && !identity.region.isEmpty()) - sep = " / "; - m_countyEdit->setText(QString("%1%2%3").arg(identity.country, sep, identity.region)); - m_postcodeEdit->setText(identity.postalCode); - m_townEdit->setText(identity.locality); - m_streetEdit->setText(identity.street); -} -KMyMoneyWizardPage* GeneralPage::nextPage() const -{ - return m_wizard->m_currencyPage; -} - -CurrencyPage::CurrencyPage(Wizard* wizard) : - Currency(wizard), - WizardPage(stepCount++, this, wizard) -{ - QTreeWidgetItem *first = 0; - - QList list = MyMoneyFile::instance()->availableCurrencyList(); - QList::const_iterator it; - - QString localCurrency(QLocale().currencySymbol(QLocale::CurrencyIsoCode)); - QString baseCurrency = MyMoneyFile::instance()->baseCurrency().id(); - - - m_currencyList->clear(); - for (it = list.constBegin(); it != list.constEnd(); ++it) { - QTreeWidgetItem* p = insertCurrency(*it); - if ((*it).id() == baseCurrency) { - first = p; - QIcon icon = QIcon::fromTheme(g_Icons[Icon::ViewBankAccount]); - p->setIcon(0, icon); - } else { - p->setIcon(0, QIcon()); - } - if (!first && (*it).id() == localCurrency) - first = p; + QUrl Wizard::url() const + { + Q_D(const Wizard); + return d->m_filePage->d_func()->ui->m_dataFileEdit->url(); } - QTreeWidgetItemIterator itemsIt = QTreeWidgetItemIterator(m_currencyList, QTreeWidgetItemIterator::All); - - if (first == 0) - first = *itemsIt; - if (first != 0) { - m_currencyList->setCurrentItem(first); - m_currencyList->setItemSelected(first, true); - m_currencyList->scrollToItem(first, QTreeView::PositionAtTop); + MyMoneyInstitution Wizard::institution() const + { + Q_D(const Wizard); + MyMoneyInstitution inst; + if (d->m_accountPage->d_func()->ui->m_haveCheckingAccountButton->isChecked()) { + if (d->m_accountPage->d_func()->ui->m_institutionNameEdit->text().length()) { + inst.setName(d->m_accountPage->d_func()->ui->m_institutionNameEdit->text()); + if (d->m_accountPage->d_func()->ui->m_institutionNumberEdit->text().length()) + inst.setSortcode(d->m_accountPage->d_func()->ui->m_institutionNumberEdit->text()); + } + } + return inst; } -} -void CurrencyPage::enterPage() -{ - m_currencyList->setFocus(); -} - -KMyMoneyWizardPage* CurrencyPage::nextPage() const -{ - QString selCur = selectedCurrency(); - QList currencies = MyMoneyFile::instance()->availableCurrencyList(); - foreach (auto currency, currencies) { - if (selCur == currency.id()) { - m_wizard->m_baseCurrency = currency; - break; + MyMoneyAccount Wizard::account() const + { + Q_D(const Wizard); + MyMoneyAccount acc; + if (d->m_accountPage->d_func()->ui->m_haveCheckingAccountButton->isChecked()) { + acc.setName(d->m_accountPage->d_func()->ui->m_accountNameEdit->text()); + if (d->m_accountPage->d_func()->ui->m_accountNumberEdit->text().length()) + acc.setNumber(d->m_accountPage->d_func()->ui->m_accountNumberEdit->text()); + acc.setOpeningDate(d->m_accountPage->d_func()->ui->m_openingDateEdit->date()); + acc.setCurrencyId(d->m_baseCurrency.id()); + acc.setAccountType(eMyMoney::Account::Checkings); } + return acc; } - m_wizard->m_accountPage->m_accountCurrencyLabel->setText(m_wizard->m_baseCurrency.tradingSymbol()); - return m_wizard->m_accountPage; -} - -AccountPage::AccountPage(Wizard* wizard) : - KAccountPageDecl(wizard), - WizardPage(stepCount, this, wizard) // don't inc. the step count here -{ - m_mandatoryGroup->add(m_accountNameEdit); - connect(m_mandatoryGroup, SIGNAL(stateChanged()), object(), SIGNAL(completeStateChanged())); - connect(m_haveCheckingAccountButton, SIGNAL(toggled(bool)), object(), SIGNAL(completeStateChanged())); - m_accountNameEdit->setFocus(); - m_openingDateEdit->setDate(QDate(QDate::currentDate().year(), 1, 1)); -} - -KMyMoneyWizardPage* AccountPage::nextPage() const -{ - return m_wizard->m_categoriesPage; -} -bool AccountPage::isComplete() const -{ - return !m_haveCheckingAccountButton->isChecked() || m_mandatoryGroup->isEnabled(); -} - -CategoriesPage::CategoriesPage(Wizard* wizard) : - Accounts(wizard), - WizardPage(stepCount++, this, wizard) -{ -} - -KMyMoneyWizardPage* CategoriesPage::nextPage() const -{ - return m_wizard->m_preferencePage; -} - -QList CategoriesPage::selectedTemplates() const -{ - return m_templateSelector->selectedTemplates(); -} - -PreferencePage::PreferencePage(Wizard* wizard) : - KPreferencePageDecl(wizard), - WizardPage(stepCount++, this, wizard) -{ -} - -KMyMoneyWizardPage* PreferencePage::nextPage() const -{ - return m_wizard->m_filePage; -} - -FilePage::FilePage(Wizard* wizard) : - KFilePageDecl(wizard), - WizardPage(stepCount++, this, wizard) -{ - m_mandatoryGroup->add(m_dataFileEdit->lineEdit()); - connect(m_mandatoryGroup, SIGNAL(stateChanged()), object(), SIGNAL(completeStateChanged())); + MyMoneyMoney Wizard::openingBalance() const + { + Q_D(const Wizard); + return d->m_accountPage->d_func()->ui->m_openingBalanceEdit->value(); + } - KUser user; - QString folder = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); - if (folder.isEmpty() || !QDir().exists(folder)) - folder = QDir::homePath(); - m_dataFileEdit->setStartDir(QUrl::fromLocalFile(folder)); - m_dataFileEdit->setUrl(QUrl::fromLocalFile(folder + QLatin1Char('/') + user.loginName() + QLatin1String(".kmy"))); - m_dataFileEdit->setFilter(i18n("*.kmy *.xml|KMyMoney files\n*|All files")); - m_dataFileEdit->setMode(KFile::File); -} + MyMoneySecurity Wizard::baseCurrency() const + { + Q_D(const Wizard); + return d->m_baseCurrency; + } -bool FilePage::isComplete() const -{ - //! @todo Allow to overwrite files - bool rc = m_mandatoryGroup->isEnabled(); - m_existingFileLabel->hide(); - m_finishLabel->show(); - if (rc) { - // if a filename is present, check that - // a) the file does not exist - // b) the directory does exist - // c) the file is stored locally (because we cannot check previous conditions if it is not) - const QUrl fullPath = m_dataFileEdit->url(); - QFileInfo directory{fullPath.adjusted(QUrl::RemoveFilename).toLocalFile()}; - qDebug() << "Selected fileptah: " << fullPath << " " << directory.absoluteFilePath() << " dir: " << directory.isDir(); - rc = false; - if (!fullPath.isValid() || !fullPath.isLocalFile()) { - m_dataFileEdit->setToolTip(i18n("The path has to be valid and cannot be on a remote location.")); - } else if (QFileInfo::exists(fullPath.toLocalFile())) { - m_dataFileEdit->setToolTip(i18n("The file exists already. Please create a new file.")); - } else if (!directory.isDir()) { - m_dataFileEdit->setToolTip(i18n("The destination directory does not exist or cannot be written to.")); - } else { - m_dataFileEdit->setToolTip(""); - rc = true; - } + QList Wizard::templates() const + { + Q_D(const Wizard); + return d->m_categoriesPage->selectedTemplates(); + } - m_existingFileLabel->setHidden(rc); - m_finishLabel->setVisible(rc); + bool Wizard::startSettingsAfterFinished() const + { + Q_D(const Wizard); + return d->m_preferencePage->d_func()->ui->m_openConfigAfterFinished->checkState() == Qt::Checked; } - return rc; -} } diff --git a/kmymoney/wizards/newuserwizard/knewuserwizard.h b/kmymoney/wizards/newuserwizard/knewuserwizard.h index e3a11a0e9..c2a4fbed5 100644 --- a/kmymoney/wizards/newuserwizard/knewuserwizard.h +++ b/kmymoney/wizards/newuserwizard/knewuserwizard.h @@ -1,130 +1,121 @@ /*************************************************************************** knewuserwizard.h ------------------- begin : Sat Feb 18 2006 copyright : (C) 2006 Thomas Baumgart email : Thomas Baumgart + (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KNEWUSERWIZARD_H #define KNEWUSERWIZARD_H // ---------------------------------------------------------------------------- // QT Includes #include #include // ---------------------------------------------------------------------------- // Project Includes #include "kmymoneywizard.h" #include "mymoneysecurity.h" class MyMoneyPayee; class MyMoneyInstitution; class MyMoneyAccount; class MyMoneyMoney; class MyMoneyTemplate; /** * @author Thomas Baumgart */ namespace NewUserWizard { + extern int stepCount; -class IntroPage; -class GeneralPage; -class CurrencyPage; -class AccountPage; -class CategoriesPage; -class PreferencePage; -class FilePage; - -/** + /** * @author Thomas Baumgart * * This class implements the new user wizard which is used to gather * some initial information from the user who creates a new KMyMoney * 'file'. */ -class Wizard : public KMyMoneyWizard -{ - friend class IntroPage; - friend class GeneralPage; - friend class CurrencyPage; - friend class AccountPage; - friend class CategoriesPage; - friend class PreferencePage; - friend class FilePage; - - Q_OBJECT -public: - explicit Wizard(QWidget* parent = 0, bool modal = false, Qt::WindowFlags flags = 0); - /** + class WizardPrivate; + class Wizard : public KMyMoneyWizard + { + friend class IntroPage; + friend class GeneralPage; + friend class CurrencyPage; + friend class AccountPage; + friend class CategoriesPage; + friend class PreferencePage; + friend class FilePage; + + Q_OBJECT + Q_DISABLE_COPY(Wizard) + + public: + explicit Wizard(QWidget *parent = nullptr, bool modal = false, Qt::WindowFlags flags = 0); + ~Wizard() override; + /** * Returns the personal information of the user (e.g. name, address, etc.) */ - MyMoneyPayee user() const; + MyMoneyPayee user() const; - /** + /** * Returns the URL that the user has chosen to store the file */ - QUrl url() const; + QUrl url() const; - /** + /** * Returns the information about an institution if entered by * the user. If the name field is empty, then he did not enter * such information. */ - MyMoneyInstitution institution() const; + MyMoneyInstitution institution() const; - /** + /** * Returns the information about a checking account if entered by * the user. If the name field is empty, then he did not enter * such information. */ - MyMoneyAccount account() const; + MyMoneyAccount account() const; - /** + /** * Returns the opening balance value provided by the user. not enter */ - MyMoneyMoney openingBalance() const; + MyMoneyMoney openingBalance() const; - /** + /** * Returns the security to be used as base currency. */ - MyMoneySecurity baseCurrency() const; + MyMoneySecurity baseCurrency() const; - /** + /** * Returns a list of templates including accounts to be created */ - QList templates() const; + QList templates() const; - /** + /** * True if the settings dialog should be launched after the wizard is finished. */ - bool startSettingsAfterFinished() const; - -private: - MyMoneySecurity m_baseCurrency; - IntroPage* m_introPage; - GeneralPage* m_generalPage; - CurrencyPage* m_currencyPage; - AccountPage* m_accountPage; - CategoriesPage* m_categoriesPage; - PreferencePage* m_preferencePage; - FilePage* m_filePage; -}; + bool startSettingsAfterFinished() const; + + private: + Q_DECLARE_PRIVATE(Wizard) + }; } // namespace #endif diff --git a/kmymoney/wizards/newuserwizard/knewuserwizard_p.h b/kmymoney/wizards/newuserwizard/knewuserwizard_p.h index 2766cd493..d5b8f3a7d 100644 --- a/kmymoney/wizards/newuserwizard/knewuserwizard_p.h +++ b/kmymoney/wizards/newuserwizard/knewuserwizard_p.h @@ -1,180 +1,68 @@ /*************************************************************************** knewuserwizard_p.h ------------------- begin : Sat Feb 18 2006 copyright : (C) 2006 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KNEWUSERWIZARD_P_H #define KNEWUSERWIZARD_P_H // ---------------------------------------------------------------------------- // QT Includes -#include - // ---------------------------------------------------------------------------- // Project Includes -#include -#include "kmymoneywizardpage.h" - -#include "ui_kintropagedecl.h" -#include "ui_kaccountpagedecl.h" -#include "ui_kpreferencepagedecl.h" -#include "ui_kfilepagedecl.h" - -#include "userinfo.h" -#include "currency.h" -#include "accounts.h" - -#include "mymoneytemplate.h" -#include "mymoneycontact.h" - -class Wizard; -class KJob; +#include "knewuserwizard.h" +#include "kmymoneywizard_p.h" +#include "mymoneysecurity.h" namespace NewUserWizard { - -class KIntroPageDecl : public QWidget, public Ui::KIntroPageDecl -{ -public: - KIntroPageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class IntroPage : public KIntroPageDecl, public WizardPage -{ - Q_OBJECT -public: - IntroPage(Wizard* parent); - KMyMoneyWizardPage* nextPage(void) const; -}; - -/** - * Wizard page collecting information about the user - * - * @author Thomas Baumgart - */ -class GeneralPage : public UserInfo, public WizardPage -{ - Q_OBJECT -public: - GeneralPage(Wizard* parent); - KMyMoneyWizardPage* nextPage(void) const; - -protected slots: - void slotLoadFromAddressBook(void); - void slotContactFetched(const ContactData &identity); - -private: - MyMoneyContact *m_contact; -}; - -/** - * Wizard page collecting information about the base currency - * - * @author Thomas Baumgart - */ -class CurrencyPage : public Currency, public WizardPage -{ - Q_OBJECT -public: - CurrencyPage(Wizard* parent); - void enterPage(void); - KMyMoneyWizardPage* nextPage(void) const; -}; - -/** - * Wizard page collecting information about the checking account - */ - -class KAccountPageDecl : public QWidget, public Ui::KAccountPageDecl -{ -public: - KAccountPageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; -class AccountPage : public KAccountPageDecl, public WizardPage -{ - Q_OBJECT -public: - AccountPage(Wizard* parent); - KMyMoneyWizardPage* nextPage(void) const; - - virtual bool isComplete(void) const; -}; - -/** - * Wizard page collecting information about the account templates. - * - * @author Thomas Baumgart - */ -class CategoriesPage : public Accounts, public WizardPage -{ - Q_OBJECT -public: - CategoriesPage(Wizard* parent); - KMyMoneyWizardPage* nextPage(void) const; - QList selectedTemplates(void) const; -}; - -/** - * Wizard page to allow changing the preferences during setup - * - * @author Thomas Baumgart - */ - -class KPreferencePageDecl : public QWidget, public Ui::KPreferencePageDecl -{ -public: - KPreferencePageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; -class PreferencePage : public KPreferencePageDecl, public WizardPage -{ - Q_OBJECT -public: - PreferencePage(Wizard* parent); - KMyMoneyWizardPage* nextPage(void) const; -}; - -/** - * Wizard page to allow selecting the filename - * - * @author Thomas Baumgart - */ - -class KFilePageDecl : public QWidget, public Ui::KFilePageDecl -{ -public: - KFilePageDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; -class FilePage : public KFilePageDecl, public WizardPage -{ - Q_OBJECT -public: - FilePage(Wizard* parent); - - virtual bool isComplete(void) const; -}; + class IntroPage; + class GeneralPage; + class CurrencyPage; + class AccountPage; + class CategoriesPage; + class PreferencePage; + class FilePage; + + class WizardPrivate : public KMyMoneyWizardPrivate + { + Q_DISABLE_COPY(WizardPrivate) + + public: + WizardPrivate(Wizard *qq): + KMyMoneyWizardPrivate(qq), + m_introPage(nullptr) + { + } + + ~WizardPrivate() + { + } + + MyMoneySecurity m_baseCurrency; + IntroPage* m_introPage; + GeneralPage* m_generalPage; + CurrencyPage* m_currencyPage; + AccountPage* m_accountPage; + CategoriesPage* m_categoriesPage; + PreferencePage* m_preferencePage; + FilePage* m_filePage; + }; } // namespace #endif diff --git a/kmymoney/wizards/newuserwizard/kpasswordpagedecl.ui b/kmymoney/wizards/newuserwizard/kpasswordpage.ui similarity index 92% rename from kmymoney/wizards/newuserwizard/kpasswordpagedecl.ui rename to kmymoney/wizards/newuserwizard/kpasswordpage.ui index 21505366b..7f0721e23 100644 --- a/kmymoney/wizards/newuserwizard/kpasswordpagedecl.ui +++ b/kmymoney/wizards/newuserwizard/kpasswordpage.ui @@ -1,33 +1,33 @@ - KPasswordPageDecl - + KPasswordPage + true 0 0 599 149 <p>KMyMoney can encrypt your datafile using GPG Encryption. GPG encryption is one of the most secure methods in the world for protecting data. All of your account numbers and other important financial information will be very secure.</p> true diff --git a/kmymoney/widgets/kmymoneywizard_p.h b/kmymoney/wizards/newuserwizard/kpreferencepage.cpp similarity index 59% copy from kmymoney/widgets/kmymoneywizard_p.h copy to kmymoney/wizards/newuserwizard/kpreferencepage.cpp index 2e365e93c..46a153770 100644 --- a/kmymoney/widgets/kmymoneywizard_p.h +++ b/kmymoney/wizards/newuserwizard/kpreferencepage.cpp @@ -1,55 +1,57 @@ /*************************************************************************** - kmymoneywizard_p.h + kpreferencepage.cpp ------------------- - copyright : (C) 2006 by Thomas Baumagrt - email : ipwizard@users.sourceforge.net + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart + email : Thomas Baumgart (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef KMYMONEYWIZARD_P_H -#define KMYMONEYWIZARD_P_H +#include "kpreferencepage.h" +#include "kpreferencepage_p.h" // ---------------------------------------------------------------------------- // QT Includes -#include - // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -/** - * @author Thomas Baumgart (C) 2006 - * - * This class represents a helper object required - * to be able to use Qt's signal/slot mechanism within - * the KMyMoneyWizardPage object which cannot be - * derived from QObject directly. - */ -class KMyMoneyWizardPagePrivate : public QObject -{ - Q_OBJECT -public: - /** - * Constructor - */ - explicit KMyMoneyWizardPagePrivate(QObject* parent); - - void emitCompleteStateChanged(void); +#include "ui_kpreferencepage.h" -signals: - void completeStateChanged(void); -}; +#include "knewuserwizard.h" +#include "knewuserwizard_p.h" +#include "kfilepage.h" -#endif +namespace NewUserWizard +{ + PreferencePage::PreferencePage(Wizard* wizard) : + QWidget(wizard), + WizardPage(*new PreferencePagePrivate(wizard), stepCount++, this, wizard) + { + Q_D(PreferencePage); + d->ui->setupUi(this); + } + + PreferencePage::~PreferencePage() + { + } + + KMyMoneyWizardPage* PreferencePage::nextPage() const + { + Q_D(const PreferencePage); + return d->m_wizard->d_func()->m_filePage; + } + +} diff --git a/kmymoney/wizards/wizardpages/currency.h b/kmymoney/wizards/newuserwizard/kpreferencepage.h similarity index 59% copy from kmymoney/wizards/wizardpages/currency.h copy to kmymoney/wizards/newuserwizard/kpreferencepage.h index af1bb2ae6..47534a75a 100644 --- a/kmymoney/wizards/wizardpages/currency.h +++ b/kmymoney/wizards/newuserwizard/kpreferencepage.h @@ -1,53 +1,60 @@ /*************************************************************************** - currency.h + kpreferencepage.h ------------------- - begin : Fri Jun 1 2007 - copyright : (C) 2007 Thomas Baumgart + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef CURRENCY_H -#define CURRENCY_H +#ifndef KNEWUSERWIZARDPREFERENCEPAGE_H +#define KNEWUSERWIZARDPREFERENCEPAGE_H // ---------------------------------------------------------------------------- // QT Includes + #include // ---------------------------------------------------------------------------- // Project Includes -#include "ui_currencydecl.h" +#include "wizardpage.h" + +class KMyMoneyWizardPage; -class MyMoneySecurity; +namespace NewUserWizard +{ + class Wizard; -/** + /** + * Wizard page to allow changing the preferences during setup + * * @author Thomas Baumgart */ - -class CurrencyDecl : public QWidget, public Ui::CurrencyDecl -{ -public: - CurrencyDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; -class Currency : public CurrencyDecl -{ - Q_OBJECT -public: - Currency(QWidget* parent = 0); - QTreeWidgetItem* insertCurrency(const MyMoneySecurity& sec); - void selectCurrency(const MyMoneySecurity& sec); - QString selectedCurrency() const; -}; + class PreferencePagePrivate; + class PreferencePage : public QWidget, public WizardPage + { + Q_OBJECT + Q_DISABLE_COPY(PreferencePage) + + public: + explicit PreferencePage(Wizard* parent); + ~PreferencePage() override; + + KMyMoneyWizardPage* nextPage() const override; + + private: + Q_DECLARE_PRIVATE_D(WizardPage::d_ptr, PreferencePage) + friend class Wizard; + }; +} // namespace #endif diff --git a/kmymoney/wizards/newuserwizard/kpreferencepagedecl.ui b/kmymoney/wizards/newuserwizard/kpreferencepage.ui similarity index 95% rename from kmymoney/wizards/newuserwizard/kpreferencepagedecl.ui rename to kmymoney/wizards/newuserwizard/kpreferencepage.ui index c5ecc214d..407b19196 100644 --- a/kmymoney/wizards/newuserwizard/kpreferencepagedecl.ui +++ b/kmymoney/wizards/newuserwizard/kpreferencepage.ui @@ -1,72 +1,72 @@ - KPreferencePageDecl - + KPreferencePage + 0 0 600 288 Qt::NoFocus If you would like to review or change any preference settings for KMyMoney after finishing this wizard, you can do so by checking this box. If not just click <b>Next</b>. true Configure preferences after finishing the wizard. Qt::Vertical QSizePolicy::Expanding 20 31 Qt::NoFocus You can change the configuration options at any time using the configuration dialog. Just select the <b>Configure KMyMoney...</b> option in the <b>Settings</b> menu. true diff --git a/kmymoney/widgets/kmymoneywizard_p.h b/kmymoney/wizards/newuserwizard/kpreferencepage_p.h similarity index 62% copy from kmymoney/widgets/kmymoneywizard_p.h copy to kmymoney/wizards/newuserwizard/kpreferencepage_p.h index 2e365e93c..5433659d7 100644 --- a/kmymoney/widgets/kmymoneywizard_p.h +++ b/kmymoney/wizards/newuserwizard/kpreferencepage_p.h @@ -1,55 +1,56 @@ /*************************************************************************** - kmymoneywizard_p.h + kpreferencepage_p.h ------------------- - copyright : (C) 2006 by Thomas Baumagrt - email : ipwizard@users.sourceforge.net + begin : Sat Feb 18 2006 + copyright : (C) 2006 Thomas Baumgart + email : Thomas Baumgart (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef KMYMONEYWIZARD_P_H -#define KMYMONEYWIZARD_P_H +#ifndef KNEWUSERWIZARDPREFERENCEPAGE_P_H +#define KNEWUSERWIZARDPREFERENCEPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes -#include - // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -/** - * @author Thomas Baumgart (C) 2006 - * - * This class represents a helper object required - * to be able to use Qt's signal/slot mechanism within - * the KMyMoneyWizardPage object which cannot be - * derived from QObject directly. - */ -class KMyMoneyWizardPagePrivate : public QObject -{ - Q_OBJECT -public: - /** - * Constructor - */ - explicit KMyMoneyWizardPagePrivate(QObject* parent); - - void emitCompleteStateChanged(void); - -signals: - void completeStateChanged(void); -}; +#include "ui_kpreferencepage.h" +#include "wizardpage_p.h" +namespace NewUserWizard +{ + class Wizard; + class PreferencePagePrivate : public WizardPagePrivate + { + Q_DISABLE_COPY(PreferencePagePrivate) + + public: + PreferencePagePrivate(QObject* parent) : + WizardPagePrivate(parent), + ui(new Ui::KPreferencePage) + { + } + + ~PreferencePagePrivate() + { + delete ui; + } + + Ui::KPreferencePage *ui; + }; +} #endif diff --git a/kmymoney/widgets/kmymoneywizard_p.h b/kmymoney/wizards/wizardpage.h similarity index 53% copy from kmymoney/widgets/kmymoneywizard_p.h copy to kmymoney/wizards/wizardpage.h index 2e365e93c..1d943f8b7 100644 --- a/kmymoney/widgets/kmymoneywizard_p.h +++ b/kmymoney/wizards/wizardpage.h @@ -1,55 +1,75 @@ /*************************************************************************** - kmymoneywizard_p.h + wizardpage.h ------------------- copyright : (C) 2006 by Thomas Baumagrt email : ipwizard@users.sourceforge.net (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef KMYMONEYWIZARD_P_H -#define KMYMONEYWIZARD_P_H +#ifndef WIZARDPAGE_H +#define WIZARDPAGE_H + +#include "wizardpage_p.h" // ---------------------------------------------------------------------------- // QT Includes -#include - // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes +#include "kmymoneywizardpage.h" + +class KMyMoneyWizard; + /** - * @author Thomas Baumgart (C) 2006 - * - * This class represents a helper object required - * to be able to use Qt's signal/slot mechanism within - * the KMyMoneyWizardPage object which cannot be - * derived from QObject directly. - */ -class KMyMoneyWizardPagePrivate : public QObject + * The general base class for wizard pages + * + * @author Thomas Baumgart + */ + +template +class WizardPage : public KMyMoneyWizardPage { - Q_OBJECT public: - /** - * Constructor - */ - explicit KMyMoneyWizardPagePrivate(QObject* parent); + WizardPage(uint step, QWidget* widget, T* parent) : + KMyMoneyWizardPage(*new WizardPagePrivate(widget), step, widget) + { + d_func()->m_wizard = parent; + d_func()->m_wizardBase = parent; + } + + ~WizardPage() override + { + } - void emitCompleteStateChanged(void); + virtual KMyMoneyWizard* wizard() const + { + return d_func()->m_wizardBase; + } -signals: - void completeStateChanged(void); +protected: + using KMyMoneyWizardPage::d_ptr; + inline WizardPagePrivate* d_func() { return reinterpret_cast *>(qGetPtrHelper(d_ptr)); } + inline const WizardPagePrivate* d_func() const { return reinterpret_cast *>(qGetPtrHelper(d_ptr)); } + friend class WizardPagePrivate; + WizardPage(WizardPagePrivate &dd, uint step, QWidget* widget, T* parent) : + KMyMoneyWizardPage(dd, step, widget) + { + d_func()->m_wizard = parent; + d_func()->m_wizardBase = parent; + } }; #endif diff --git a/kmymoney/widgets/kmymoneywizard_p.h b/kmymoney/wizards/wizardpage_p.h similarity index 69% rename from kmymoney/widgets/kmymoneywizard_p.h rename to kmymoney/wizards/wizardpage_p.h index 2e365e93c..d87d7c6f4 100644 --- a/kmymoney/widgets/kmymoneywizard_p.h +++ b/kmymoney/wizards/wizardpage_p.h @@ -1,55 +1,47 @@ /*************************************************************************** - kmymoneywizard_p.h + wizardpage_p.h ------------------- copyright : (C) 2006 by Thomas Baumagrt email : ipwizard@users.sourceforge.net (C) 2017 by Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ -#ifndef KMYMONEYWIZARD_P_H -#define KMYMONEYWIZARD_P_H +#ifndef WIZARDPAGE_P_H +#define WIZARDPAGE_P_H // ---------------------------------------------------------------------------- // QT Includes -#include - // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes -/** - * @author Thomas Baumgart (C) 2006 - * - * This class represents a helper object required - * to be able to use Qt's signal/slot mechanism within - * the KMyMoneyWizardPage object which cannot be - * derived from QObject directly. - */ -class KMyMoneyWizardPagePrivate : public QObject +#include "kmymoneywizardpage_p.h" + +class KMyMoneyWizard; + +template +class WizardPagePrivate : public KMyMoneyWizardPagePrivate { - Q_OBJECT public: - /** - * Constructor - */ - explicit KMyMoneyWizardPagePrivate(QObject* parent); - - void emitCompleteStateChanged(void); + WizardPagePrivate(QObject* parent) : + KMyMoneyWizardPagePrivate(parent) + { + } -signals: - void completeStateChanged(void); + T* m_wizard; + KMyMoneyWizard* m_wizardBase; }; #endif diff --git a/kmymoney/wizards/wizardpages/CMakeLists.txt b/kmymoney/wizards/wizardpages/CMakeLists.txt index e2b95b790..98c99e558 100644 --- a/kmymoney/wizards/wizardpages/CMakeLists.txt +++ b/kmymoney/wizards/wizardpages/CMakeLists.txt @@ -1,22 +1,22 @@ project(Wizardpages) ########### next target ############### set(libwizardpages_a_SOURCES accounts.cpp currency.cpp userinfo.cpp ) set (libwizardpages_a_UI - accountsdecl.ui currencydecl.ui userinfodecl.ui + accounts.ui currency.ui userinfo.ui ) ki18n_wrap_ui(wizardpages_ui_srcs ${libwizardpages_a_UI} ) # in order to use add_dependencies, we need to add this custom target # for all generated header files. add_custom_target(generate_wizardpages_ui_srcs DEPENDS ${wizardpages_ui_srcs}) add_library(wizardpages STATIC ${libwizardpages_a_SOURCES} ${wizardpages_ui_srcs}) # TODO: fix widgets library public dependencies -target_link_libraries(wizardpages KF5::KIOWidgets KF5::TextWidgets KF5::Completion Alkimia::alkimia Qt5::Sql Qt5::Xml) +target_link_libraries(wizardpages KF5::KIOWidgets KF5::TextWidgets Alkimia::alkimia Qt5::Xml) diff --git a/kmymoney/wizards/wizardpages/accounts.cpp b/kmymoney/wizards/wizardpages/accounts.cpp index d823e22c4..39cb68207 100644 --- a/kmymoney/wizards/wizardpages/accounts.cpp +++ b/kmymoney/wizards/wizardpages/accounts.cpp @@ -1,32 +1,41 @@ /*************************************************************************** accounts.cpp ------------------- begin : Fri Jun 1 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "accounts.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes +#include "ui_accounts.h" + Accounts::Accounts(QWidget* parent) : - AccountsDecl(parent) + QWidget(parent), + ui(new Ui::Accounts) +{ + ui->setupUi(this); +} + +Accounts::~Accounts() { + delete ui; } diff --git a/kmymoney/wizards/wizardpages/accounts.h b/kmymoney/wizards/wizardpages/accounts.h index 574dd0f1e..fe78e5604 100644 --- a/kmymoney/wizards/wizardpages/accounts.h +++ b/kmymoney/wizards/wizardpages/accounts.h @@ -1,51 +1,48 @@ /*************************************************************************** accounts.h ------------------- begin : Fri Jun 1 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef ACCOUNTS_H #define ACCOUNTS_H // ---------------------------------------------------------------------------- // QT Includes +#include + // ---------------------------------------------------------------------------- // Project Includes -#include "ui_accountsdecl.h" +namespace Ui { class Accounts; } /** * @author Thomas Baumgart */ -class AccountsDecl : public QWidget, public Ui::AccountsDecl -{ -public: - AccountsDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; - -class Accounts : public AccountsDecl +class Accounts : public QWidget { Q_OBJECT + Q_DISABLE_COPY(Accounts) + public: - Accounts(QWidget* parent = 0); + explicit Accounts(QWidget *parent = nullptr); + virtual ~Accounts(); -private: + Ui::Accounts *ui; }; #endif diff --git a/kmymoney/wizards/wizardpages/accountsdecl.ui b/kmymoney/wizards/wizardpages/accounts.ui similarity index 95% rename from kmymoney/wizards/wizardpages/accountsdecl.ui rename to kmymoney/wizards/wizardpages/accounts.ui index ec4463a66..3bc6b5bd4 100644 --- a/kmymoney/wizards/wizardpages/accountsdecl.ui +++ b/kmymoney/wizards/wizardpages/accounts.ui @@ -1,49 +1,49 @@ - AccountsDecl - + Accounts + 0 0 600 550 Select groups of accounts that correspond to the ways that you will use KMyMoney. Each group you select will cause several accounts and categories to be created. Select the groups that are relevant to you. You can always create additional accounts manually later. true 20 20 QSizePolicy::Expanding Qt::Vertical diff --git a/kmymoney/wizards/wizardpages/currency.cpp b/kmymoney/wizards/wizardpages/currency.cpp index 5bcaf7fff..dcc50b65c 100644 --- a/kmymoney/wizards/wizardpages/currency.cpp +++ b/kmymoney/wizards/wizardpages/currency.cpp @@ -1,70 +1,77 @@ /*************************************************************************** userinfo.cpp ------------------- begin : Fri Jun 1 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "currency.h" // ---------------------------------------------------------------------------- // QT Includes #include #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes +#include "ui_currency.h" #include "mymoneysecurity.h" Currency::Currency(QWidget* parent) : - CurrencyDecl(parent) + QWidget(parent), + ui(new Ui::Currency) { - m_currencyList->setAllColumnsShowFocus(true); - m_currencyList->setColumnWidth(0, size().width()*6 / 10); + ui->setupUi(this); + ui->m_currencyList->setAllColumnsShowFocus(true); + ui->m_currencyList->setColumnWidth(0, size().width()*6 / 10); +} + +Currency::~Currency() +{ + delete ui; } QTreeWidgetItem* Currency::insertCurrency(const MyMoneySecurity& sec) { QStringList item = QStringList(); item.append(sec.name()); item.append(QString(sec.id())); item.append(sec.tradingSymbol()); - return new QTreeWidgetItem(m_currencyList, item); + return new QTreeWidgetItem(ui->m_currencyList, item); } void Currency::selectCurrency(const MyMoneySecurity& sec) { - QList selectedItems = m_currencyList->findItems(sec.id(), Qt::MatchExactly, 1); + QList selectedItems = ui->m_currencyList->findItems(sec.id(), Qt::MatchExactly, 1); QList::iterator itemIt = selectedItems.begin(); while (itemIt != selectedItems.end()) { (*itemIt)->setSelected(true); - m_currencyList->scrollToItem(*itemIt); + ui->m_currencyList->scrollToItem(*itemIt); } } - QString Currency::selectedCurrency() const { QString id; - if (m_currencyList->selectedItems().size() > 0) { - id = m_currencyList->selectedItems().at(0)->text(1); + if (ui->m_currencyList->selectedItems().size() > 0) { + id = ui->m_currencyList->selectedItems().at(0)->text(1); } return id; } diff --git a/kmymoney/wizards/wizardpages/currency.h b/kmymoney/wizards/wizardpages/currency.h index af1bb2ae6..ebde40e34 100644 --- a/kmymoney/wizards/wizardpages/currency.h +++ b/kmymoney/wizards/wizardpages/currency.h @@ -1,53 +1,54 @@ /*************************************************************************** currency.h ------------------- begin : Fri Jun 1 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CURRENCY_H #define CURRENCY_H // ---------------------------------------------------------------------------- // QT Includes + #include // ---------------------------------------------------------------------------- // Project Includes -#include "ui_currencydecl.h" - +class QTreeWidgetItem; class MyMoneySecurity; +namespace Ui { class Currency; } + /** * @author Thomas Baumgart */ -class CurrencyDecl : public QWidget, public Ui::CurrencyDecl -{ -public: - CurrencyDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; -class Currency : public CurrencyDecl +class Currency : public QWidget { Q_OBJECT + Q_DISABLE_COPY(Currency) + public: - Currency(QWidget* parent = 0); + explicit Currency(QWidget *parent = nullptr); + virtual ~Currency(); + QTreeWidgetItem* insertCurrency(const MyMoneySecurity& sec); void selectCurrency(const MyMoneySecurity& sec); QString selectedCurrency() const; + + Ui::Currency *ui; }; #endif diff --git a/kmymoney/wizards/wizardpages/currencydecl.ui b/kmymoney/wizards/wizardpages/currency.ui similarity index 94% rename from kmymoney/wizards/wizardpages/currencydecl.ui rename to kmymoney/wizards/wizardpages/currency.ui index 43e4828a6..3fa2a15a6 100644 --- a/kmymoney/wizards/wizardpages/currencydecl.ui +++ b/kmymoney/wizards/wizardpages/currency.ui @@ -1,51 +1,51 @@ - CurrencyDecl - + Currency + 0 0 383 494 KMyMoney supports multiple currencies, nevertheless one of them will be used as your base currency. The base currency is used as default for new accounts and reports. Please select the base currency from the following list. true false Name ISO Code Symbol diff --git a/kmymoney/wizards/wizardpages/userinfo.cpp b/kmymoney/wizards/wizardpages/userinfo.cpp index 473078b58..8fe218483 100644 --- a/kmymoney/wizards/wizardpages/userinfo.cpp +++ b/kmymoney/wizards/wizardpages/userinfo.cpp @@ -1,49 +1,56 @@ /*************************************************************************** userinfo.cpp ------------------- begin : Fri Jun 1 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "userinfo.h" // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes +#include "ui_userinfo.h" #include "mymoneypayee.h" - UserInfo::UserInfo(QWidget* parent) : - UserInfoDecl(parent) + QWidget(parent), + ui(new Ui::UserInfo) +{ + ui->setupUi(this); + ui->m_userNameEdit->setFocus(); +} + +UserInfo::~UserInfo() { - m_userNameEdit->setFocus(); + delete ui; } MyMoneyPayee UserInfo::user() const { MyMoneyPayee user; - user.setName(m_userNameEdit->text()); - user.setAddress(m_streetEdit->text()); - user.setCity(m_townEdit->text()); - user.setState(m_countyEdit->text()); - user.setPostcode(m_postcodeEdit->text()); - user.setTelephone(m_telephoneEdit->text()); - user.setEmail(m_emailEdit->text()); + user.setName(ui->m_userNameEdit->text()); + user.setAddress(ui->m_streetEdit->text()); + user.setCity(ui->m_townEdit->text()); + user.setState(ui->m_countyEdit->text()); + user.setPostcode(ui->m_postcodeEdit->text()); + user.setTelephone(ui->m_telephoneEdit->text()); + user.setEmail(ui->m_emailEdit->text()); return user; } diff --git a/kmymoney/wizards/wizardpages/userinfo.h b/kmymoney/wizards/wizardpages/userinfo.h index 216c153a9..a2541bfc3 100644 --- a/kmymoney/wizards/wizardpages/userinfo.h +++ b/kmymoney/wizards/wizardpages/userinfo.h @@ -1,52 +1,51 @@ /*************************************************************************** userinfo.h ------------------- begin : Fri Jun 1 2007 copyright : (C) 2007 Thomas Baumgart email : Thomas Baumgart ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef USERINFO_H #define USERINFO_H // ---------------------------------------------------------------------------- // QT Includes +#include + // ---------------------------------------------------------------------------- // Project Includes -#include "ui_userinfodecl.h" +namespace Ui { class UserInfo; } + class MyMoneyPayee; /** * @author Thomas Baumgart */ -class UserInfoDecl : public QWidget, public Ui::UserInfoDecl -{ -public: - UserInfoDecl(QWidget *parent) : QWidget(parent) { - setupUi(this); - } -}; -class UserInfo : public UserInfoDecl +class UserInfo : public QWidget { Q_OBJECT + Q_DISABLE_COPY(UserInfo) + public: - UserInfo(QWidget* parent = 0); - MyMoneyPayee user() const; + explicit UserInfo(QWidget *parent = nullptr); + virtual ~UserInfo(); -private: + MyMoneyPayee user() const; + Ui::UserInfo *ui; }; #endif diff --git a/kmymoney/wizards/wizardpages/userinfodecl.ui b/kmymoney/wizards/wizardpages/userinfo.ui similarity index 98% rename from kmymoney/wizards/wizardpages/userinfodecl.ui rename to kmymoney/wizards/wizardpages/userinfo.ui index 30ffb49ff..282ba9fbc 100644 --- a/kmymoney/wizards/wizardpages/userinfodecl.ui +++ b/kmymoney/wizards/wizardpages/userinfo.ui @@ -1,215 +1,215 @@ - UserInfoDecl - + UserInfo + 0 0 603 374 Qt::NoFocus <p>Use the fields below to enter some information about yourself.</p> <p>All information is optional and only used to personalize your KMyMoney file.</p> true 100 0 Town: false 100 0 County/State: false 100 0 Street: false 100 0 Email: false 100 0 Telephone: false Your name: false Load from Addressbook 305 21 QSizePolicy::Expanding Qt::Horizontal 20 16 QSizePolicy::Expanding Qt::Vertical 100 0 Postal Code: false m_userNameEdit m_streetEdit m_townEdit m_countyEdit m_postcodeEdit m_telephoneEdit m_emailEdit m_loadAddressButton