diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,20 +36,23 @@ include(KDEInstallDirs) include(KDECMakeSettings) include(FeatureSummary) +include(CMakeDependentOption) include(GenerateExportHeader) include(KMyMoneyMacros) set(GPG_ENCRYPTION "no") -set (OPT_KF5_COMPONENTS DocTools Holidays Contacts Akonadi IdentityManagement Activities Kross) +set (OPT_KF5_COMPONENTS DocTools Holidays Contacts Akonadi IdentityManagement Activities) find_package(Gpgmepp) if (Gpgmepp_FOUND) set(GPG_ENCRYPTION "yes") else() set(OPT_KF5_COMPONENTS ${OPT_KF5_COMPONENTS} Gpgmepp) endif() -find_package(Qt5 5.6 REQUIRED COMPONENTS Core DBus Widgets Svg Sql Xml Test PrintSupport) +find_package(Qt5 5.6 REQUIRED + COMPONENTS Core DBus Widgets Svg Sql Xml Test PrintSupport + OPTIONAL_COMPONENTS Concurrent) find_package(KF5 5.2 REQUIRED COMPONENTS Archive CoreAddons Config ConfigWidgets I18n Completion KCMUtils ItemModels ItemViews Service Wallet IconThemes XmlGui TextWidgets Notifications KIO @@ -178,24 +181,23 @@ endif () endif(ENABLE_KBANKING) -# check for optional Weboob support -set(WEBOOB_FOUND "AUTO") -mark_as_advanced(WEBOOB_FOUND) -if(DEFINED ENABLE_WEBOOB) - set(WEBOOB_FOUND OFF) -endif(DEFINED ENABLE_WEBOOB) -option(ENABLE_WEBOOB "Enable weboob plugin" ON) -if(ENABLE_WEBOOB) - if(KF5Kross_FOUND) - set(WEBOOB_FOUND ON) - else(KF5Kross_FOUND) - if(NOT WEBOOB_FOUND STREQUAL "AUTO") - message(FATAL_ERROR "Weboob requirements not met") - endif(NOT WEBOOB_FOUND STREQUAL "AUTO") - set(WEBOOB_FOUND OFF) - set(ENABLE_WEBOOB OFF CACHE BOOL "Enable weboob plugin" FORCE) - endif(KF5Kross_FOUND) -endif(ENABLE_WEBOOB) +set(Python_ADDITIONAL_VERSIONS 2.7 2.6) +find_package(PythonInterp 2.6) +find_package(PythonLibs ${PYTHON_VERSION_STRING}) + +if(PYTHONINTERP_FOUND AND PYTHONLIBS_FOUND) + if(PYTHON_VERSION_MAJOR GREATER_EQUAL 3) + unset(PYTHONLIBS_FOUND) + unset(PYTHONINTERP_FOUND) + message(WARNING "Python 2 required, but Python 3 found.") + else() + include(FindPythonModule) + find_python_module(weboob REQUIRED) + endif() +endif() + +CMAKE_DEPENDENT_OPTION(ENABLE_WEBOOB "Enable Weboob plugin" ON + "PYTHONLIBS_FOUND;PYTHONINTERP_FOUND;PY_WEBOOB;Qt5Concurrent_FOUND" OFF) # check for optional ical support set(LIBICAL_DEFAULT "AUTO") diff --git a/cmake/modules/FindPythonModule.cmake b/cmake/modules/FindPythonModule.cmake new file mode 100644 --- /dev/null +++ b/cmake/modules/FindPythonModule.cmake @@ -0,0 +1,25 @@ +# Find if a Python module is installed +# Found at http://www.cmake.org/pipermail/cmake/2011-January/041666.html +# To use do: find_python_module(PyQt4 REQUIRED) +function(find_python_module module) + string(TOUPPER ${module} module_upper) + if(NOT PY_${module_upper}) + if(ARGC GREATER 1 AND ARGV1 STREQUAL "REQUIRED") + set(${module}_FIND_REQUIRED TRUE) + endif() + # A module's location is usually a directory, but for binary modules + # it's a .so file. + execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" + "import re, ${module}; print(re.compile('/__init__.py.*').sub('',${module}.__file__))" + RESULT_VARIABLE _${module}_status + OUTPUT_VARIABLE _${module}_location + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT _${module}_status) + set(PY_${module_upper} ${_${module}_location} CACHE STRING + "Location of Python module ${module}") + endif(NOT _${module}_status) + endif(NOT PY_${module_upper}) + find_package_handle_standard_args(PY_${module} DEFAULT_MSG PY_${module_upper}) +endfunction(find_python_module) + diff --git a/kmymoney/plugins/CMakeLists.txt b/kmymoney/plugins/CMakeLists.txt --- a/kmymoney/plugins/CMakeLists.txt +++ b/kmymoney/plugins/CMakeLists.txt @@ -23,9 +23,9 @@ add_subdirectory(onlinejobpluginmockup) endif() -if (WEBOOB_FOUND) +if (ENABLE_WEBOOB) add_subdirectory( weboob ) -endif (WEBOOB_FOUND) +endif () ########### next target ############### diff --git a/kmymoney/plugins/weboob/CMakeLists.txt b/kmymoney/plugins/weboob/CMakeLists.txt --- a/kmymoney/plugins/weboob/CMakeLists.txt +++ b/kmymoney/plugins/weboob/CMakeLists.txt @@ -1,35 +1,33 @@ -find_package(Qt5 COMPONENTS REQUIRED Concurrent) - # Use KDE compiler settings to enable C++11 -include(KDECompilerSettings NO_POLICY_SCOPE) +# include(KDECompilerSettings NO_POLICY_SCOPE) # patch the version with the version defined in the build system configure_file(${CMAKE_CURRENT_SOURCE_DIR}/weboob.json.in ${CMAKE_CURRENT_BINARY_DIR}/weboob.json @ONLY) add_subdirectory( dialogs ) +add_subdirectory( interface ) ########### next target ############### set(weboob_PART_SRCS - weboobext.cpp weboob.cpp ) add_library(weboob MODULE ${weboob_PART_SRCS}) -target_link_libraries(weboob +target_link_libraries( + weboob + PRIVATE + weboob_interface weboob_dialogs kmm_mymoney kmm_widgets kmm_plugin - KF5::KrossCore + Qt5::Concurrent ) ########### install files ############### -install(FILES weboob.py - DESTINATION "${DATA_INSTALL_DIR}/weboob") - install(FILES weboob.rc DESTINATION "${KXMLGUI_INSTALL_DIR}/weboob") diff --git a/kmymoney/plugins/weboob/dialogs/CMakeLists.txt b/kmymoney/plugins/weboob/dialogs/CMakeLists.txt --- a/kmymoney/plugins/weboob/dialogs/CMakeLists.txt +++ b/kmymoney/plugins/weboob/dialogs/CMakeLists.txt @@ -2,16 +2,24 @@ ########### next target ############### set(weboob_dialogs_la_SOURCES - mapaccount.cpp - webaccount.cpp + mapaccountwizard.cpp + accountsettings.cpp ) set(weboob_dialogs_UI - mapaccount.ui - webaccount.ui + mapaccountwizard.ui + accountsettings.ui ) ki18n_wrap_ui(weboob_dialogs_la_SOURCES ${weboob_dialogs_UI}) add_library(weboob_dialogs STATIC ${weboob_dialogs_la_SOURCES}) -target_link_libraries(weboob_dialogs Qt5::Concurrent KF5::KrossCore widgets dialogs) +target_link_libraries ( + weboob_dialogs + PRIVATE + Qt5::Concurrent + Qt5::Widgets + KF5::WidgetsAddons + KF5::I18n + Alkimia::alkimia + ) diff --git a/kmymoney/plugins/weboob/dialogs/webaccount.h b/kmymoney/plugins/weboob/dialogs/accountsettings.h rename from kmymoney/plugins/weboob/dialogs/webaccount.h rename to kmymoney/plugins/weboob/dialogs/accountsettings.h --- a/kmymoney/plugins/weboob/dialogs/webaccount.h +++ b/kmymoney/plugins/weboob/dialogs/accountsettings.h @@ -2,7 +2,7 @@ * 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 @@ -17,29 +17,40 @@ * along with this program. If not, see . */ -#ifndef WEBOOB_WEBACCOUNTSETTINGS_H -#define WEBOOB_WEBACCOUNTSETTINGS_H +#ifndef ACCOUNTSETTINGS_H +#define ACCOUNTSETTINGS_H + +// ---------------------------------------------------------------------------- +// QT Includes #include +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + class MyMoneyAccount; class MyMoneyKeyValueContainer; -class WebAccountSettings: public QWidget +class AccountSettingsPrivate; +class AccountSettings: public QWidget { + Q_OBJECT + public: - WebAccountSettings(const MyMoneyAccount& acc, QWidget* parent); - ~WebAccountSettings(); + explicit AccountSettings(const MyMoneyAccount& acc, QWidget* parent); + ~AccountSettings(); void loadUi(const MyMoneyKeyValueContainer& kvp); void loadKvp(MyMoneyKeyValueContainer& kvp); private: - /// \internal d-pointer class. - struct Private; - /// \internal d-pointer instance. - Private* const d; + + Q_DECLARE_PRIVATE(AccountSettings) + AccountSettingsPrivate * const d_ptr; }; -#endif /* WEBOOB_WEBACCOUNTSETTINGS_H */ +#endif diff --git a/kmymoney/plugins/weboob/dialogs/accountsettings.cpp b/kmymoney/plugins/weboob/dialogs/accountsettings.cpp new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/weboob/dialogs/accountsettings.cpp @@ -0,0 +1,79 @@ +/* + * 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 "accountsettings.h" + +// ---------------------------------------------------------------------------- +// QT Includes + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_accountsettings.h" + +#include "mymoneykeyvaluecontainer.h" + +class AccountSettingsPrivate +{ +public: + AccountSettingsPrivate() : + ui(new Ui::AccountSettings) + { + } + + ~AccountSettingsPrivate() + { + delete ui; + } + Ui::AccountSettings *ui; +}; + +AccountSettings::AccountSettings(const MyMoneyAccount& /*acc*/, QWidget* parent) : + QWidget(parent), + d_ptr(new AccountSettingsPrivate) +{ + Q_D(AccountSettings); + d->ui->setupUi(this); +} + +AccountSettings::~AccountSettings() +{ + Q_D(AccountSettings); + delete d; +} + +void AccountSettings::loadUi(const MyMoneyKeyValueContainer& kvp) +{ + Q_D(AccountSettings); + d->ui->id->setText(kvp.value("wb-id")); + d->ui->backend->setText(kvp.value("wb-backend")); + d->ui->max_history->setText(kvp.value("wb-max")); +} + +void AccountSettings::loadKvp(MyMoneyKeyValueContainer& kvp) +{ + Q_D(AccountSettings); + kvp.setValue("wb-id", d->ui->id->text()); + kvp.setValue("wb-backend", d->ui->backend->text()); + kvp.setValue("wb-max", d->ui->max_history->text()); +} diff --git a/kmymoney/plugins/weboob/dialogs/webaccount.ui b/kmymoney/plugins/weboob/dialogs/accountsettings.ui rename from kmymoney/plugins/weboob/dialogs/webaccount.ui rename to kmymoney/plugins/weboob/dialogs/accountsettings.ui --- a/kmymoney/plugins/weboob/dialogs/webaccount.ui +++ b/kmymoney/plugins/weboob/dialogs/accountsettings.ui @@ -1,7 +1,7 @@ - WebAccountSettings - + AccountSettings + 0 diff --git a/kmymoney/plugins/weboob/dialogs/mapaccount.cpp b/kmymoney/plugins/weboob/dialogs/mapaccount.cpp deleted file mode 100644 --- a/kmymoney/plugins/weboob/dialogs/mapaccount.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - * This file is part of KMyMoney, A Personal Finance Manager by KDE - * Copyright (C) 2014-2015 Romain Bignon - * Copyright (C) 2014-2015 Florent Fourcot - * - * 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 "mapaccount.h" - -#include -#include -#include - -#include -#include - -#include "../weboob.h" - -struct WbMapAccountDialog::Private -{ - QFutureWatcher > watcher; - QFutureWatcher > watcher2; - std::unique_ptr progress; -}; - -WbMapAccountDialog::WbMapAccountDialog(QWidget *parent): - QWizard(parent), - d(new Private), - d2(new Private) -{ - setupUi(this); - - checkNextButton(); - connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(checkNextButton())); - connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(newPage(int))); - connect(backendsList, SIGNAL(itemSelectionChanged()), this, SLOT(checkNextButton())); - connect(accountsList, SIGNAL(itemSelectionChanged()), this, SLOT(checkNextButton())); - - connect(&d->watcher, SIGNAL(finished()), this, SLOT(gotAccounts())); - connect(&d2->watcher2, SIGNAL(finished()), this, SLOT(gotBackends())); - - // setup icons - button(QWizard::FinishButton)->setIcon(KStandardGuiItem::ok().icon()); - button(QWizard::CancelButton)->setIcon(KStandardGuiItem::cancel().icon()); - button(QWizard::NextButton)->setIcon(KStandardGuiItem::forward(KStandardGuiItem::UseRTL).icon()); - button(QWizard::BackButton)->setIcon(KStandardGuiItem::back(KStandardGuiItem::UseRTL).icon()); -} - -/** - * @internal Deconstructer stub needed to delete unique_ptrs with type Private - */ -WbMapAccountDialog::~WbMapAccountDialog() -{ -} - -void WbMapAccountDialog::checkNextButton(void) -{ - bool enableButton = false; - switch (currentId()) { - case BACKENDS_PAGE: - enableButton = backendsList->currentItem() != 0 && backendsList->currentItem()->isSelected(); - break; - case ACCOUNTS_PAGE: - enableButton = accountsList->currentItem() != 0 && accountsList->currentItem()->isSelected(); - break; - } - button(QWizard::NextButton)->setEnabled(enableButton); -} - -void WbMapAccountDialog::newPage(int id) -{ - //! @Todo C++14: this should be make_unique - d2->progress = std::unique_ptr(new QProgressDialog(this)); - d2->progress->setModal(true); - d2->progress->setCancelButton(nullptr); - d2->progress->setMinimum(0); - d2->progress->setMaximum(0); - d2->progress->setMinimumDuration(0); - - switch (id) { - case BACKENDS_PAGE: { - backendsList->clear(); - - d2->progress->setWindowTitle(i18n("Loading Weboob backend...")); - d2->progress->setLabelText(i18n("Getting list of backends.")); - - QCoreApplication::processEvents(); - - QFuture > future = QtConcurrent::run(weboob, &WeboobExt::getBackends); - d2->watcher2.setFuture(future); - - break; - } - case ACCOUNTS_PAGE: { - accountsList->clear(); - d2->progress->setWindowTitle(i18n("Connecting to bank...")); - d2->progress->setLabelText(i18n("Getting list of accounts from your bank.")); - - QCoreApplication::processEvents(); - - QFuture > future = QtConcurrent::run(weboob, &WeboobExt::getAccounts, backendsList->currentItem()->text(0)); - d->watcher.setFuture(future); - button(QWizard::BackButton)->setEnabled(false); - accountsList->setEnabled(false); - - break; - } - - default: - // I do not know if this can actually happen. But to be safe: - d2->progress.reset(); - } -} - -void WbMapAccountDialog::gotBackends() -{ - QList backends = d2->watcher2.result(); - - for (QListIterator it(backends); it.hasNext();) { - WeboobExt::Backend backend = it.next(); - QStringList headers; - headers << backend.name << backend.module; - backendsList->addTopLevelItem(new QTreeWidgetItem(headers)); - } - - d2->progress.reset(); -} - -void WbMapAccountDialog::gotAccounts() -{ - QList accounts = d->watcher.result(); - - for (QListIterator it(accounts); it.hasNext();) { - WeboobExt::Account account = it.next(); - QStringList headers; - headers << account.id << account.name << account.balance.formatMoney(QString(), 2); - accountsList->addTopLevelItem(new QTreeWidgetItem(headers)); - } - - d->progress.reset(); - - button(QWizard::BackButton)->setEnabled(true); - accountsList->setEnabled(true); -} diff --git a/kmymoney/plugins/weboob/dialogs/mapaccount.h b/kmymoney/plugins/weboob/dialogs/mapaccountwizard.h rename from kmymoney/plugins/weboob/dialogs/mapaccount.h rename to kmymoney/plugins/weboob/dialogs/mapaccountwizard.h --- a/kmymoney/plugins/weboob/dialogs/mapaccount.h +++ b/kmymoney/plugins/weboob/dialogs/mapaccountwizard.h @@ -2,6 +2,7 @@ * 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 @@ -17,48 +18,43 @@ * along with this program. If not, see . */ -#ifndef WEBOOB_MAPACCOUNT_HPP -#define WEBOOB_MAPACCOUNT_HPP +#ifndef MAPACCOUNTWIZARD_H +#define MAPACCOUNTWIZARD_H -#include +// ---------------------------------------------------------------------------- +// QT Includes #include -#include "../weboob.h" -#include "ui_mapaccount.h" +// ---------------------------------------------------------------------------- +// KDE Includes -class WbMapAccountDialog : public QWizard, public Ui::WbMapAccountDialog +// ---------------------------------------------------------------------------- +// Project Includes + +class WeboobInterface; + +class MapAccountWizardPrivate; +class MapAccountWizard : public QWizard { Q_OBJECT -public: - - WeboobExt *weboob; - explicit WbMapAccountDialog(QWidget *parent = 0); - virtual ~WbMapAccountDialog(); -protected Q_SLOTS: - void checkNextButton(void); - void newPage(int id); - void gotAccounts(); - void gotBackends(); +public: + explicit MapAccountWizard(QWidget *parent, WeboobInterface *weboob); + ~MapAccountWizard(); -protected: - bool finishAccountPage(void); - bool finishLoginPage(void); - bool finishFiPage(void); + QString currentBackend() const; + QString currentAccount() const; private: - - enum { - BACKENDS_PAGE = 0, - ACCOUNTS_PAGE - }; - - struct Private; - /// \internal d-pointer instance. - const std::unique_ptr d; - const std::unique_ptr d2; + Q_DECLARE_PRIVATE(MapAccountWizard) + MapAccountWizardPrivate * const d_ptr; + +private Q_SLOTS: + void slotCheckNextButton(void); + void slotNewPage(int id); + void slotGotAccounts(); + void slotGotBackends(); }; - -#endif /* WEBOOB_MAPACCOUNT_HPP */ +#endif diff --git a/kmymoney/plugins/weboob/dialogs/mapaccountwizard.cpp b/kmymoney/plugins/weboob/dialogs/mapaccountwizard.cpp new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/weboob/dialogs/mapaccountwizard.cpp @@ -0,0 +1,214 @@ +/* + * 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 "mapaccountwizard.h" + +#include + +// ---------------------------------------------------------------------------- +// QT Includes + +#include +#include +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +#include +#include + +// ---------------------------------------------------------------------------- +// Project Includes + +#include "ui_mapaccountwizard.h" + +#include "../interface/weboobinterface.h" +#include "../weboobexc.h" + +enum { + BACKENDS_PAGE = 0, + ACCOUNTS_PAGE +}; + +class MapAccountWizardPrivate +{ +public: + MapAccountWizardPrivate(WeboobInterface* weboob) : + ui(new Ui::MapAccountWizard), + m_weboob(*weboob) + { + } + + ~MapAccountWizardPrivate() + { + delete ui; + } + + Ui::MapAccountWizard *ui; + WeboobInterface &m_weboob; + QFutureWatcher > accountsWatcher; + QFutureWatcher > backendsWatcher; + std::unique_ptr progress; +}; + +MapAccountWizard::MapAccountWizard(QWidget *parent, WeboobInterface* weboob) : + QWizard(parent), + d_ptr(new MapAccountWizardPrivate(weboob)) +{ + Q_D(MapAccountWizard); + d->ui->setupUi(this); + d->ui->addBackendButton->setVisible(false); // the button isn't connected to anything + + slotCheckNextButton(); + connect(this, &QWizard::currentIdChanged, this, &MapAccountWizard::slotCheckNextButton); + connect(this, &QWizard::currentIdChanged, this, &MapAccountWizard::slotNewPage); + connect(d->ui->backendsList, &QTreeWidget::itemSelectionChanged, this, &MapAccountWizard::slotCheckNextButton); + connect(d->ui->accountsList, &QTreeWidget::itemSelectionChanged, this, &MapAccountWizard::slotCheckNextButton); +auto abc = QString(); + connect(&d->accountsWatcher, &QFutureWatcherBase::finished, this, &MapAccountWizard::slotGotAccounts); + connect(&d->backendsWatcher, &QFutureWatcherBase::finished, this, &MapAccountWizard::slotGotBackends); +} + +/** + * @internal Deconstructer stub needed to delete unique_ptrs with type Private + */ +MapAccountWizard::~MapAccountWizard() +{ + Q_D(MapAccountWizard); + delete d; +} + +QString MapAccountWizard::currentBackend() const +{ + Q_D(const MapAccountWizard); + return d->ui->backendsList->currentItem()->text(0); +} + +QString MapAccountWizard::currentAccount() const +{ + Q_D(const MapAccountWizard); + return d->ui->accountsList->currentItem()->text(0); +} + +void MapAccountWizard::slotCheckNextButton(void) +{ + Q_D(MapAccountWizard); + auto enableButton = false; + switch (currentId()) { + case BACKENDS_PAGE: + enableButton = d->ui->backendsList->currentItem() != 0 && d->ui->backendsList->currentItem()->isSelected(); + button(QWizard::NextButton)->setEnabled(enableButton); + break; + case ACCOUNTS_PAGE: + enableButton = d->ui->accountsList->currentItem() != 0 && d->ui->accountsList->currentItem()->isSelected(); + button(QWizard::FinishButton)->setEnabled(enableButton); + break; + } + +} + +void MapAccountWizard::slotNewPage(int id) +{ + Q_D(MapAccountWizard); + d->progress = std::make_unique(this); + d->progress->setModal(true); + d->progress->setCancelButton(nullptr); + d->progress->setMinimum(0); + d->progress->setMaximum(0); + d->progress->setMinimumDuration(0); + + switch (id) { + case BACKENDS_PAGE: { + d->ui->backendsList->clear(); + d->progress->setWindowTitle(i18n("Loading Weboob backend...")); + d->progress->setLabelText(i18n("Getting list of backends.")); + + QCoreApplication::processEvents(); + d->backendsWatcher.setFuture(QtConcurrent::run(&d->m_weboob, &WeboobInterface::getBackends)); + + break; + } + case ACCOUNTS_PAGE: { + d->ui->accountsList->clear(); + d->progress->setWindowTitle(i18n("Connecting to bank...")); + d->progress->setLabelText(i18n("Getting list of accounts from your bank.")); + + QCoreApplication::processEvents(); + d->accountsWatcher.setFuture(QtConcurrent::run(&d->m_weboob, &WeboobInterface::getAccounts, d->ui->backendsList->currentItem()->text(0))); + + button(QWizard::BackButton)->setEnabled(false); + d->ui->accountsList->setEnabled(false); + + break; + } + + default: + // I do not know if this can actually happen. But to be safe: + d->progress.reset(); + } +} + +void MapAccountWizard::slotGotBackends() +{ + Q_D(MapAccountWizard); + const auto backends = d->backendsWatcher.result(); + for (const auto& backend : backends) + d->ui->backendsList->addTopLevelItem(new QTreeWidgetItem(QStringList{backend.name, + backend.module})); + d->progress.reset(); + + if (backends.isEmpty()) + KMessageBox::information(this, i18n("No backends available.\nAdd one using weboob-config-qt.")); +} + +void MapAccountWizard::slotGotAccounts() +{ + Q_D(MapAccountWizard); + try { + const auto accounts = d->accountsWatcher.result(); + for (const auto& account : accounts) + d->ui->accountsList->addTopLevelItem(new QTreeWidgetItem(QStringList{account.id, + account.name, + account.balance.formatMoney(QString(), 2)})); + d->progress.reset(); + + if (accounts.isEmpty()) + KMessageBox::information(this, i18n("No accounts available.\nCheck your backend configuration in weboob-config-qt.")); + else + button(QWizard::FinishButton)->setEnabled(true); + + } catch (const WeboobException &e) { + d->progress.reset(); + QString msg; + switch (e.msg()) { + case ExceptionCode::BrowserIncorrectPassword: + msg = i18n("Incorrect password."); + break; + default: + break; + } + if (!msg.isEmpty()) + KMessageBox::error(this, msg); + } + + button(QWizard::BackButton)->setEnabled(true); + d->ui->accountsList->setEnabled(true); +} diff --git a/kmymoney/plugins/weboob/dialogs/mapaccount.ui b/kmymoney/plugins/weboob/dialogs/mapaccountwizard.ui rename from kmymoney/plugins/weboob/dialogs/mapaccount.ui rename to kmymoney/plugins/weboob/dialogs/mapaccountwizard.ui --- a/kmymoney/plugins/weboob/dialogs/mapaccount.ui +++ b/kmymoney/plugins/weboob/dialogs/mapaccountwizard.ui @@ -1,7 +1,7 @@ - WbMapAccountDialog - + MapAccountWizard + 0 diff --git a/kmymoney/plugins/weboob/dialogs/webaccount.cpp b/kmymoney/plugins/weboob/dialogs/webaccount.cpp deleted file mode 100644 --- a/kmymoney/plugins/weboob/dialogs/webaccount.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of KMyMoney, A Personal Finance Manager by KDE - * Copyright (C) 2014-2015 Romain Bignon - * Copyright (C) 2014-2015 Florent Fourcot - * - * 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 . - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include "mymoneykeyvaluecontainer.h" -#include - - -struct WebAccountSettings::Private { - Ui::WebAccountSettings ui; -}; - -WebAccountSettings::WebAccountSettings(const MyMoneyAccount& /*acc*/, - QWidget* parent) : - QWidget(parent), - d(new Private) -{ - d->ui.setupUi(this); -} - -WebAccountSettings::~WebAccountSettings() -{ - delete d; -} - -void WebAccountSettings::loadUi(const MyMoneyKeyValueContainer& kvp) -{ - d->ui.id->setText(kvp.value("wb-id")); - d->ui.backend->setText(kvp.value("wb-backend")); - d->ui.max_history->setText(kvp.value("wb-max")); -} - -void WebAccountSettings::loadKvp(MyMoneyKeyValueContainer& kvp) -{ - kvp.setValue("wb-id", d->ui.id->text()); - kvp.setValue("wb-backend", d->ui.backend->text()); - kvp.setValue("wb-max", d->ui.max_history->text()); -} diff --git a/kmymoney/plugins/weboob/interface/CMakeLists.txt b/kmymoney/plugins/weboob/interface/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/weboob/interface/CMakeLists.txt @@ -0,0 +1,24 @@ +set(weboob_interface_SOURCES + weboobinterface.cpp + ) + +include_directories(${PYTHON_INCLUDE_DIRS}) + +# begin of a hack (read more on https://bugs.kde.org/show_bug.cgi?id=335965) +get_filename_component(PYTHON_LIBRARY_REALPATH "${PYTHON_LIBRARY}" REALPATH) +get_filename_component(LIB_PYTHON ${PYTHON_LIBRARY_REALPATH} NAME) +add_definitions(-DLIB_PYTHON="${LIB_PYTHON}") +# end of a hack + +add_library(weboob_interface STATIC ${weboob_interface_SOURCES}) +target_link_libraries ( + weboob_interface + PUBLIC + Qt5::Core + Alkimia::alkimia + PRIVATE + ${PYTHON_LIBRARIES} + ) + +install(FILES kmymoneyweboob.py + DESTINATION "${DATA_INSTALL_DIR}/kmymoney/weboob") diff --git a/kmymoney/plugins/weboob/weboob.py b/kmymoney/plugins/weboob/interface/kmymoneyweboob.py rename from kmymoney/plugins/weboob/weboob.py rename to kmymoney/plugins/weboob/interface/kmymoneyweboob.py diff --git a/kmymoney/plugins/weboob/weboobext.h b/kmymoney/plugins/weboob/interface/weboobinterface.h rename from kmymoney/plugins/weboob/weboobext.h rename to kmymoney/plugins/weboob/interface/weboobinterface.h --- a/kmymoney/plugins/weboob/weboobext.h +++ b/kmymoney/plugins/weboob/interface/weboobinterface.h @@ -2,6 +2,7 @@ * 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 @@ -17,23 +18,28 @@ * along with this program. If not, see . */ -#ifndef WEBOOBEXT_HPP -#define WEBOOBEXT_HPP +#ifndef WEBOOBINTERFACE_H +#define WEBOOBINTERFACE_H -#include -#include -#include -#include +// ---------------------------------------------------------------------------- +// QT Includes + +#include + +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes #include "mymoneymoney.h" -class WeboobExt : public QObject -{ - Q_OBJECT +struct _object; +typedef _object PyObject; - Kross::Action* action; - QMutex *mutex; - QString path; +class WeboobInterface +{ + PyObject *m_weboobInterface; public: @@ -81,9 +87,9 @@ QList transactions; }; - explicit WeboobExt(QObject* parent = 0); + explicit WeboobInterface(); - ~WeboobExt(); + ~WeboobInterface(); QStringList getProtocols(); @@ -93,8 +99,12 @@ Account getAccount(QString backend, QString account, QString max); - QVariant execute(QString method, QVariantList args); +private: + + PyObject* execute(QString method, QVariantList args); + QString extractDictStringValue(PyObject* pyContainer, const char *szKey); + long extractDictLongValue(PyObject* pyContainer, const char* szKey); }; -#endif /* WEBOOBEXT_HPP */ +#endif diff --git a/kmymoney/plugins/weboob/interface/weboobinterface.cpp b/kmymoney/plugins/weboob/interface/weboobinterface.cpp new file mode 100644 --- /dev/null +++ b/kmymoney/plugins/weboob/interface/weboobinterface.cpp @@ -0,0 +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" + +// ---------------------------------------------------------------------------- +// 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.h b/kmymoney/plugins/weboob/weboob.h --- a/kmymoney/plugins/weboob/weboob.h +++ b/kmymoney/plugins/weboob/weboob.h @@ -2,6 +2,7 @@ * 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 @@ -17,27 +18,30 @@ * along with this program. If not, see . */ -#ifndef WEBOOB_HPP -#define WEBOOB_HPP +#ifndef WEBOOB_H +#define WEBOOB_H -#include +// ---------------------------------------------------------------------------- +// QT Includes -#ifdef HAVE_CONFIG_H -#include -#endif +// ---------------------------------------------------------------------------- +// KDE Includes + +// ---------------------------------------------------------------------------- +// Project Includes #include "kmymoneyplugin.h" -#include "mymoneyaccount.h" -#include "mymoneykeyvaluecontainer.h" -#include "weboobext.h" +class MyMoneyAccount; +class MyMoneyKeyValueContainer; + +class WeboobPrivate; class Weboob : public KMyMoneyPlugin::Plugin, public KMyMoneyPlugin::OnlinePlugin { Q_OBJECT Q_INTERFACES(KMyMoneyPlugin::OnlinePlugin) public: - WeboobExt weboob; explicit Weboob(QObject *parent, const QVariantList &args); ~Weboob() override; @@ -55,16 +59,13 @@ bool updateAccount(const MyMoneyAccount& acc, bool moreAccounts = false) override; void injectExternalSettings(KMyMoneySettings* p) override; - -protected Q_SLOTS: - - void gotAccount(); - + private: + Q_DECLARE_PRIVATE(Weboob) + WeboobPrivate * const d_ptr; - struct Private; - /// \internal d-pointer instance. - const std::unique_ptr d; +private Q_SLOTS: + void gotAccount(); }; -#endif /* WEBOOB_PLUGIN_HPP */ +#endif diff --git a/kmymoney/plugins/weboob/weboob.cpp b/kmymoney/plugins/weboob/weboob.cpp --- a/kmymoney/plugins/weboob/weboob.cpp +++ b/kmymoney/plugins/weboob/weboob.cpp @@ -3,6 +3,7 @@ * 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 @@ -19,32 +20,55 @@ */ #include "weboob.h" -#include "weboobext.h" + +#include + +// ---------------------------------------------------------------------------- +// QT Includes #include #include #include +// ---------------------------------------------------------------------------- +// KDE Includes + #include #include -#include "dialogs/mapaccount.h" -#include "dialogs/webaccount.h" +// ---------------------------------------------------------------------------- +// Project Includes + +#include "mapaccountwizard.h" +#include "accountsettings.h" +#include "weboobinterface.h" +#include "mymoneyaccount.h" +#include "mymoneykeyvaluecontainer.h" #include "mymoneystatement.h" #include "statementinterface.h" #include "kmymoneyglobalsettings.h" -struct Weboob::Private +class WeboobPrivate { - QFutureWatcher watcher; +public: + WeboobPrivate() + { + } + + ~WeboobPrivate() + { + } + + WeboobInterface weboob; + QFutureWatcher watcher; std::unique_ptr progress; - WebAccountSettings* accountSettings; + AccountSettings* accountSettings; }; Weboob::Weboob(QObject *parent, const QVariantList &args) : KMyMoneyPlugin::Plugin(parent, "weboob"), - d(new Private()) + d_ptr(new WeboobPrivate) { Q_UNUSED(args) setComponentName("weboob", i18n("Weboob")); @@ -55,6 +79,8 @@ Weboob::~Weboob() { + Q_D(Weboob); + delete d; qDebug("Plugins: weboob unloaded"); } @@ -65,12 +91,14 @@ void Weboob::plug() { - connect(&d->watcher, &QFutureWatcher::finished, this, &Weboob::gotAccount); + Q_D(Weboob); + connect(&d->watcher, &QFutureWatcher::finished, this, &Weboob::gotAccount); } void Weboob::unplug() { - disconnect(&d->watcher, &QFutureWatcher::finished, this, &Weboob::gotAccount); + Q_D(Weboob); + disconnect(&d->watcher, &QFutureWatcher::finished, this, &Weboob::gotAccount); } void Weboob::protocols(QStringList& protocolList) const @@ -80,17 +108,19 @@ QWidget* Weboob::accountConfigTab(const MyMoneyAccount& account, QString& tabName) { + Q_D(Weboob); const MyMoneyKeyValueContainer& kvp = account.onlineBankingSettings(); tabName = i18n("Weboob configuration"); - d->accountSettings = new WebAccountSettings(account, 0); + 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) { @@ -101,38 +131,38 @@ bool Weboob::mapAccount(const MyMoneyAccount& acc, MyMoneyKeyValueContainer& onlineBankingSettings) { + Q_D(Weboob); Q_UNUSED(acc); - WbMapAccountDialog w; - w.weboob = &weboob; + MapAccountWizard w(nullptr, &d->weboob); if (w.exec() == QDialog::Accepted) { - onlineBankingSettings.setValue("wb-backend", w.backendsList->currentItem()->text(0)); - onlineBankingSettings.setValue("wb-id", w.accountsList->currentItem()->text(0)); + onlineBankingSettings.setValue("wb-backend", w.currentBackend()); + onlineBankingSettings.setValue("wb-id", w.currentAccount()); onlineBankingSettings.setValue("wb-max", "0"); return true; } return false; } 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"); - //! @todo C++14 use make_unique() - d->progress = std::unique_ptr(new QProgressDialog()); + 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(&weboob, &WeboobExt::getAccount, bname, id, max); + QFuture future = QtConcurrent::run(&d->weboob, &WeboobInterface::getAccount, bname, id, max); d->watcher.setFuture(future); d->progress->exec(); @@ -143,7 +173,8 @@ void Weboob::gotAccount() { - WeboobExt::Account acc = d->watcher.result(); + Q_D(Weboob); + WeboobInterface::Account acc = d->watcher.result(); MyMoneyAccount kacc = statementInterface()->account("wb-id", acc.id); MyMoneyStatement ks; @@ -173,8 +204,8 @@ } #endif - for (QListIterator it(acc.transactions); it.hasNext();) { - WeboobExt::Transaction tr = it.next(); + for (QListIterator it(acc.transactions); it.hasNext();) { + WeboobInterface::Transaction tr = it.next(); MyMoneyStatement::Transaction kt; kt.m_strBankID = QLatin1String("ID ") + tr.id; diff --git a/kmymoney/plugins/weboob/dialogs/mapaccount.h b/kmymoney/plugins/weboob/weboobexc.h rename from kmymoney/plugins/weboob/dialogs/mapaccount.h rename to kmymoney/plugins/weboob/weboobexc.h --- a/kmymoney/plugins/weboob/dialogs/mapaccount.h +++ b/kmymoney/plugins/weboob/weboobexc.h @@ -2,7 +2,7 @@ * 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 @@ -17,48 +17,31 @@ * along with this program. If not, see . */ -#ifndef WEBOOB_MAPACCOUNT_HPP -#define WEBOOB_MAPACCOUNT_HPP - -#include - -#include - -#include "../weboob.h" -#include "ui_mapaccount.h" - -class WbMapAccountDialog : public QWizard, public Ui::WbMapAccountDialog -{ - Q_OBJECT -public: - - WeboobExt *weboob; - explicit WbMapAccountDialog(QWidget *parent = 0); - virtual ~WbMapAccountDialog(); +#ifndef WEBOOBEXC_H +#define WEBOOBEXC_H -protected Q_SLOTS: - void checkNextButton(void); - void newPage(int id); - void gotAccounts(); - void gotBackends(); +// ---------------------------------------------------------------------------- +// QT Includes -protected: - bool finishAccountPage(void); - bool finishLoginPage(void); - bool finishFiPage(void); +#include -private: +// ---------------------------------------------------------------------------- +// KDE Includes - enum { - BACKENDS_PAGE = 0, - ACCOUNTS_PAGE - }; +// ---------------------------------------------------------------------------- +// Project Includes - struct Private; - /// \internal d-pointer instance. - const std::unique_ptr d; - const std::unique_ptr d2; +enum class ExceptionCode { + BrowserIncorrectPassword }; - -#endif /* WEBOOB_MAPACCOUNT_HPP */ +class WeboobException : public QException +{ +public: + explicit WeboobException(ExceptionCode ec) : m_exceptionCode(ec) {} + ExceptionCode msg() const { return m_exceptionCode; } + void raise() const { throw *this; } + WeboobException *clone() const { return new WeboobException(*this); } + ExceptionCode m_exceptionCode; +}; +#endif diff --git a/kmymoney/plugins/weboob/weboobext.cpp b/kmymoney/plugins/weboob/weboobext.cpp deleted file mode 100644 --- a/kmymoney/plugins/weboob/weboobext.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is part of KMyMoney, A Personal Finance Manager by KDE - * Copyright (C) 2014-2015 Romain Bignon - * Copyright (C) 2014-2015 Florent Fourcot - * - * 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 "weboobext.h" - -#include -#include -#include - -WeboobExt::WeboobExt(QObject* parent) - : QObject(parent) -{ - mutex = new QMutex(); - path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmm_weboob/weboob.py"); - action = new Kross::Action(0, path); - action->setFile(path); -} - -WeboobExt::~WeboobExt() -{ - delete mutex; - action->finalize(); - delete action; -} - -QVariant WeboobExt::execute(QString method, QVariantList args) -{ - QVariant result; - - mutex->lock(); - result = action->callFunction(method, args); - mutex->unlock(); - - return result; -} - -QList WeboobExt::getBackends() -{ - QList backendsList; - - QVariantList args; - - QVariant result = this->execute("get_backends", args); - - QMap list = result.toMap(); - QMapIterator it(list); - - while (it.hasNext()) { - it.next(); - QMap params = it.value().toMap(); - - WeboobExt::Backend backend; - backend.name = it.key(); - backend.module = params["module"].toString(); - - backendsList.append(backend); - } - - return backendsList; -} - - -QList WeboobExt::getAccounts(QString backend) -{ - QList accountsList; - - QVariantList args; - args << backend; - QVariant result = this->execute("get_accounts", args); - - QMap list = result.toMap(); - for (QMapIterator it(list); it.hasNext();) { - it.next(); - QMap params = it.value().toMap(); - - WeboobExt::Account account; - account.id = it.key(); - account.name = params["name"].toString(); - account.balance = MyMoneyMoney(params["balance"].toInt(), 100); - account.type = (WeboobExt::Account::type_t)params["type"].toInt(); - - accountsList.append(account); - } - - return accountsList; -} - -WeboobExt::Account WeboobExt::getAccount(QString backend, QString accid, QString max) -{ - WeboobExt::Account acc; - - QVariantList args; - args << backend; - args << accid; - args << max; - QMap result = this->execute("get_transactions", args).toMap(); - - acc.id = result["id"].toString(); - acc.name = result["name"].toString(); - acc.balance = MyMoneyMoney(result["balance"].toInt(), 100); - acc.type = (WeboobExt::Account::type_t)result["type"].toInt(); - - QList list = result["transactions"].toList(); - for (QListIterator it(list); it.hasNext();) { - QMap params = it.next().toMap(); - WeboobExt::Transaction tr; - - tr.id = params["id"].toString(); - tr.date = QDate::fromString(params["date"].toString(), "yyyy-MM-dd"); - tr.rdate = QDate::fromString(params["rdate"].toString(), "yyyy-MM-dd"); - tr.type = (WeboobExt::Transaction::type_t)params["type"].toInt(); - tr.raw = params["raw"].toString(); - tr.category = params["category"].toString(); - tr.label = params["label"].toString(); - tr.amount = MyMoneyMoney(params["amount"].toInt(), 100); - - acc.transactions.append(tr); - } - return acc; -}