/***************************************************************************
                           settingsdialog.cpp
                           ------------------
    begin                : Sun Sep 13 2003
    copyright            : (C) 2003 Dirk Ziegelmeier
    email                : dziegel@gmx.de
 ***************************************************************************/

/*
 * 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 Steet, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <kdebug.h>
#include <kiconloader.h>
#include <klocale.h>
#include <qlayout.h>
#include <qgrid.h>

#include "settingsdialog.h"
#include "settingsdialogpage.h"
#include "kdetv.h"
#include "cfgdata.h"

#include "channelwidgetimpl.h"
#include "generalwidgetimpl.h"
#include "pluginwidgetimpl.h"
#include "soundwidgetimpl.h"
#include "videowidgetimpl.h"
#include "filterwidgetimpl.h"

SettingsDialog::SettingsDialog(QWidget *parent, char *name, bool modal,
                               Kdetv *ktv, QPtrList<SettingsDialogPage>* externalPages, WFlags fl)
    : KDialogBase(KDialogBase::IconList, i18n("Settings"), 
                  KDialogBase::Default | KDialogBase::Apply | KDialogBase::Ok | KDialogBase::Cancel,
                  KDialogBase::Ok, parent, name, modal, true),
      _ktv(ktv),
      _externalPageCount(0)
{
    kdDebug() << "SettingsDialog: constructor" << endl;

    setWFlags(fl);

    // Kdetv backend pages
    addDialogPage(static_cast<SettingsDialogPage*>(new GeneralWidgetImpl(0L, _ktv, _ktv->config())));
    addDialogPage(static_cast<SettingsDialogPage*>(new VideoWidgetImpl  (0L, _ktv, _ktv->config())));
    addDialogPage(static_cast<SettingsDialogPage*>(new SoundWidgetImpl  (0L, _ktv, _ktv->config())));
    addDialogPage(static_cast<SettingsDialogPage*>(new ChannelWidgetImpl(0L, _ktv, _ktv->config())));
    addDialogPage(static_cast<SettingsDialogPage*>(new PluginWidgetImpl (0L, _ktv, _ktv->config())));
    addDialogPage(static_cast<SettingsDialogPage*>(new FilterWidgetImpl (0L, _ktv, _ktv->config())));

    // Other pages (client, plugins)
    if (externalPages != 0) {
        for (QPtrListIterator<SettingsDialogPage>it(*externalPages);
             it.current() != 0;
             ++it) {
            addDialogPage(*it);
            _externalPageCount++;
        }
    }
    
    setInitialSize(QSize(702, 490), false);
} // SettingsDialog constructor

SettingsDialog::~SettingsDialog()
{
    kdDebug() << "SettingsDialog: destructor" << endl;
} // SettingsDialog destructor


/***************************************************************************
 *
 * Private Functions
 *
 ***************************************************************************/

void SettingsDialog::addDialogPage(SettingsDialogPage* page)
{
    QWidget* pageWidget = dynamic_cast<QWidget*>(page);
    if (!pageWidget) {
        kdWarning() << "Page does not have QWidget parent - cannot add page: " << page->pageName() << endl;
        // and we memleak here... if you see this message, fix it :-)
        return;
    }

    _pages.append(page);

    QGrid* p = addGridPage(1,
                           QGridLayout::Horizontal,
                           page->pageName(),
                           page->header(),
                           BarIcon(page->barIconName().local8Bit(), KIcon::SizeMedium));
    pageWidget->reparent(p, QPoint(0, 0));
    page->setup();
}

/***************************************************************************
 *
 * Protected Slots
 *
 ***************************************************************************/

void SettingsDialog::slotCancel()
{
    for (QPtrListIterator<SettingsDialogPage>it(_pages);
         it.current() != 0;
         ++it) {
        it.current()->cancel();
    }

    KDialogBase::slotCancel();
} // slotCancel

void SettingsDialog::doApply()
{
    /*
     * FIXME: Dirk: The settingsdialog pages are not independent
     *              of each other, so the apply order matters.
     * 
     * 1) Changing device/source after video plugin rescan does not always work
     * 2) Changing device/source before applying channel changes breaks channel file or crashes
     * 3) Rescanning source plugins before applying channel changes may break channel file or crash
     */

    for (int i=0; i<_externalPageCount; i++) {
        _pages.at(i+6)->apply();
    }

    _pages.at(5)->apply(); // Filter
    _pages.at(4)->apply(); // Plugins
    _pages.at(3)->apply(); // Channel
    _pages.at(0)->apply(); // Sound
    _pages.at(2)->apply(); // Video
    _pages.at(1)->apply(); // General

    //    for (QPtrListIterator<SettingsDialogPage>it(_pages);
    //    	 it.current() != 0;
    //    	 ++it) {
    //    	it.current()->apply();
    //    }

    emit optionsModified();
}

void SettingsDialog::slotApply()
{
    doApply();

    for (QPtrListIterator<SettingsDialogPage>it(_pages);
    	 it.current() != 0;
    	 ++it) {
    	it.current()->setup();
    }
} // slotApply

void SettingsDialog::slotDefault()
{
    // hack around bug in KJanusWidget in KDE prior to KDE3.1.2 (returns invalid values)
    // only works if the settings page count remains constant
    // (which is given at the time of this writing) !!!
    // this was the offending code:
    // http://webcvs.kde.org/cgi-bin/cvsweb.cgi/kdelibs/kdeui/kjanuswidget.cpp.diff?r1=1.52.2.2&r2=1.52.2.3&f=h
    int i = activePageIndex() % _pages.count();
    _pages.at(i)->defaults();
} // slotDefault

void SettingsDialog::slotHelp()
{
    KDialogBase::slotHelp();
} // slotHelp

void SettingsDialog::slotOk()
{
    doApply();
    accept();
    _ktv->config()->save();    
} // slotOk

#include "settingsdialog.moc"
