/* ====================================================================
 * Copyright (c) 2003-2006, Martin Hauner
 *                          http://subcommander.tigris.org
 *
 * Subcommander is licensed as described in the file doc/COPYING, which
 * you should have received as part of this distribution.
 * ====================================================================
 */

// sc
#include "config.h"
#include "SettingsDialog.h"
#include "SettingsWidget.h"
#include "SettingsInfo.h"
#include "sublib/Gui.h"
#include "util/Compare.h"

// qt
#include <qlayout.h>
#include <qlistview.h>
#include <qwidgetstack.h>
#include <qpushbutton.h>
#include <qgroupbox.h>


class SettingsLvi : public QListViewItem
{
  typedef QListViewItem super;

public:
  SettingsLvi( SettingsInfo* info, QListView* lv )
    : super( lv, info->getTitle() ), _info(info)
  {
  }

  SettingsLvi( SettingsInfo* info, QListViewItem* lvi )
    : super( lvi, info->getTitle() ), _info(info)
  {
  }

  void paintCell( QPainter *p, const QColorGroup & cg, int column, int width, int alignment )
  {
    QColorGroup g(cg);

    if( isModified() )
    {
      g.setColor( QColorGroup::Base, QColor(200,200,230) );
    }

    super::paintCell(p,g,column,width,alignment);
  }

  SettingsInfo* getInfo() const
  {
    return _info;
  }

  bool isModified()
  {
    bool modified = _info->isModified();

    if( isOpen() == false )
    {
      SettingsLvi* child = (SettingsLvi*)firstChild();
      while( child )
      {
        modified |= child->isModified();

        child = (SettingsLvi*)child->nextSibling();
      }
    }

    return modified;
  }

  int compare( QListViewItem * i, int col, bool ascending ) const
  {
    SettingsLvi* lvi = dynamic_cast<SettingsLvi*>(i);
    return compare3( getInfo()->getSortIndex(), lvi->getInfo()->getSortIndex() );
  }

private:
  SettingsInfo* _info;
};





SettingsDialog::SettingsDialog( const QString& title, QWidget *parent, const char *name )
  : super( parent, name, true, Qt::WStyle_Customize | Qt::WStyle_Dialog |
  Qt::WStyle_NormalBorder | Qt::WStyle_Title | Qt::WStyle_SysMenu ), _curInfo(0)
{
  setCaption( title );

  QVBoxLayout *vbl = new QVBoxLayout(this,5,8);
  vbl->setSpacing(10);
  {
    QGridLayout* gl = new QGridLayout( vbl, 2, 2, 0, 0 );
    gl->setMargin(5);
    gl->setSpacing(10);
    {
      _categories = new QListView(this);
      gl->addWidget( _categories, 0, 0 );
      {
        _categories->setRootIsDecorated(true);
        _categories->setSorting(0,true);
        _categories->setTreeStepSize(11);
        _categories->addColumn( _q("category") );
        _categories->setColumnWidthMode( 0, QListView::Maximum );
        _categories->setResizeMode( QListView::LastColumn );
        _categories->setSizePolicy( QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Preferred) );
      }
      connect( _categories, SIGNAL(clicked(QListViewItem*)), SLOT(clicked(QListViewItem*)) );

      _box = new QGroupBox( 1, Qt::Horizontal, _q("no settings selected: "), this );
      _box->setMargin(10);
      _box->setInsideMargin(10);
      gl->addWidget( _box, 0, 1 );
      {
        _stack = new QWidgetStack(_box);
        _stack->setSizePolicy( QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding) );
        {
          _stack->addWidget( new QWidget(), 0 );
        }
      }

      QHBoxLayout* hl = new QHBoxLayout;
      vbl->addLayout( hl );
      {
        // eats up any extra space, so the buttons keep their size
        hl->addStretch(1); 

        _ok = new QPushButton(this);
        _ok->setText( _q("&Ok") );
        //_ok->setDefault(true);
        _ok->setEnabled(false);
        hl->addWidget(_ok);

        _apply = new QPushButton(this);
        _apply->setText( _q("&Apply") );
        _apply->setEnabled(false);
        hl->addWidget(_apply);

        QPushButton* ca = new QPushButton(this);
        ca->setDefault(true);
        ca->setFocus();
        ca->setText( _q("&Close") );
        hl->addWidget(ca);
        
        hl->addSpacing(getSizeGripSpacing());

        connect( _ok,    SIGNAL(clicked()), SLOT(ok()) );
        connect( _apply, SIGNAL(clicked()), SLOT(apply()) );
        connect( ca,     SIGNAL(clicked()), SLOT(cancel()) );
      }
    }
  }
}

SettingsDialog::~SettingsDialog()
{
}

void SettingsDialog::addSettingsInfo( SettingsInfo* info, const QString& parentTitle )
{
  SettingsLvi* lvi = 0;

  Lvis::iterator it = _lvis.find( parentTitle );
  if( it == _lvis.end() )
  {
    // toplevel..
    lvi = new SettingsLvi( info, _categories );
  }
  else
  {
    // childlevel..
    lvi = new SettingsLvi( info, (*it).second );
  }

  int newSize = (lvi->depth()+ 4/*?*/) * _categories->treeStepSize() +
    lvi->width( QFontMetrics(_categories->font()), _categories, 0 );

  if( newSize > _categories->minimumWidth() )
  {
    _categories->setMinimumWidth( newSize );
  }

  _lvis.insert( Lvis::value_type(info->getTitle(),lvi) );

  if( info->getSelected() )
  {
    lvi->setSelected(true);
    clicked(lvi);

    QListViewItem* p = lvi;
    if( (p = p->parent()) )
    {
      p->setOpen(true);
    }
  }
}

void SettingsDialog::addSettingsWidget( const QString& settingsId, SettingsWidget* sw )
{
  _stack->addWidget( sw );
  _widgets.insert( Widgets::value_type(settingsId,sw) );

  connect( sw, SIGNAL(modified()), SLOT(modified()) );
}


void SettingsDialog::ok()
{
  for( Lvis::iterator it = _lvis.begin(); it != _lvis.end(); it++ )
  {
    SettingsLvi* lvi = (*it).second;
    lvi->getInfo()->ok();
  }

  accept();
}

void SettingsDialog::apply()
{
  _curInfo->apply();
  modified();
}

void SettingsDialog::cancel()
{
  for( Lvis::iterator it = _lvis.begin(); it != _lvis.end(); it++ )
  {
    SettingsLvi* lvi = (*it).second;
    lvi->getInfo()->cancel();
  }

  reject();
}

void SettingsDialog::modified()
{
  _curInfo->storeWidgetData( (SettingsWidget*)_stack->visibleWidget() );

  _apply->setEnabled(_curInfo->isModified());
  _ok   ->setEnabled(isModified());
}

bool SettingsDialog::isModified()
{
  bool modified = false;

  for( Lvis::iterator it = _lvis.begin(); it != _lvis.end(); it++ )
  {
    SettingsLvi* lvi = (*it).second;

    modified |= lvi->isModified();
  }

  return modified;
}

void SettingsDialog::clicked( QListViewItem* item )
{
  if( ! item )
  {
    return;
  }

  // remember data from current SettingsWidget..
  if( _curInfo )
  {
    SettingsWidget* sw = (SettingsWidget*)_stack->visibleWidget();
    _curInfo->storeWidgetData( sw );
  }

  // set new SettingsWidget...
  SettingsLvi*  lvi  = (SettingsLvi*)item;
  SettingsInfo* info = lvi->getInfo();

  _apply->setDisabled( ! info->isModified() );

  Widgets::iterator it = _widgets.find( info->getSettingsId() );
  if( it == _widgets.end() )
  {
    _box->setTitle( _q("no settings selected: ") );
    _stack->raiseWidget(0);
    _curInfo = 0;
  }
  else
  {
    SettingsWidget* sw = (*it).second;

    _box->setTitle( info->getSettingsId() + ": " );

    _curInfo = info;
    _stack->raiseWidget( sw );
    info->initWidgetData( sw );
  }
}


syntax highlighted by Code2HTML, v. 0.9.1