/*
 *  This file is part of the KDE libraries
 *  Copyright (C) 2003 Benjamin C Meyer (ben+tdelibs at meyerhome dot net)
 *  Copyright (C) 2003 Waldo Bastian <bastian@kde.org>
 *  Copyright (C) 2004 Michael Brade <brade@kde.org>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 */

/*
 *  TDEConfigDialog derivative allowing for a multi-level hierarchical TreeList.
 *  Differences from TDEConfigDialog:
 *  - Use TQStringList instead of TQString for the item name(s) in addPage and
 *    addPageInternal, thus calling the respective KDialogBase methods which
 *    allow specifying a path from which the TreeList hierarchy is constructed.
 *  - Use 16x16 icons in the TreeList.
 *  - Fill a new int m_lastAddedIndex with the pageIndex() of a new page added
 *    with addPageInternal, and offer a public interface int lastAddedIndex().
 *  See the TDEConfigDialog reference for detailed documentation.
 *
 *  begin:     Nov 22 2005
 *  copyright: (C) 2005-2006 by Eike Hein, TDEConfigDialog developers
 *  email:     hein@kde.org
 */

#include "konviconfigdialog.h"

#include <tdeconfigskeleton.h>
#include <tdeconfigdialogmanager.h>
#include <tdelocale.h>
#include <kiconloader.h>
#include <kdebug.h>

#include <tqlayout.h>
#include <tqvbox.h>
#include <tqmap.h>


TQAsciiDict<KonviConfigDialog> KonviConfigDialog::openDialogs;

// This class is here purly so we don't break binary compatibility down the road.
class KonviConfigDialog::TDEConfigDialogPrivate
{
    public:
        TDEConfigDialogPrivate(KDialogBase::DialogType t) : shown(false), type(t), manager(0) { }

        bool shown;
        KDialogBase::DialogType type;
        TDEConfigDialogManager *manager;
        TQMap<TQWidget *, TDEConfigDialogManager *> managerForPage;
};

KonviConfigDialog::KonviConfigDialog( TQWidget *parent, const char *name,
                                      TDEConfigSkeleton *config,
                                      DialogType dialogType,
                                      int dialogButtons,
                                      ButtonCode defaultButton,
                                      bool modal ) :
                   KDialogBase( dialogType, TQt::WStyle_DialogBorder,
                                parent, name, modal, i18n("Configure"), dialogButtons, defaultButton ),
                                d(new TDEConfigDialogPrivate(dialogType))
{
    if ( name )
    {
        openDialogs.insert(name, this);
    }
    else
    {
        TQCString genericName;
        genericName.sprintf("SettingsDialog-%p", this);
        openDialogs.insert(genericName, this);
        setName(genericName);
    }

    connect(this, TQ_SIGNAL(okClicked()), this, TQ_SLOT(updateSettings()));
    connect(this, TQ_SIGNAL(applyClicked()), this, TQ_SLOT(updateSettings()));
    connect(this, TQ_SIGNAL(applyClicked()), this, TQ_SLOT(updateButtons()));
    connect(this, TQ_SIGNAL(defaultClicked()), this, TQ_SLOT(updateWidgetsDefault()));
    connect(this, TQ_SIGNAL(defaultClicked()), this, TQ_SLOT(updateButtons()));

    d->manager = new TDEConfigDialogManager(this, config);
    setupManagerConnections(d->manager);

    enableButton(Apply, false);
}

KonviConfigDialog::~KonviConfigDialog()
{
    openDialogs.remove(name());
    delete d;
}

void KonviConfigDialog::addPage(TQWidget *page,
                                const TQStringList &items,
                                const TQString &pixmapName,
                                const TQString &header,
                                bool manage)
{
    addPageInternal(page, items, pixmapName, header);
    if(manage)
        d->manager->addWidget(page);
}

void KonviConfigDialog::addPage(TQWidget *page,
                                TDEConfigSkeleton *config,
                                const TQStringList &items,
                                const TQString &pixmapName,
                                const TQString &header)
{
    addPageInternal(page, items, pixmapName, header);
    d->managerForPage[page] = new TDEConfigDialogManager(page, config);
    setupManagerConnections(d->managerForPage[page]);
}

void KonviConfigDialog::addPageInternal(TQWidget *page,
                                        const TQStringList &items,
                                        const TQString &pixmapName,
                                        const TQString &header)
{
    if(d->shown)
    {
        kdDebug(240) << "KonviConfigDialog::addPage: can not add a page after the dialog has been shown.";
        return;
    }
    switch(d->type)
    {
        case TreeList:
        case IconList:
        case Tabbed:
        {
            TQVBox *frame = addVBoxPage(items, header, SmallIcon(pixmapName, 16));
            frame->setSpacing( 0 );
            frame->setMargin( 0 );
            page->reparent(((TQWidget*)frame), 0, TQPoint());
            m_lastAddedIndex = pageIndex(frame);
        }
        break;

        case Swallow:
        {
            page->reparent(this, 0, TQPoint());
            setMainWidget(page);
        }
        break;

        case Plain:
        {
            TQFrame *main = plainPage();
            TQVBoxLayout *topLayout = new TQVBoxLayout( main, 0, 0 );
            page->reparent(((TQWidget*)main), 0, TQPoint());
            topLayout->addWidget( page );
        }
        break;

        default:
            kdDebug(240) << "KonviConfigDialog::addpage: unknown type.";
    }
}

void KonviConfigDialog::setupManagerConnections(TDEConfigDialogManager *manager)
{
    connect(manager, TQ_SIGNAL(settingsChanged()), this, TQ_SLOT(settingsChangedSlot()));
    connect(manager, TQ_SIGNAL(widgetModified()), this, TQ_SLOT(updateButtons()));

    connect(this, TQ_SIGNAL(okClicked()), manager, TQ_SLOT(updateSettings()));
    connect(this, TQ_SIGNAL(applyClicked()), manager, TQ_SLOT(updateSettings()));
    connect(this, TQ_SIGNAL(defaultClicked()), manager, TQ_SLOT(updateWidgetsDefault()));
}

KonviConfigDialog* KonviConfigDialog::exists(const char* name)
{
    return openDialogs.find(name);
}

bool KonviConfigDialog::showDialog(const char* name)
{
    KonviConfigDialog *dialog = exists(name);
    if(dialog)
        dialog->show();
    return (dialog != NULL);
}

void KonviConfigDialog::updateButtons()
{
    static bool only_once = false;
    if (only_once) return;
    only_once = true;

    TQMap<TQWidget *, TDEConfigDialogManager *>::iterator it;

    bool has_changed = d->manager->hasChanged() || hasChanged();
    for (it = d->managerForPage.begin();
        it != d->managerForPage.end() && !has_changed;
        ++it)
    {
        has_changed |= (*it)->hasChanged();
    }

    enableButton(Apply, has_changed);

    bool is_default = d->manager->isDefault() && isDefault();
    for (it = d->managerForPage.begin();
        it != d->managerForPage.end() && is_default;
        ++it)
    {
        is_default &= (*it)->isDefault();
    }

    enableButton(Default, !is_default);

    emit widgetModified();
    only_once = false;
}

void KonviConfigDialog::settingsChangedSlot()
{
    // Update the buttons
    updateButtons();
    emit settingsChanged();
    emit settingsChanged(name());
}

void KonviConfigDialog::show()
{
    TQMap<TQWidget *, TDEConfigDialogManager *>::iterator it;

    updateWidgets();
    d->manager->updateWidgets();
    for (it = d->managerForPage.begin(); it != d->managerForPage.end(); ++it)
        (*it)->updateWidgets();

    bool has_changed = d->manager->hasChanged() || hasChanged();
    for (it = d->managerForPage.begin();
        it != d->managerForPage.end() && !has_changed;
        ++it)
    {
        has_changed |= (*it)->hasChanged();
    }

    enableButton(Apply, has_changed);

    bool is_default = d->manager->isDefault() && isDefault();
    for (it = d->managerForPage.begin();
        it != d->managerForPage.end() && is_default;
        ++it)
    {
        is_default &= (*it)->isDefault();
    }

    enableButton(Default, !is_default);
    d->shown = true;
    KDialogBase::show();
}

int KonviConfigDialog::lastAddedIndex()
{
    return m_lastAddedIndex;
}

void KonviConfigDialog::updateSettings()
{
}

void KonviConfigDialog::updateWidgets()
{
}

void KonviConfigDialog::updateWidgetsDefault()
{
}

#include "konviconfigdialog.moc"
