/***************************************************************************
 *   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 <KStandardDirs>
#include <KIO/NetAccess>
#include <KLocale>
#include <KRun>
#include <KUrl>
#include <knewstuff3/downloaddialog.h>
#include <knewstuff3/uploaddialog.h>
#include <KZip>

#include <QtGui/QSortFilterProxyModel>
#include <QDomDocument>
#include <QFile>
#include <QKeyEvent>
#include <QDir>

#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)
{
    SKGTRACEINFUNC(10);
    if (!iDocument) {
        return;
    }

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

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

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

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

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

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

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

    QStringList overlays;
    overlays.push_back("list-add");
    m_upload = new KAction(KIcon("get-hot-new-stuff", NULL, overlays), i18n("Upload"), this);
    connect(m_upload, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), SLOT(onPutNewHotStuff()));

    KMenu* menu = new KMenu();
    menu->addAction(m_upload);
    ui.kGetNewHotStuff->setMenu(menu);

    ui.kUnitOpen->setIcon(KIcon("skg_open"));
    connect(ui.kUnitOpen, SIGNAL(clicked(bool)), this, SLOT(onOpenURL()));

    KAction* downloadLastAction = new KAction(KIcon("download"), i18n("download last value only"), this);
    downloadLastAction->setData(SKGUnitObject::LAST);
    connect(downloadLastAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), SLOT(onDownloadUnitValue()));

    KAction* downloadLastMonthlyAction = new KAction(KIcon("download"), i18n("download monthly values since last known value"), this);
    downloadLastMonthlyAction->setData(SKGUnitObject::LAST_MONTHLY);
    connect(downloadLastMonthlyAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), SLOT(onDownloadUnitValue()));

    KAction* downloadLastWeeklyAction = new KAction(KIcon("download"), i18n("download weekly values since last known value"), this);
    downloadLastWeeklyAction->setData(SKGUnitObject::LAST_WEEKLY);
    connect(downloadLastWeeklyAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), SLOT(onDownloadUnitValue()));

    KAction* downloadLastDailyAction = new KAction(KIcon("download"), i18n("download daily values since last known value"), this);
    downloadLastDailyAction->setData(SKGUnitObject::LAST_DAILY);
    connect(downloadLastDailyAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), SLOT(onDownloadUnitValue()));

    KAction* downloadMonthlyAction = new KAction(KIcon("download"), i18n("download all monthly values"), this);
    downloadMonthlyAction->setData(SKGUnitObject::ALL_MONTHLY);
    connect(downloadMonthlyAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), SLOT(onDownloadUnitValue()));

    KAction* downloadWeeklyAction = new KAction(KIcon("download"), i18n("download all weekly values"), this);
    downloadWeeklyAction->setData(SKGUnitObject::ALL_WEEKLY);
    connect(downloadWeeklyAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), SLOT(onDownloadUnitValue()));

    KAction* downloadDailyAction = new KAction(KIcon("download"), i18n("download all daily values"), this);
    downloadDailyAction->setData(SKGUnitObject::ALL_DAILY);
    connect(downloadDailyAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), SLOT(onDownloadUnitValue()));

    KAction* simplifyAction = new KAction(KIcon("edit-delete"), i18n("simplify values"), this);
    connect(simplifyAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), SLOT(onSimplify()));


    KMenu* downloadMenu = new KMenu();
    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, SIGNAL(clicked(bool)), SLOT(onDownloadUnitValue()));
    {
        SKGWidgetSelector::SKGListQWidget list;
        list.push_back(ui.kStandardFrm);
        list.push_back(ui.kBtnFrm);
        ui.kWidgetSelector->addButton(KIcon("dialog-ok-apply"), 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(KIcon("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(KIcon("view-currency-list"), i18n("Values"), i18n("Display the edit panel for values of units"), list);
    }
    connect(ui.kWidgetSelector, SIGNAL(selectedModeChanged(int)), this, SLOT(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("unit", "t_type='1'", primaryUnit);
    iDocument->existObjects("unit", "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()), "v_unit_display", "", this, "", false));

        // Add registered global action in contextual menu
        if (SKGMainPanel::getMainPanel()) {
            ui.kUnitTableViewEdition->getView()->insertGlobalAction();
            ui.kUnitTableViewEdition->getView()->insertGlobalAction("open");
            ui.kUnitTableViewEdition->getView()->insertGlobalAction("open_report");
            ui.kUnitTableViewEdition->getView()->insertGlobalAction();
            ui.kUnitTableViewEdition->getView()->insertGlobalAction("edit_delete");
            ui.kUnitTableViewEdition->getView()->insertGlobalAction();
            ui.kUnitTableViewEdition->getView()->insertGlobalAction("edit_switch_highlight");
            ui.kUnitTableViewEdition->getView()->insertGlobalAction("edit_split_stock");
        }

        connect(ui.kUnitTableViewEdition->getView(), SIGNAL(clickEmptyArea()), this, SLOT(cleanEditor()));
        connect(ui.kUnitTableViewEdition->getView(), SIGNAL(doubleClicked(QModelIndex)), SKGMainPanel::getMainPanel()->getGlobalAction("open"), SLOT(trigger()));
        connect(ui.kUnitTableViewEdition->getView(), SIGNAL(selectionChangedDelayed()), this, SLOT(onSelectionChanged()));
    }

    // Bind unit creation view
    {
        SKGObjectModel* objectModel2 = new SKGObjectModel(static_cast<SKGDocumentBank*>(getDocument()), "v_unitvalue_display", "1=0", this, "", false);

        ui.kUnitValueTableViewEdition->setModel(objectModel2);

        // Add registered global action in contextual menu
        ui.kUnitValueTableViewEdition->insertGlobalAction("edit_delete");

        connect(ui.kUnitValueTableViewEdition, SIGNAL(selectionChangedDelayed()), this, SLOT(onSelectionValueChanged()));
    }

    // Refresh
    connect(getDocument(), SIGNAL(tableModified(QString,int,bool)), this, SLOT(dataModified(QString,int)), Qt::QueuedConnection);
    ui.kWidgetSelector->setSelectedMode(0);

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

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

    // Synchronize zooms of both tables
    connect(ui.kUnitTableViewEdition->getView(), SIGNAL(zoomChanged(int)), ui.kUnitValueTableViewEdition, SLOT(setZoomPosition(int)));
    connect(ui.kUnitValueTableViewEdition, SIGNAL(zoomChanged(int)), ui.kUnitTableViewEdition->getView(), SLOT(setZoomPosition(int)));

    // Fill combo box for currency
    m_timer.setSingleShot(true);
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(refreshUnitList()), Qt::QueuedConnection);
    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("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("");    // 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("v_unitvalue_display", "d_date", "t_UNIT", "f_quantity", "TOTAL", wc % " AND d_date>(SELECT date('now', '-50 year'))" , table , "");

    SKGServices::SKGUnitInfo primaryUnit = static_cast<SKGDocumentBank*>(getDocument())->getPrimaryUnit();
    SKGServices::SKGUnitInfo secondaryUnit = static_cast<SKGDocumentBank*>(getDocument())->getSecondaryUnit();
    if (unit.getType() == SKGUnitObject::INDEX) {
        primaryUnit.Symbol = "";
        secondaryUnit.Symbol = "";
    } 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(KGlobal::locale()->formatMoney(SKGServices::stringToDouble(unitValue.getAttribute("f_quantity")),
                                        "",
                                        SKGServices::stringToInt(unit.getAttribute("i_nbdecimal"))));
            }
        } else {
            ui.kDateEdit->setDate(QDate::currentDate());
            ui.kAmountEdit->setText("");
        }
        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[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[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);
}

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;
    KAction* act = qobject_cast<KAction*>(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.count() == 0) {
        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("SKGML");
    QDomElement root = doc.createElement("parameters");
    doc.appendChild(root);

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

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

    return doc.toString();
}

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

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

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

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

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

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

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

    if (iTableName == "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("");
        ui.kSymbolCreatorUnit->setText("");
        ui.kCountryCreatorUnit->setText("");
        ui.kInternetCreatorUnit->setText("");
        ui.kUnitCreatorUnit->setText("");
    }
}

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("skrooge_unit.knsrc", this);
    dialog->exec();
    delete dialog;

    fillSourceList();
}

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

    // Create zip file
    QString sourceFileName = KStandardDirs::locateLocal("data", QString::fromLatin1("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("skrooge_unit.knsrc", this);

        dialog->setUploadFile(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);
}

#include "skgunitpluginwidget.moc"
