diff --git a/kmymoney/main.cpp b/kmymoney/main.cpp index 1450c6872..f3bb0e7d7 100644 --- a/kmymoney/main.cpp +++ b/kmymoney/main.cpp @@ -1,366 +1,366 @@ /*************************************************************************** main.cpp ------------------- copyright : (C) 2001 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. * * * ***************************************************************************/ #include #include // ---------------------------------------------------------------------------- // QT Includes #include #include #include #include #include #include #ifdef KMM_DBUS #include #include #include #endif // ---------------------------------------------------------------------------- // KDE Includes #include #include #include #include // ---------------------------------------------------------------------------- // Project Includes #include "mymoney/mymoneyfile.h" #include "kmymoney.h" #include "kstartuplogo.h" #include "kcreditswindow.h" #include "kmymoneyutils.h" #include "kmymoneysettings.h" #include "misc/webconnect.h" #include "platformtools.h" #ifdef KMM_DEBUG #include "mymoneyutils.h" #include "mymoneytracer.h" #endif bool timersOn = false; KMyMoneyApp* kmymoney; static int runKMyMoney(QApplication& a, std::unique_ptr splash, const QUrl & file, bool noFile); static void migrateConfigFiles(); int main(int argc, char *argv[]) { /** * Create application first */ QApplication app(argc, argv); KLocalizedString::setApplicationDomain("kmymoney"); migrateConfigFiles(); /** * construct and register about data */ KAboutData aboutData(QStringLiteral("kmymoney"), i18n("KMyMoney"), QStringLiteral(VERSION)); aboutData.setOrganizationDomain("kde.org"); KAboutData::setApplicationData(aboutData); QStringList fileUrls; bool isNoCatchOption = false; bool isNoFileOption = false; #ifdef KMM_DEBUG bool isDumpActionsOption = false; #endif if (argc != 0) { /** * Create command line parser and feed it with known options */ QCommandLineParser parser; aboutData.setupCommandLine(&parser); // language // const QCommandLineOption langOption(QStringLiteral("lang"), i18n("language to be used")); // parser.addOption(langOption); // no file const QCommandLineOption noFileOption(QStringLiteral("n"), i18n("do not open last used file")); parser.addOption(noFileOption); // timers const QCommandLineOption timersOption(QStringLiteral("timers"), i18n("enable performance timers")); parser.addOption(timersOption); // no catch const QCommandLineOption noCatchOption(QStringLiteral("nocatch"), i18n("do not globally catch uncaught exceptions")); parser.addOption(noCatchOption); #ifdef KMM_DEBUG // The following options are only available when compiled in debug mode // trace const QCommandLineOption traceOption(QStringLiteral("trace"), i18n("turn on program traces")); parser.addOption(traceOption); // dump actions const QCommandLineOption dumpActionsOption(QStringLiteral("dump-actions"), i18n("dump the names of all defined QAction objects to stdout and quit")); parser.addOption(dumpActionsOption); #endif // INSERT YOUR COMMANDLINE OPTIONS HERE // url to open parser.addPositionalArgument(QStringLiteral("url"), i18n("file to open")); /** * do the command line parsing */ parser.parse(QApplication::arguments()); bool ishelpSet = parser.isSet(QStringLiteral("help")); if (ishelpSet || parser.isSet(QStringLiteral("author")) || parser.isSet(QStringLiteral("license"))) { aboutData = initializeCreditsData(); if (ishelpSet) parser.showHelp(); } if (parser.isSet(QStringLiteral("version"))) parser.showVersion(); /** * handle standard options */ aboutData.processCommandLine(&parser); #ifdef KMM_DEBUG if (parser.isSet(traceOption)) MyMoneyTracer::on(); timersOn = parser.isSet(timersOption); isDumpActionsOption = parser.isSet(dumpActionsOption); #endif isNoCatchOption = parser.isSet(noCatchOption); isNoFileOption = parser.isSet(noFileOption); fileUrls = parser.positionalArguments(); } // create the singletons before we start memory checking // to avoid false error reports MyMoneyFile::instance(); KMyMoneyUtils::checkConstants(); // show startup logo std::unique_ptr splash(KMyMoneySettings::showSplash() ? createStartupLogo() : nullptr); app.processEvents(); // setup the MyMoneyMoney locale settings according to the KDE settings MyMoneyMoney::setThousandSeparator(QLocale().groupSeparator()); MyMoneyMoney::setDecimalSeparator(QLocale().decimalPoint()); // TODO: port to kf5 (negative numbers in parens) //MyMoneyMoney::setNegativeMonetarySignPosition(static_cast(KLocale::global()->negativeMonetarySignPosition())); //MyMoneyMoney::setPositiveMonetarySignPosition(static_cast(KLocale::global()->positiveMonetarySignPosition())); MyMoneyMoney::setNegativePrefixCurrencySymbol(platformTools::currencySymbolPosition(true) < platformTools::AfterQuantityMoney); MyMoneyMoney::setPositivePrefixCurrencySymbol(platformTools::currencySymbolPosition(false) < platformTools::AfterQuantityMoney); // QString language = parser.value(langOption); // if (!language.isEmpty()) { //if (!KLocale::global()->setLanguage(QStringList() << language)) { // qWarning("Unable to select language '%s'. This has one of two reasons:\n\ta) the standard KDE message catalog is not installed\n\tb) the KMyMoney message catalog is not installed", qPrintable(language)); //} // } kmymoney = new KMyMoneyApp(); #ifdef KMM_DEBUG if (isDumpActionsOption) { kmymoney->dumpActions(); // Before we delete the application, we make sure that we destroy all // widgets by running the event loop for some time to catch all those // widgets that are requested to be destroyed using the deleteLater() method. //QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput, 10); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 10); delete kmymoney; exit(0); } #endif QString fname; // in case a filename is provided we need to check if it is a local // file. In case the name does not start with "file://" or "./" or "/" // we need to prepend "./" to fake a relative filename. Otherwiese, QUrl prepends // "http://" and uses the full path which will not work. // // The handling might be different on other OSes if (!fileUrls.isEmpty()) { fname = fileUrls.front(); QFileInfo fi(fname); if (fi.isFile() && !fname.startsWith(QLatin1String("file://")) && !fname.startsWith(QLatin1String("./")) && !fname.startsWith(QLatin1String("/"))) { fname.prepend(QLatin1String("./")); } } const QUrl url = QUrl::fromUserInput(fname, QLatin1String("."), QUrl::AssumeLocalFile); int rc = 0; if (isNoCatchOption) { qDebug("Running w/o global try/catch block"); rc = runKMyMoney(app, std::move(splash), url, isNoFileOption); } else { try { rc = runKMyMoney(app, std::move(splash), url, isNoFileOption); } catch (const MyMoneyException &e) { KMessageBox::detailedError(0, i18n("Uncaught error. Please report the details to the developers"), i18n("%1 in file %2 line %3", e.what(), e.file(), e.line())); throw e; } } return rc; } int runKMyMoney(QApplication& a, std::unique_ptr splash, const QUrl & file, bool noFile) { bool instantQuit = false; /** * enable high dpi icons */ a.setAttribute(Qt::AA_UseHighDpiPixmaps); if (kmymoney->webConnect()->isClient()) { // If the user launches a second copy of the app and includes a file to // open, they are probably attempting a "WebConnect" session. In this case, // we'll check to make sure it's an importable file that's passed in, and if so, we'll // notify the primary instance of the file and kill ourselves. if (file.isValid()) { if (kmymoney->isImportableFile(file)) { instantQuit = true; kmymoney->webConnect()->loadFile(file); } } else if (KMessageBox::questionYesNo(0, i18n("Another instance of KMyMoney is already running. Do you want to quit?")) == KMessageBox::Yes) { instantQuit = true; } } kmymoney->centralWidget()->setEnabled(false); // force complete paint of widgets qApp->processEvents(); if (!instantQuit) { QString importfile; QUrl url; // make sure, we take the file provided on the command // line before we go and open the last one used if (file.isValid()) { // Check to see if this is an importable file, as opposed to a loadable // file. If it is importable, what we really want to do is load the // last used file anyway and then immediately import this file. This // implements a "web connect" session where there is not already an // instance of the program running. if (kmymoney->isImportableFile(file)) { importfile = file.path(); url = QUrl::fromUserInput(kmymoney->readLastUsedFile()); } else { url = file; } } else { url = QUrl::fromUserInput(kmymoney->readLastUsedFile()); } KTipDialog::showTip(kmymoney, QString(), false); if (url.isValid() && !noFile) { kmymoney->slotFileOpenRecent(url); } else if (KMyMoneySettings::firstTimeRun()) { kmymoney->slotFileNew(); } KMyMoneySettings::setFirstTimeRun(false); if (!importfile.isEmpty()) kmymoney->webConnect(importfile, QByteArray()); } else { // the instantQuit flag is set, so we force the app to quit right away kmymoney->slotFileQuit(); } kmymoney->updateCaption(); kmymoney->centralWidget()->setEnabled(true); kmymoney->show(); splash.reset(); - const int rc = a.exec(); + const int rc = a.exec(); //krazy:exclude=crashy return rc; } static void migrateConfigFiles() { const QString sMainConfigName(QStringLiteral("kmymoneyrc")); const QString sMainConfigSubdirectory(QStringLiteral("kmymoney/")); // all KMM config files should be in ~/.config/kmymoney/ const QString sMainConfigPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/') + sMainConfigSubdirectory; if (!QFile::exists(sMainConfigPath + sMainConfigName)) { // if main config file doesn't exist, then it's first run // it could be migration from KDE4 to KF5 so prepare list of configuration files to migrate QStringList sConfigNames { sMainConfigName, QStringLiteral("csvimporterrc"), QStringLiteral("printcheckpluginrc"), QStringLiteral("icalendarexportpluginrc"), QStringLiteral("kbankingrc"), }; // Copy KDE 4 config files to the KF5 location Kdelibs4ConfigMigrator migrator(QStringLiteral("kmymoney")); migrator.setConfigFiles(sConfigNames); migrator.setUiFiles(QStringList{QStringLiteral("kmymoneyui.rc")}); migrator.migrate(); QFileInfo fileInfo(sMainConfigPath + sMainConfigName); QDir().mkpath(fileInfo.absolutePath()); const QString sOldMainConfigPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QLatin1Char('/'); // some files have changed their names during switch to KF5, so prepare map for name replacements QMap configNamesChange { {QStringLiteral("printcheckpluginrc"), QStringLiteral("checkprintingrc")}, {QStringLiteral("icalendarexportpluginrc"), QStringLiteral("icalendarexporterrc")} }; for (const auto& sConfigName : sConfigNames) { const auto sOldConfigFilename = sOldMainConfigPath + sConfigName; const auto sNewConfigFilename = sMainConfigPath + configNamesChange.value(sConfigName, sConfigName); if (QFile::exists(sOldConfigFilename)) { if (QFile::copy(sOldConfigFilename, sNewConfigFilename)) QFile::remove(sOldConfigFilename); } } } KConfig::setMainConfigName(sMainConfigSubdirectory + sMainConfigName); // otherwise it would be ~/.config/kmymoneyrc and not ~/.config/kmymoney/kmymoneyrc } diff --git a/kmymoney/plugins/weboob/interface/weboobinterface.cpp b/kmymoney/plugins/weboob/interface/weboobinterface.cpp index 7e846eebe..4fcdd8cd3 100644 --- a/kmymoney/plugins/weboob/interface/weboobinterface.cpp +++ b/kmymoney/plugins/weboob/interface/weboobinterface.cpp @@ -1,243 +1,243 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014-2015 Romain Bignon * Copyright (C) 2014-2015 Florent Fourcot * (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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include #include "weboobinterface.h" +#include // ---------------------------------------------------------------------------- // QT Includes #include #include #include #include #include // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes #include "../weboobexc.h" WeboobInterface::WeboobInterface() : m_weboobInterface(nullptr) { const auto fileInfo = QFileInfo(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmymoney/weboob/kmymoneyweboob.py")); // begin of a hack (read more on https://bugs.kde.org/show_bug.cgi?id=335965) auto pythonLib = new QLibrary(); pythonLib->setLoadHints(QLibrary::ExportExternalSymbolsHint); pythonLib->setFileName(LIB_PYTHON); pythonLib->load(); // end of a hack Py_Initialize(); auto script = QString::fromLatin1("import sys\n" "sys.path.append('%1')\n").arg(fileInfo.absolutePath()); auto ba = script.toLocal8Bit(); const char *cscript = ba.data(); PyRun_SimpleString(cscript); ba = fileInfo.baseName().toLocal8Bit(); const char *sBaseName = ba.data(); auto pyName = PyString_FromString(sBaseName); m_weboobInterface = PyImport_Import(pyName); // this will be nullptr if no hack Py_DECREF(pyName); } WeboobInterface::~WeboobInterface() { if (m_weboobInterface) Py_DECREF(m_weboobInterface); if (Py_IsInitialized()) Py_Finalize(); } PyObject* WeboobInterface::execute(QString method, QVariantList args) { QMutex mutex; QMutexLocker locker(&mutex); PyObject* retVal = nullptr; auto ba = method.toLocal8Bit(); const char *cmethod = ba.data(); auto pyFunc = PyObject_GetAttrString(m_weboobInterface, cmethod); if (pyFunc && PyCallable_Check(pyFunc)) { PyObject* pArgs = nullptr; if (!args.isEmpty()) { pArgs = PyTuple_New(args.size()); for (auto i = 0; i < args.size(); ++i) { ba = args.at(i).toString().toLocal8Bit(); const char *carg = ba.data(); auto argValue = PyString_FromString(carg); if (!argValue) { Py_DECREF(pArgs); fprintf(stderr, "Cannot convert argument: %s\n", carg); return retVal; } PyTuple_SetItem(pArgs, i, argValue); } } retVal = PyObject_CallObject(pyFunc, pArgs); Py_XDECREF(pArgs); if (!retVal) { if (PyErr_Occurred()) { PyObject *pyType, *pyValue, *pyTraceback; PyErr_Fetch(&pyType, &pyValue, &pyTraceback); PyErr_NormalizeException(&pyType, &pyValue, &pyTraceback); Py_XDECREF(pyType); Py_XDECREF(pyTraceback); if (pyValue) { auto pyRepr = PyObject_Repr(pyValue); QString sError = PyString_AsString(pyRepr); if (sError.contains(QLatin1String("BrowserIncorrectPassword()"))) throw WeboobException(ExceptionCode::BrowserIncorrectPassword); Py_DECREF(pyRepr); Py_DECREF(pyValue); } } } } Py_XDECREF(pyFunc); return retVal; } QList WeboobInterface::getBackends() { QList backendsList; if(!m_weboobInterface) return backendsList; auto pValue = execute("get_backends", QVariantList()); if (pValue) { PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(pValue, &pos, &key, &value)) { WeboobInterface::Backend backend; backend.name = PyString_AsString(key); backend.module = extractDictStringValue(value, "module"); backendsList.append(backend); } Py_DECREF(pValue); } return backendsList; } QList WeboobInterface::getAccounts(QString backend) { QList accountsList; if(!m_weboobInterface) return accountsList; auto pValue = execute("get_accounts", QVariantList{backend}); if (pValue) { PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(pValue, &pos, &key, &value)) { WeboobInterface::Account account; account.id = PyString_AsString(key); account.name = extractDictStringValue(value, "name"); account.balance = MyMoneyMoney(extractDictLongValue(value, "balance"), 100); account.type = (WeboobInterface::Account::type_t)extractDictLongValue(value, "type"); accountsList.append(account); } Py_DECREF(pValue); } return accountsList; } WeboobInterface::Account WeboobInterface::getAccount(QString backend, QString accid, QString max) { WeboobInterface::Account acc; if(!m_weboobInterface) return acc; auto retVal = execute("get_transactions", QVariantList{backend, accid, max}); if (retVal) { acc.id = extractDictStringValue(retVal, "id"); acc.name = extractDictStringValue(retVal, "name"); acc.balance = MyMoneyMoney(extractDictLongValue(retVal, "balance"), 100); acc.type = (WeboobInterface::Account::type_t)extractDictLongValue(retVal, "type"); auto key = PyString_FromString("transactions"); auto val = PyDict_GetItem(retVal, key); if (val) { auto sizeVal = PyList_Size(val); for (auto i = 0 ; i < sizeVal; ++i) { auto val2 = PyList_GetItem(val, i); if (val2) { PyObject *key3, *val3; Py_ssize_t pos3 = 0; while (PyDict_Next(val2, &pos3, &key3, &val3)) { WeboobInterface::Transaction tr; tr.id = extractDictStringValue(val3, "id"); tr.date = QDate::fromString(extractDictStringValue(val3, "date"), "yyyy-MM-dd"); tr.rdate = QDate::fromString(extractDictStringValue(val3, "rdate"), "yyyy-MM-dd"); tr.type = (WeboobInterface::Transaction::type_t)extractDictLongValue(val3, "type");; tr.raw = extractDictStringValue(val3, "raw"); tr.category = extractDictStringValue(val3, "category"); tr.label = extractDictStringValue(val3, "label"); tr.amount = MyMoneyMoney(extractDictLongValue(val3, "amount"), 100); acc.transactions.append(tr); } } } } Py_DECREF(key); Py_DECREF(retVal); } return acc; } QString WeboobInterface::extractDictStringValue(PyObject* pyContainer, const char* szKey) { QString sVal; auto pyKey = PyString_FromString(szKey); auto pyVal = PyDict_GetItem(pyContainer, pyKey); if (pyVal) sVal = PyString_AsString(pyVal); Py_DECREF(pyKey); return sVal; } long WeboobInterface::extractDictLongValue(PyObject* pyContainer, const char* szKey) { long sVal = 0; auto pyKey = PyString_FromString(szKey); auto pyVal = PyDict_GetItem(pyContainer, pyKey); if (pyVal) sVal = PyInt_AsLong(pyVal); Py_DECREF(pyKey); return sVal; } diff --git a/kmymoney/plugins/weboob/weboob.cpp b/kmymoney/plugins/weboob/weboob.cpp index e12133ed4..c6a89e6ca 100644 --- a/kmymoney/plugins/weboob/weboob.cpp +++ b/kmymoney/plugins/weboob/weboob.cpp @@ -1,221 +1,223 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014-2015 Romain Bignon * Copyright (C) 2014-2015 Florent Fourcot * Copyright (C) 2016 Christian David * (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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "weboob.h" #include // ---------------------------------------------------------------------------- // QT Includes #include #include #include // ---------------------------------------------------------------------------- // KDE Includes #include #include // ---------------------------------------------------------------------------- // Project Includes #include "mapaccountwizard.h" #include "accountsettings.h" #include "weboobinterface.h" #include "mymoneyaccount.h" #include "mymoneykeyvaluecontainer.h" #include "mymoneystatement.h" #include "statementinterface.h" class WeboobPrivate { public: WeboobPrivate() { } ~WeboobPrivate() { } WeboobInterface weboob; QFutureWatcher watcher; std::unique_ptr progress; AccountSettings* accountSettings; }; Weboob::Weboob(QObject *parent, const QVariantList &args) : KMyMoneyPlugin::Plugin(parent, "weboob"), d_ptr(new WeboobPrivate) { Q_UNUSED(args) setComponentName("weboob", i18n("Weboob")); setXMLFile("weboob.rc"); qDebug("Plugins: weboob loaded"); } Weboob::~Weboob() { Q_D(Weboob); delete d; qDebug("Plugins: weboob unloaded"); } void Weboob::plug() { Q_D(Weboob); connect(&d->watcher, &QFutureWatcher::finished, this, &Weboob::gotAccount); } void Weboob::unplug() { Q_D(Weboob); disconnect(&d->watcher, &QFutureWatcher::finished, this, &Weboob::gotAccount); } void Weboob::protocols(QStringList& protocolList) const { protocolList << "weboob"; } QWidget* Weboob::accountConfigTab(const MyMoneyAccount& account, QString& tabName) { Q_D(Weboob); const MyMoneyKeyValueContainer& kvp = account.onlineBankingSettings(); tabName = i18n("Weboob configuration"); d->accountSettings = new AccountSettings(account, 0); d->accountSettings->loadUi(kvp); return d->accountSettings; } MyMoneyKeyValueContainer Weboob::onlineBankingSettings(const MyMoneyKeyValueContainer& current) { Q_D(Weboob); MyMoneyKeyValueContainer kvp(current); kvp["provider"] = objectName().toLower(); if (d->accountSettings) { d->accountSettings->loadKvp(kvp); } return kvp; } bool Weboob::mapAccount(const MyMoneyAccount& acc, MyMoneyKeyValueContainer& onlineBankingSettings) { Q_D(Weboob); Q_UNUSED(acc); - MapAccountWizard w(nullptr, &d->weboob); - if (w.exec() == QDialog::Accepted) { - onlineBankingSettings.setValue("wb-backend", w.currentBackend()); - onlineBankingSettings.setValue("wb-id", w.currentAccount()); + bool rc = false; + QPointer w = new MapAccountWizard(nullptr, &d->weboob); + if (w->exec() == QDialog::Accepted && w != nullptr) { + onlineBankingSettings.setValue("wb-backend", w->currentBackend()); + onlineBankingSettings.setValue("wb-id", w->currentAccount()); onlineBankingSettings.setValue("wb-max", "0"); - return true; + rc = true; } - return false; + delete w; + return rc; } bool Weboob::updateAccount(const MyMoneyAccount& kacc, bool moreAccounts) { Q_D(Weboob); Q_UNUSED(moreAccounts); QString bname = kacc.onlineBankingSettings().value("wb-backend"); QString id = kacc.onlineBankingSettings().value("wb-id"); QString max = kacc.onlineBankingSettings().value("wb-max"); d->progress = std::make_unique(nullptr); d->progress->setWindowTitle(i18n("Connecting to bank...")); d->progress->setLabelText(i18n("Retrieving transactions...")); d->progress->setModal(true); d->progress->setCancelButton(nullptr); d->progress->setMinimum(0); d->progress->setMaximum(0); d->progress->setMinimumDuration(0); QFuture future = QtConcurrent::run(&d->weboob, &WeboobInterface::getAccount, bname, id, max); d->watcher.setFuture(future); d->progress->exec(); d->progress.reset(); return true; } void Weboob::gotAccount() { Q_D(Weboob); WeboobInterface::Account acc = d->watcher.result(); MyMoneyAccount kacc = statementInterface()->account("wb-id", acc.id); MyMoneyStatement ks; ks.m_accountId = kacc.id(); ks.m_strAccountName = acc.name; ks.m_closingBalance = acc.balance; if (acc.transactions.length() > 0) ks.m_dateEnd = acc.transactions.front().date; #if 0 switch (acc.type) { case Weboob::Account::TYPE_CHECKING: ks.m_eType = MyMoneyStatement::etCheckings; break; case Weboob::Account::TYPE_SAVINGS: ks.m_eType = MyMoneyStatement::etSavings; break; case Weboob::Account::TYPE_MARKET: ks.m_eType = MyMoneyStatement::etInvestment; break; case Weboob::Account::TYPE_DEPOSIT: case Weboob::Account::TYPE_LOAN: case Weboob::Account::TYPE_JOINT: case Weboob::Account::TYPE_UNKNOWN: break; } #endif for (QListIterator it(acc.transactions); it.hasNext();) { WeboobInterface::Transaction tr = it.next(); MyMoneyStatement::Transaction kt; kt.m_strBankID = QLatin1String("ID ") + tr.id; kt.m_datePosted = tr.rdate; kt.m_amount = tr.amount; kt.m_strMemo = tr.raw; kt.m_strPayee = tr.label; ks.m_listTransactions += kt; } statementInterface()->import(ks); d->progress->hide(); } K_PLUGIN_FACTORY_WITH_JSON(WeboobFactory, "weboob.json", registerPlugin();) #include "weboob.moc"