/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   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 <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
/** @file
 * This file is Skrooge plugin for unit management.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgunitpluginwidget.h"

#include <klocalizedstring.h>
#include <krun.h>
#include <kns3/downloaddialog.h>
#include <kns3/uploaddialog.h>
#include <kzip.h>

#include <qurl.h>
#include <qsortfilterproxymodel.h>
#include <qdom.h>
#include <qfile.h>
#include <qevent.h>
#include <qdir.h>
#include <qstandardpaths.h>
#include <qvalidator.h>

#include "skgmainpanel.h"
#include "skgobjectmodel.h"
#include "skgbankincludes.h"
#include "skgservices.h"
#include "skgtraces.h"
#include "skgunit_settings.h"

SKGUnitPluginWidget::SKGUnitPluginWidget(SKGDocumentBank* iDocument)
    : SKGTabPage(iDocument), m_upload(nullptr)
{
    SKGTRACEINFUNC(10);
    if (!iDocument) {
        return;
    }

    ui.setupUi(this);
    ui.kGraph->setShadowVisible(false);

    ui.kNameLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_name"))));
    ui.kDecimalLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("i_nbdecimal"))));
    ui.kCountyLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_country"))));
    ui.kSymbolLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_symbol"))));
    ui.kTypeLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_type"))));
    ui.kInternetLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_internet_code"))));
    ui.kDateLabel->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("d_date"))));
    ui.kAmountLabel->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("f_value"))));
    ui.kUnitLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_UNIT"))));
    ui.kUnitLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_UNIT"))));
    ui.kDownloadSourceLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_source"))));

    ui.kUnitTableViewEdition->getShowWidget()->addItem(QStringLiteral("all"), i18nc("Noun, items to display", "All"), QStringLiteral(""),
            QStringLiteral(""),
            QStringLiteral("currency;share;index;object"),  // Check when checked
            QStringLiteral("highlighted"),  // Uncheck when checked
            QStringLiteral(""), QStringLiteral(""),
            Qt::META + Qt::Key_A);
    ui.kUnitTableViewEdition->getShowWidget()->addItem(QStringLiteral("highlighted"), i18n("Highlighted only"), QStringLiteral("bookmarks"), QStringLiteral("t_bookmarked='Y'"), QStringLiteral(""), QStringLiteral("all;currency;share;index;object"), QStringLiteral("all"), QStringLiteral(""), Qt::META + Qt::Key_H);
    ui.kUnitTableViewEdition->getShowWidget()->addSeparator();
    ui.kUnitTableViewEdition->getShowWidget()->addItem(QStringLiteral("currency"), i18nc("Noun, a country's currency", "Currency"), QStringLiteral(""),
            QStringLiteral("t_type IN ('1','2','C')"),
            QStringLiteral(""),  // Check when checked
            QStringLiteral("highlighted"),       // Uncheck when checked
            QStringLiteral(""),       // Check when unchecked
            QStringLiteral("all"), Qt::META + Qt::Key_C);     // Uncheck when unchecked
    ui.kUnitTableViewEdition->getShowWidget()->addItem(QStringLiteral("share"), i18nc("Noun, a financial share, as in a stock market", "Share"), QStringLiteral(""),
            QStringLiteral("t_type='S'"),
            QStringLiteral(""),
            QStringLiteral("highlighted"),
            QStringLiteral(""),
            QStringLiteral("all"), Qt::META + Qt::Key_S);
    ui.kUnitTableViewEdition->getShowWidget()->addItem(QStringLiteral("index"), i18nc("Noun, a financial index like the Dow Jones, NASDAQ, CAC40...", "Index"), QStringLiteral(""),
            QStringLiteral("t_type='I'"),
            QStringLiteral(""),
            QStringLiteral("highlighted"),
            QStringLiteral(""),
            QStringLiteral("all;current"), Qt::META + Qt::Key_I);
    ui.kUnitTableViewEdition->getShowWidget()->addItem(QStringLiteral("object"), i18nc("Noun, a physical object like a house or a car", "Object"), QStringLiteral(""),
            QStringLiteral("t_type='O'"),
            QStringLiteral(""),
            QStringLiteral("highlighted"),
            QStringLiteral(""),
            QStringLiteral("all"), Qt::META + Qt::Key_O);

    ui.kUnitTableViewEdition->getShowWidget()->setDefaultState(QStringLiteral("all;currency;share;index;object"));

    ui.kGraph->getShowWidget()->setState(QStringLiteral("\"graph\""));
    ui.kGraph->setFilterVisibility(false);

    ui.kUnitCreatorUnit->setDocument(iDocument);
    ui.kUnitCreatorUnit->setWhereClauseCondition(QStringLiteral("t_type IN ('1','2','C')"));

    // Add Standard KDE Icons to buttons to Accounts
    ui.kUnitAdd->setIcon(SKGServices::fromTheme(QStringLiteral("list-add")));
    ui.kUnitUpdate->setIcon(SKGServices::fromTheme(QStringLiteral("dialog-ok")));
    ui.kUnitValueDownload->setIcon(SKGServices::fromTheme(QStringLiteral("download")));
    ui.kDeleteSource->setIcon(SKGServices::fromTheme(QStringLiteral("edit-delete")));
    ui.kGetNewHotStuff->setIcon(SKGServices::fromTheme(QStringLiteral("get-hot-new-stuff")));

    auto newValidator = new QRegExpValidator(QRegExp(QStringLiteral("^[\\w\\s]+$")), this);
    ui.kDownloadSource->setValidator(newValidator);

    QStringList overlays;
    overlays.push_back(QStringLiteral("list-add"));
    m_upload = new QAction(SKGServices::fromTheme(QStringLiteral("get-hot-new-stuff"), overlays), i18n("Upload"), this);
    connect(m_upload, &QAction::triggered, this, &SKGUnitPluginWidget::onPutNewHotStuff);

    auto menu = new QMenu();
    menu->addAction(m_upload);
    ui.kGetNewHotStuff->setMenu(menu);

    ui.kUnitOpen->setIcon(SKGServices::fromTheme(QStringLiteral("quickopen")));
    connect(ui.kUnitOpen, &QPushButton::clicked, this, &SKGUnitPluginWidget::onOpenURL);

    auto downloadLastAction = new QAction(SKGServices::fromTheme(QStringLiteral("download")), i18n("download last value only"), this);
    downloadLastAction->setData(SKGUnitObject::LAST);
    connect(downloadLastAction, &QAction::triggered, this, &SKGUnitPluginWidget::onDownloadUnitValue);

    auto downloadLastMonthlyAction = new QAction(SKGServices::fromTheme(QStringLiteral("download")), i18n("download monthly values since last known value"), this);
    downloadLastMonthlyAction->setData(SKGUnitObject::LAST_MONTHLY);
    connect(downloadLastMonthlyAction, &QAction::triggered, this, &SKGUnitPluginWidget::onDownloadUnitValue);

    auto downloadLastWeeklyAction = new QAction(SKGServices::fromTheme(QStringLiteral("download")), i18n("download weekly values since last known value"), this);
    downloadLastWeeklyAction->setData(SKGUnitObject::LAST_WEEKLY);
    connect(downloadLastWeeklyAction, &QAction::triggered, this, &SKGUnitPluginWidget::onDownloadUnitValue);

    auto downloadLastDailyAction = new QAction(SKGServices::fromTheme(QStringLiteral("download")), i18n("download daily values since last known value"), this);
    downloadLastDailyAction->setData(SKGUnitObject::LAST_DAILY);
    connect(downloadLastDailyAction, &QAction::triggered, this, &SKGUnitPluginWidget::onDownloadUnitValue);

    auto downloadMonthlyAction = new QAction(SKGServices::fromTheme(QStringLiteral("download")), i18n("download all monthly values"), this);
    downloadMonthlyAction->setData(SKGUnitObject::ALL_MONTHLY);
    connect(downloadMonthlyAction, &QAction::triggered, this, &SKGUnitPluginWidget::onDownloadUnitValue);

    auto downloadWeeklyAction = new QAction(SKGServices::fromTheme(QStringLiteral("download")), i18n("download all weekly values"), this);
    downloadWeeklyAction->setData(SKGUnitObject::ALL_WEEKLY);
    connect(downloadWeeklyAction, &QAction::triggered, this, &SKGUnitPluginWidget::onDownloadUnitValue);

    auto downloadDailyAction = new QAction(SKGServices::fromTheme(QStringLiteral("download")), i18n("download all daily values"), this);
    downloadDailyAction->setData(SKGUnitObject::ALL_DAILY);
    connect(downloadDailyAction, &QAction::triggered, this, &SKGUnitPluginWidget::onDownloadUnitValue);

    auto simplifyAction = new QAction(SKGServices::fromTheme(QStringLiteral("edit-delete")), i18n("simplify values"), this);
    connect(simplifyAction, &QAction::triggered, this, &SKGUnitPluginWidget::onSimplify);


    auto downloadMenu = new QMenu();
    downloadMenu->addAction(downloadLastAction);
    downloadMenu->addAction(downloadLastMonthlyAction);
    downloadMenu->addAction(downloadLastWeeklyAction);
    downloadMenu->addAction(downloadLastDailyAction);
    downloadMenu->addAction(downloadMonthlyAction);
    downloadMenu->addAction(downloadWeeklyAction);
    downloadMenu->addAction(downloadDailyAction);

    downloadMenu->addAction(simplifyAction);
    ui.kUnitValueDownload->setMenu(downloadMenu);
    connect(ui.kUnitValueDownload, &QToolButton::clicked, this, &SKGUnitPluginWidget::onDownloadUnitValue);
    {
        SKGWidgetSelector::SKGListQWidget list;
        list.push_back(ui.kStandardFrm);
        list.push_back(ui.kBtnFrm);
        ui.kWidgetSelector->addButton(SKGServices::fromTheme(QStringLiteral("dialog-ok")), i18n("Standard"), i18n("Display the edit panel for standard units"), list);
    }
    {
        SKGWidgetSelector::SKGListQWidget list;
        list.push_back(ui.kManualFrm);
        list.push_back(ui.kBtnFrm);
        ui.kWidgetSelector->addButton(SKGServices::fromTheme(QStringLiteral("user-properties")), i18n("Manual / Share"), i18n("Display the edit panel for manual units"), list);
    }
    {
        SKGWidgetSelector::SKGListQWidget list;
        list.push_back(ui.kValuesFrm);
        list.push_back(ui.kBtnFrm);
        ui.kWidgetSelector->addButton(SKGServices::fromTheme(QStringLiteral("taxes-finances")), i18n("Values"), i18n("Display the edit panel for values of units"), list);
    }
    connect(ui.kWidgetSelector, &SKGWidgetSelector::selectedModeChanged, this, &SKGUnitPluginWidget::onUnitCreatorModified);

    // Fill combo box for type
    ui.kTypeCreatorUnit->addItem(i18nc("Noun", "Primary currency"), SKGUnitObject::PRIMARY);
    ui.kTypeCreatorUnit->addItem(i18nc("Noun", "Secondary currency"), SKGUnitObject::SECONDARY);
    ui.kTypeCreatorUnit->addItem(i18nc("Noun, a country's currency", "Currency"), SKGUnitObject::CURRENCY);
    ui.kTypeCreatorUnit->addItem(i18nc("Noun, a financial share, as in a stock market", "Share"), SKGUnitObject::SHARE);
    ui.kTypeCreatorUnit->addItem(i18nc("Noun, a financial index like the Dow Jones, NASDAQ, CAC40...", "Index"), SKGUnitObject::INDEX);
    ui.kTypeCreatorUnit->addItem(i18nc("Noun, a physical object like a house or a car", "Object"), SKGUnitObject::OBJECT);
    bool primaryUnit, secondaryUnit;
    iDocument->existObjects(QStringLiteral("unit"), QStringLiteral("t_type='1'"), primaryUnit);
    iDocument->existObjects(QStringLiteral("unit"), QStringLiteral("t_type='2'"), secondaryUnit);
    if (primaryUnit) {
        if (secondaryUnit) {
            ui.kTypeCreatorUnit->setCurrentIndex(2);
        } else {
            ui.kTypeCreatorUnit->setCurrentIndex(1);
        }
    } else {
        ui.kTypeCreatorUnit->setCurrentIndex(0);
    }

    // Bind unit creation view
    {
        ui.kUnitTableViewEdition->setModel(new SKGObjectModel(static_cast<SKGDocumentBank*>(getDocument()), QStringLiteral("v_unit_display"), QStringLiteral(""), this, QStringLiteral(""), false));

        connect(ui.kUnitTableViewEdition->getView(), &SKGTreeView::clickEmptyArea, this, &SKGUnitPluginWidget::cleanEditor);
        connect(ui.kUnitTableViewEdition->getView(), &SKGTreeView::doubleClicked, SKGMainPanel::getMainPanel()->getGlobalAction(QStringLiteral("open")).data(), &QAction::trigger);
        connect(ui.kUnitTableViewEdition->getView(), &SKGTreeView::selectionChangedDelayed, [ = ] {this->onSelectionChanged();});
    }

    // Bind unit creation view
    {
        auto objectModel2 = new SKGObjectModel(static_cast<SKGDocumentBank*>(getDocument()), QStringLiteral("v_unitvalue_display"), QStringLiteral("1=0"), this, QStringLiteral(""), false);
        ui.kUnitValueTableViewEdition->setModel(objectModel2);
        connect(ui.kUnitValueTableViewEdition, &SKGTableView::selectionChangedDelayed, this, &SKGUnitPluginWidget::onSelectionValueChanged);
    }

    // Refresh
    connect(getDocument(), &SKGDocument::tableModified, this, &SKGUnitPluginWidget::dataModified, Qt::QueuedConnection);
    ui.kWidgetSelector->setSelectedMode(0);

    // Fill combo box for reference currency
    fillSourceList();
    dataModified(QStringLiteral(""), 0);

    // Set Event filters to catch CTRL+ENTER or SHIFT+ENTER
    this->installEventFilter(this);

    // Synchronize zooms of both tables
    connect(ui.kUnitTableViewEdition->getView(), &SKGTreeView::zoomChanged, ui.kUnitValueTableViewEdition, &SKGTreeView::setZoomPosition);
    connect(ui.kUnitValueTableViewEdition, &SKGTreeView::zoomChanged, ui.kUnitTableViewEdition->getView(), &SKGTreeView::setZoomPosition);

    // Fill combo box for currency
    m_timer.setSingleShot(true);
    connect(&m_timer, &QTimer::timeout, this, &SKGUnitPluginWidget::refreshUnitList);
    m_timer.start(500);;
}

SKGUnitPluginWidget::~SKGUnitPluginWidget()
{
    SKGTRACEINFUNC(10);
}

bool SKGUnitPluginWidget::eventFilter(QObject* iObject, QEvent* iEvent)
{
    if (iEvent && iEvent->type() == QEvent::KeyPress) {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(iEvent);
        if ((keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) && iObject == this) {
            if (QApplication::keyboardModifiers() &Qt::ControlModifier && ui.kUnitAdd->isEnabled()) {
                ui.kUnitAdd->click();
            } else if (QApplication::keyboardModifiers() &Qt::ShiftModifier && ui.kUnitUpdate->isEnabled()) {
                ui.kUnitUpdate->click();
            }
        }
    }

    return false;
}

void SKGUnitPluginWidget::fillSourceList()
{
    // Get previous selected item
    QString current = ui.kDownloadSource->text();

    // Fill
    ui.kDownloadSource->clear();
    ui.kDownloadSource->addItem(i18nc("Native download source (Yahoo)", "Yahoo"));
    ui.kDownloadSource->addItems(SKGUnitObject::downloadSources());
    ui.kDeleteSource->hide();

    // Set previous selected itemData
    if (!current.isEmpty() && ui.kDownloadSource->contains(current)) {
        ui.kDownloadSource->setCurrentItem(current);
    }
}

void SKGUnitPluginWidget::onSelectionChanged()
{
    SKGTRACEINFUNC(10);
    // Mapping
    SKGUnitObject unit;

    int nbSelect = ui.kUnitTableViewEdition->getView()->getNbSelectedObjects();
    if (nbSelect == 1) {
        unit = ui.kUnitTableViewEdition->getView()->getFirstSelectedObject();
        ui.kNameCreatorUnit->setText(unit.getName());
        ui.kSymbolCreatorUnit->setText(unit.getSymbol());
        ui.kCountryCreatorUnit->setText(unit.getCountry());
        ui.kTypeCreatorUnit->setCurrentIndex(ui.kTypeCreatorUnit->findData(unit.getType()));
        ui.kInternetCreatorUnit->setText(unit.getInternetCode());
        ui.kUnitCreatorUnit->setText(unit.getAttribute(QStringLiteral("t_UNIT")));
        ui.kNbDecimal->setValue(unit.getNumberDecimal());
        ui.kDownloadSource->setText(unit.getDownloadSource());
    } else if (nbSelect > 1) {
        ui.kNameCreatorUnit->setText(NOUPDATE);
        ui.kSymbolCreatorUnit->setText(NOUPDATE);
        ui.kCountryCreatorUnit->setText(NOUPDATE);
        ui.kTypeCreatorUnit->setText(NOUPDATE);
        ui.kInternetCreatorUnit->setText(NOUPDATE);
        ui.kUnitCreatorUnit->setText(NOUPDATE);
        ui.kDownloadSource->setText(NOUPDATE);
    }
    ui.kUnitValueFrame->setEnabled(nbSelect == 1);
    ui.kUnitValueDownload->setEnabled(nbSelect > 0);
    ui.kUnitOpen->setEnabled(nbSelect > 0);

    // Fill values
    QString wc = "rd_unit_id=(select id from unit where t_name='" % SKGServices::stringToSqlString(ui.kNameCreatorUnit->text()) % "')";
    SKGObjectModel* objectModel = static_cast<SKGObjectModel*>(ui.kUnitValueTableViewEdition->model());
    if (objectModel) {
        objectModel->setFilter(QStringLiteral(""));    // Correction 2299600: to be sure that refresh will be done
        objectModel->setFilter(wc % " order by d_date desc");
        objectModel->refresh();
    }

    ui.kUnitOfUnitLbl->setText(ui.kUnitCreatorUnit->text());

    // Draw plot
    SKGStringListList table;
    getDocument()->getConsolidatedView(QStringLiteral("v_unitvalue_display"), QStringLiteral("d_date"), QStringLiteral("t_UNIT"), QStringLiteral("f_quantity"), QStringLiteral("TOTAL"), wc % " AND d_date>(SELECT date('now', '-50 year')) AND d_date<(SELECT date('now', '+50 year'))" , table , QStringLiteral(""));

    SKGServices::SKGUnitInfo primaryUnit = static_cast<SKGDocumentBank*>(getDocument())->getPrimaryUnit();
    SKGServices::SKGUnitInfo secondaryUnit = static_cast<SKGDocumentBank*>(getDocument())->getSecondaryUnit();
    if (unit.getType() == SKGUnitObject::INDEX) {
        primaryUnit.Symbol = QStringLiteral("");
        secondaryUnit.Symbol = QStringLiteral("");
    } else {
        SKGUnitObject parentUnitObject;
        unit.getUnit(parentUnitObject);
        SKGServices::SKGUnitInfo parentUnit = parentUnitObject.getUnitInfo();
        if (primaryUnit.Symbol != parentUnit.Symbol) {
            secondaryUnit = primaryUnit;
            primaryUnit = parentUnit;

            secondaryUnit.Value = 1.0 / primaryUnit.Value;
            primaryUnit.Value = 1;
        }
    }
    ui.kGraph->setData(table, primaryUnit, secondaryUnit, SKGTableWithGraph::LIMITS);

    // Correction bug 2299394 vvv
    if (ui.kUnitValueTableViewEdition->isAutoResized()) {
        ui.kUnitValueTableViewEdition->resizeColumnsToContentsDelayed();
    }
    // Correction bug 2299394 ^^^

    onUnitCreatorModified();
    Q_EMIT selectionChanged();
}

void SKGUnitPluginWidget::onSelectionValueChanged()
{
    SKGTRACEINFUNC(10);
    // Mapping
    QItemSelectionModel* selModel = ui.kUnitValueTableViewEdition->selectionModel();
    if (selModel) {
        QModelIndexList indexes = selModel->selectedRows();
        int nbSelect = indexes.count();
        if (nbSelect) {
            QModelIndex idx = indexes[indexes.count() - 1];

            SKGObjectModel* model = static_cast<SKGObjectModel*>(ui.kUnitValueTableViewEdition->model());
            if (model) {
                SKGUnitValueObject unitValue(model->getObject(idx));
                SKGUnitObject unit;
                unitValue.getUnit(unit);

                ui.kDateEdit->setDate(unitValue.getDate());
                ui.kAmountEdit->setText(SKGServices::toCurrencyString(SKGServices::stringToDouble(unitValue.getAttribute(QStringLiteral("f_quantity"))),
                                        QStringLiteral(""),
                                        SKGServices::stringToInt(unit.getAttribute(QStringLiteral("i_nbdecimal")))));
            }
        } else {
            ui.kDateEdit->setDate(QDate::currentDate());
            ui.kAmountEdit->setText(QStringLiteral(""));
        }
        Q_EMIT selectionChanged();
    }
}

void SKGUnitPluginWidget::onUnitCreatorModified()
{
    SKGTRACEINFUNC(10);

    bool activated = ui.kWidgetSelector->getSelectedMode() != -1 &&
                     !ui.kNameCreatorUnit->text().isEmpty()  &&
                     !ui.kSymbolCreatorUnit->text().isEmpty();

    int nbSelect = getNbSelectedObjects();

    ui.kUnitAdd->setEnabled((activated && (ui.kAmountEdit->valid() || ui.kWidgetSelector->getSelectedMode() != 2)) || ui.kWidgetSelector->getSelectedMode() == 0);
    ui.kUnitUpdate->setEnabled(activated && nbSelect > 0 && ui.kWidgetSelector->getSelectedMode() == 1);

    ui.kWidgetSelector->setEnabledMode(2, nbSelect == 1);
    if (!(activated && nbSelect > 0) && ui.kWidgetSelector->getSelectedMode() == 2) {
        ui.kWidgetSelector->setSelectedMode(0);
    }
}

void SKGUnitPluginWidget::onAddUnit()
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);
    int mode = ui.kWidgetSelector->getSelectedMode();

    if (mode == 0) {
        QString untiname = ui.kCurrencyList->text();
        SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Unit creation '%1'", untiname), err);
        SKGUnitObject oUnit;
        err = SKGUnitObject::createCurrencyUnit(static_cast<SKGDocumentBank*>(getDocument()), ui.kCurrencyList->text(), oUnit);
    } else if (mode == 1) {
        QString untiname = ui.kNameCreatorUnit->text();
        SKGUnitObject unitObj(getDocument());
        {
            SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Unit creation '%1'", untiname), err);

            // Create unit object
            IFOKDO(err, unitObj.setName(untiname))
            IFOKDO(err, unitObj.setSymbol(ui.kSymbolCreatorUnit->text()))
            IFOKDO(err, unitObj.setCountry(ui.kCountryCreatorUnit->text()))
            IFOKDO(err, unitObj.setInternetCode(ui.kInternetCreatorUnit->text()))
            IFOKDO(err, unitObj.setType(static_cast<SKGUnitObject::UnitType>(ui.kTypeCreatorUnit->itemData(ui.kTypeCreatorUnit->currentIndex()).toInt())))
            IFOKDO(err, unitObj.setNumberDecimal(ui.kNbDecimal->value()))
            IFOKDO(err, unitObj.setUnit(ui.kUnitCreatorUnit->getUnit()))
            IFOKDO(err, unitObj.setDownloadSource(ui.kDownloadSource->text()))
            IFOKDO(err, unitObj.save())
        }

        // status bar
        IFOK(err) {
            err = SKGError(0, i18nc("Successful message after an user action", "Unit '%1' created", untiname));
            ui.kUnitTableViewEdition->getView()->selectObject(unitObj.getUniqueID());
        } else {
            err.addError(ERR_FAIL, i18nc("Error message", "Unit creation failed"));
        }
    } else if (mode == 2) {
        QString untiname = ui.kNameCreatorUnit->text();
        SKGUnitValueObject unitValueObject;
        {
            SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Unit value creation for '%1'", untiname), err);
            IFOKDO(err, static_cast<SKGDocumentBank*>(getDocument())->addOrModifyUnitValue(untiname, ui.kDateEdit->date(), ui.kAmountEdit->value(), &unitValueObject))
        }
        // status bar
        IFOK(err) {
            err = SKGError(0, i18nc("Successful message after an user action", "Unit value created for '%1'", untiname));
            // TODO(Stephane MANKOWSKI) doesn't work because of unit table is modified an refreshed
            ui.kUnitValueTableViewEdition->selectObject(unitValueObject.getUniqueID());
        } else {
            err.addError(ERR_FAIL, i18nc("Error message", "Unit value creation failed"));
        }
    }

    // Display error
    SKGMainPanel::displayErrorMessage(err);
}

void SKGUnitPluginWidget::onModifyUnit()
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);
    // Get Selection
    SKGObjectBase::SKGListSKGObjectBase selection = ui.kUnitTableViewEdition->getView()->getSelectedObjects();

    int nb = selection.count();

    {
        SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Unit update")  , err, nb);

        // Is it a massive modification of payees to merge them ?
        if (nb > 1 && ui.kNameCreatorUnit->text() != NOUPDATE && !ui.kNameCreatorUnit->text().startsWith(QLatin1String("="))) {
            getDocument()->sendMessage(i18nc("Information message", "You tried to modify all names of selected units. Units have been merged."));

            // Do the merge
            SKGUnitObject unitObj1(selection[0]);
            for (int i = 1; !err && i < nb; ++i) {
                SKGUnitObject unitObj(selection.at(i));
                err = unitObj1.merge(unitObj);
            }

            // Change selection for the rest of the operation
            selection.clear();
            selection.push_back(unitObj1);
            nb = 1;
        }

        for (int i = 0; !err && i < nb; ++i) {
            // Modification of unit object
            SKGUnitObject unitObj(selection.at(i));
            IFOKDO(err, unitObj.setName(ui.kNameCreatorUnit->text()))
            IFOKDO(err, unitObj.setSymbol(ui.kSymbolCreatorUnit->text()))
            IFOKDO(err, unitObj.setCountry(ui.kCountryCreatorUnit->text()))
            IFOKDO(err, unitObj.setInternetCode(ui.kInternetCreatorUnit->text()))
            if (!err && ui.kTypeCreatorUnit->text() != NOUPDATE) {
                err = unitObj.setType(static_cast<SKGUnitObject::UnitType>(ui.kTypeCreatorUnit->itemData(ui.kTypeCreatorUnit->currentIndex()).toInt()));
            }
            IFOKDO(err, unitObj.setNumberDecimal(ui.kNbDecimal->value()))
            if (!err && ui.kUnitCreatorUnit->text() != NOUPDATE) {
                err = unitObj.setUnit(ui.kUnitCreatorUnit->getUnit());
            }
            if (!err && ui.kDownloadSource->text() != NOUPDATE) {
                err = unitObj.setDownloadSource(ui.kDownloadSource->text());
            }
            IFOKDO(err, unitObj.save())

            // Send message
            IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The unit '%1' has been updated", unitObj.getDisplayName()), SKGDocument::Hidden));

            IFOKDO(err, getDocument()->stepForward(i + 1))
        }
    }

    // status bar
    IFOKDO(err, SKGError(0, i18nc("Message for successful user action", "Unit updated")))
    else {
        err.addError(ERR_FAIL, i18nc("Error message", "Unit update failed"));
    }

    // Display error
    SKGMainPanel::displayErrorMessage(err);

    // Set focus on table
    ui.kUnitTableViewEdition->getView()->setFocus();
}

SKGUnitObject::UnitDownloadMode SKGUnitPluginWidget::getDownloadModeFromSettings()
{
    SKGUnitObject::UnitDownloadMode mode = SKGUnitObject::LAST;
    if (skgunit_settings::last()) {
        mode = SKGUnitObject::LAST;
    } else if (skgunit_settings::last_monthly()) {
        mode = SKGUnitObject::LAST_MONTHLY;
    } else if (skgunit_settings::last_weekly()) {
        mode = SKGUnitObject::LAST_WEEKLY;
    } else if (skgunit_settings::last_daily()) {
        mode = SKGUnitObject::LAST_DAILY;
    } else if (skgunit_settings::all_monthly()) {
        mode = SKGUnitObject::ALL_MONTHLY;
    } else if (skgunit_settings::all_weekly()) {
        mode = SKGUnitObject::ALL_WEEKLY;
    } else if (skgunit_settings::all_daily()) {
        mode = SKGUnitObject::ALL_DAILY;
    }
    return mode;
}

SKGError SKGUnitPluginWidget::downloadUnitValue(const SKGUnitObject& iUnit, SKGUnitObject::UnitDownloadMode mode)
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);

    QString unitname = iUnit.getName();
    QString code = iUnit.getInternetCode();
    SKGDocumentBank* doc = static_cast<SKGDocumentBank*>(iUnit.getDocument());
    if (!code.isEmpty() && doc) {
        SKGBEGINTRANSACTION(*doc, i18nc("Noun, name of the user action", "Download values for [%1 (%2)]", unitname, code), err);
        err = const_cast<SKGUnitObject*>(&iUnit)->downloadUnitValue(mode, skgunit_settings::nb_loaded_values(), skgunit_settings::download_additional_info());
    }

    return err;
}

void SKGUnitPluginWidget::onDownloadUnitValue()
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);

    SKGUnitObject::UnitDownloadMode mode = SKGUnitObject::LAST;
    QAction* act = qobject_cast<QAction*>(sender());
    if (act) {
        mode = static_cast<SKGUnitObject::UnitDownloadMode>(act->data().toInt());
    } else {
        mode = SKGUnitPluginWidget::getDownloadModeFromSettings();
    }

    SKGObjectBase::SKGListSKGObjectBase selection = ui.kUnitTableViewEdition->getView()->getSelectedObjects();
    int nb = selection.count();
    if (nb) {
        SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Download values"), err, nb);
        for (int i = 0; !err && i < nb; ++i) {
            SKGUnitObject unit(selection.at(i));
            err = downloadUnitValue(unit, mode);

            // Send message
            IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The unit '%1' has been downloaded", unit.getDisplayName()), SKGDocument::Hidden));

            IFOKDO(err, getDocument()->stepForward(i + 1))
        }
    }

    IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Download done")))
    else {
        err.addError(ERR_FAIL, i18nc("Error message", "Download failed"));
    }

    // Display error
    SKGMainPanel::displayErrorMessage(err);
}

void SKGUnitPluginWidget::onSimplify()
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);

    SKGObjectBase::SKGListSKGObjectBase selection = ui.kUnitTableViewEdition->getView()->getSelectedObjects();
    int nb = selection.count();
    if (nb) {
        SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Simplify unit values"), err, nb);
        for (int i = 0; !err && i < nb; ++i) {
            SKGUnitObject unit(selection.at(i));
            err = unit.simplify();

            // Send message
            IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The unit '%1' has been simplified", unit.getDisplayName()), SKGDocument::Hidden));

            IFOKDO(err, getDocument()->stepForward(i + 1))
        }
    }

    IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Simplification done")))
    else {
        err.addError(ERR_FAIL, i18nc("Error message", "Simplification failed"));
    }

    // Display error
    SKGMainPanel::displayErrorMessage(err);
}

SKGObjectBase::SKGListSKGObjectBase SKGUnitPluginWidget::getSelectedObjects()
{
    SKGObjectBase::SKGListSKGObjectBase output;
    if (ui.kUnitValueTableViewEdition->hasFocus()) {
        output = ui.kUnitValueTableViewEdition->getSelectedObjects();
    }
    if (output.isEmpty()) {
        output = ui.kUnitTableViewEdition->getView()->getSelectedObjects();
    }
    return output;
}

int SKGUnitPluginWidget::getNbSelectedObjects()
{
    int output = 0;
    if (ui.kUnitValueTableViewEdition->hasFocus()) {
        output = ui.kUnitValueTableViewEdition->getNbSelectedObjects();
    }
    if (output == 0) {
        output = ui.kUnitTableViewEdition->getView()->getNbSelectedObjects();
    }
    return output;
}


QString SKGUnitPluginWidget::getState()
{
    SKGTRACEINFUNC(10);
    QDomDocument doc(QStringLiteral("SKGML"));
    QDomElement root = doc.createElement(QStringLiteral("parameters"));
    doc.appendChild(root);

    root.setAttribute(QStringLiteral("splitter1State"), QString(ui.kMainSplitter->saveState().toHex()));
    root.setAttribute(QStringLiteral("splitter2State"), QString(ui.kValuesSplitter->saveState().toHex()));

    // Memorize table settings
    root.setAttribute(QStringLiteral("unitview"), ui.kUnitTableViewEdition->getState());
    root.setAttribute(QStringLiteral("unitvalueview"), ui.kUnitValueTableViewEdition->getState());
    root.setAttribute(QStringLiteral("currentPage"), SKGServices::intToString(ui.kWidgetSelector->getSelectedMode()));
    root.setAttribute(QStringLiteral("obsolete"), ui.kObsolete->isChecked() ? QStringLiteral("Y") : QStringLiteral("N"));
    root.setAttribute(QStringLiteral("graphSettings"), ui.kGraph->getState());

    return doc.toString();
}

void SKGUnitPluginWidget::setState(const QString& iState)
{
    SKGTRACEINFUNC(10);
    QDomDocument doc(QStringLiteral("SKGML"));
    doc.setContent(iState);
    QDomElement root = doc.documentElement();

    QString splitter1State = root.attribute(QStringLiteral("splitter1State"));
    QString splitter2State = root.attribute(QStringLiteral("splitter2State"));
    QString currentPage = root.attribute(QStringLiteral("currentPage"));
    QString obsolete = root.attribute(QStringLiteral("obsolete"));

    if (currentPage.isEmpty()) {
        currentPage = '0';
    }

    if (!splitter1State.isEmpty()) {
        ui.kMainSplitter->restoreState(QByteArray::fromHex(splitter1State.toLatin1()));
    }
    if (!splitter2State.isEmpty()) {
        ui.kValuesSplitter->restoreState(QByteArray::fromHex(splitter2State.toLatin1()));
    }
    ui.kWidgetSelector->setSelectedMode(SKGServices::stringToInt(currentPage));
    ui.kObsolete->setChecked(obsolete == QStringLiteral("Y"));

    ui.kUnitTableViewEdition->setState(root.attribute(QStringLiteral("unitview")));
    ui.kUnitValueTableViewEdition->setState(root.attribute(QStringLiteral("unitvalueview")));
    ui.kGraph->setState(root.attribute(QStringLiteral("graphSettings")));
    ui.kGraph->setGraphType(SKGTableWithGraph::LINE);
}

QString SKGUnitPluginWidget::getDefaultStateAttribute()
{
    return QStringLiteral("SKGUNIT_DEFAULT_PARAMETERS");
}

void SKGUnitPluginWidget::dataModified(const QString& iTableName, int iIdTransaction)
{
    SKGTRACEINFUNC(10);
    Q_UNUSED(iIdTransaction);

    if (iTableName == QStringLiteral("unitvalue") || iTableName.isEmpty()) {
        // Correction bug 2299394 vvv
        if (ui.kUnitValueTableViewEdition->isAutoResized()) {
            ui.kUnitValueTableViewEdition->resizeColumnsToContentsDelayed();
        }
        // Correction bug 2299394 ^^^
    }
}

void SKGUnitPluginWidget::cleanEditor()
{
    if (getNbSelectedObjects() == 0) {
        ui.kNameCreatorUnit->setText(QStringLiteral(""));
        ui.kSymbolCreatorUnit->setText(QStringLiteral(""));
        ui.kCountryCreatorUnit->setText(QStringLiteral(""));
        ui.kInternetCreatorUnit->setText(QStringLiteral(""));
        ui.kUnitCreatorUnit->setText(QStringLiteral(""));
    }
}

bool SKGUnitPluginWidget::isEditor()
{
    return true;
}

void SKGUnitPluginWidget::activateEditor()
{
    if (ui.kWidgetSelector->getSelectedMode() == -1) {
        ui.kWidgetSelector->setSelectedMode(0);
    }
    ui.kCurrencyList->setFocus();
}

void SKGUnitPluginWidget::refreshUnitList()
{
    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
    // Clean list
    ui.kCurrencyList->clear();

    // Add items
    QStringList list = SKGUnitObject::getListofKnownCurrencies(ui.kObsolete->isChecked());
    ui.kCurrencyList->addItems(list);

    // Completion
    KCompletion* comp = ui.kCurrencyList->completionObject();
    if (comp) {
        comp->setIgnoreCase(true);
        comp->setSoundsEnabled(true);
        comp->clear();
        comp->insertItems(list);
    }
    QApplication::restoreOverrideCursor();
}

QWidget* SKGUnitPluginWidget::mainWidget()
{
    if (ui.kUnitValueTableViewEdition->hasFocus()) {
        return ui.kUnitValueTableViewEdition;
    }
    return ui.kUnitTableViewEdition->getView();
}

void SKGUnitPluginWidget::onAddSource()
{
    QString source = ui.kDownloadSource->text().trimmed();
    if (!source.isEmpty() && source != i18nc("Native download source (Yahoo)", "Yahoo") &&
        (!SKGUnitObject::downloadSources().contains(source) || SKGUnitObject::isWritable(source))) {
        // This is a new source
        SKGError err = SKGUnitObject::addSource(source);
        onSourceChanged();

        // Display error
        SKGMainPanel::displayErrorMessage(err);
    }
}

void SKGUnitPluginWidget::onDeleteSource()
{
    QString source = ui.kDownloadSource->text();
    if (!source.isEmpty() && source != i18nc("Native download source (Yahoo)", "Yahoo") && SKGUnitObject::downloadSources().contains(source)) {
        // This is a new source
        SKGError err = SKGUnitObject::deleteSource(source);
        IFOK(err) ui.kDownloadSource->removeItem(ui.kDownloadSource->findText(source));

        // Display error
        SKGMainPanel::displayErrorMessage(err);
    }
}

void SKGUnitPluginWidget::onSourceChanged()
{
    QString source = ui.kDownloadSource->text().trimmed();
    bool local = !source.isEmpty() && source != i18nc("Native download source (Yahoo)", "Yahoo") && SKGUnitObject::isWritable(source);
    ui.kDeleteSource->setVisible(local);
    m_upload->setEnabled(local);
}

void SKGUnitPluginWidget::onGetNewHotStuff()
{
    QPointer<KNS3::DownloadDialog> dialog = new KNS3::DownloadDialog(QStringLiteral("skrooge_unit.knsrc"), this);
    dialog->exec();
    delete dialog;

    fillSourceList();
}

void SKGUnitPluginWidget::onPutNewHotStuff()
{
    QString source = ui.kDownloadSource->text().trimmed();

    // Create zip file
    QString sourceFileName = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + QStringLiteral("skrooge/quotes/") % source % ".txt";
    QString zipFileName = QDir::tempPath() % "/" % source % ".zip";
    KZip zip(zipFileName);
    if (zip.open(QIODevice::WriteOnly)) {
        zip.addLocalFile(sourceFileName, source % ".txt");
        zip.close();

        // Open dialog
        QPointer<KNS3::UploadDialog> dialog = new KNS3::UploadDialog(QStringLiteral("skrooge_unit.knsrc"), this);

        dialog->setUploadFile(QUrl::fromLocalFile(zipFileName));
        dialog->setUploadName(source);
        dialog->setDescription(i18nc("Default description for the source", "My favorite source of download for units"));
        dialog->exec();
        delete dialog;

        // Delete temporary files
        QFile(zipFileName).remove();
    }
}

void SKGUnitPluginWidget::onOpenURL()
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);

    SKGObjectBase::SKGListSKGObjectBase selection = ui.kUnitTableViewEdition->getView()->getSelectedObjects();
    int nb = selection.count();
    if (nb) {
        for (int i = 0; !err && i < nb; ++i) {
            SKGUnitObject unit(selection.at(i));
            err = unit.openURL();
        }
    }

    // Display error
    SKGMainPanel::displayErrorMessage(err);
}


