/***************************************************************************
begin                : Thu Feb 7  2002
copyright            : (C) 2002 by Christian Hubinger
email                : chubinger@gmail.com
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
#include "kmfruleedit.h"

//KDE includes
#include <kled.h>
#include <kdebug.h>
#include <klocale.h>
#include <klistview.h>
#include <kpopupmenu.h>
#include <kmessagebox.h>
#include <kapplication.h>
#include <klistbox.h>
#include <kpushbutton.h>
#include <kcombobox.h>
#include <ktrader.h>
#include <kparts/part.h>
#include <kparts/plugin.h>
#include <kparts/factory.h>

//QT includes
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <qheader.h>
#include <qsplitter.h>

#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qcombobox.h>
#include <qptrlist.h>
#include <qstring.h>
#include <qinputdialog.h>
#include <qlabel.h>
#include <qmessagebox.h>
#include <qgroupbox.h>
#include <qsize.h>
#include <qradiobutton.h>
#include <qbuttongroup.h>
#include <qwidgetstack.h>

// project includes
#include "../core/kmfdoc.h"
#include "../core/kmfiptdoc.h"
#include "../core/iptchain.h"
#include "../core/iptrule.h"
#include "../core/kmfcheckinput.h"
#include "../core/kmferror.h"
#include "../core/kmferrorhandler.h"
#include "../core/kmfconfig.h"
#include "../core/kmfpluginfactory.h"
#include "../core/kmfappstate.h"

#include "../kmfwidgets/kmflistview.h"
#include "../kmfwidgets/kmflistviewitem.h"
#include "../kmfwidgets/kmfobjectinfo.h"
#include "../interfaces/kmfruleoptioneditinterface.h"
#include "../interfaces/kmfruletargetoptioneditinterface.h"

#include "kmfchainedit.h"
#include "kmfnewchaindlg.h"

KMFRuleEdit::KMFRuleEdit( QWidget* parent, const char* name, WFlags fl )
		: KMyFirewallRuleEditor( parent, name, fl ), KMFRuleEditInterface() {
	if ( !name )
		setName( "KMFRuleEdit" );
	loadIcons();
	m_editPlugins.clear();
	b_move_up->setPixmap( icon_up );
	b_move_down->setPixmap( icon_down );
	// need to remove dummy page from QTDesigner ;-)
	m_ws_target_opt->removeWidget( page );

	m_err = new KMFError();
	m_err_handler = new KMFErrorHandler( "KMFRuleEdit" );
	kb_optSelect->clear();
	connect( kb_optSelect, SIGNAL( activated( int ) ) , this, SLOT( slotNewOptionType( int ) ) );

	m_lv_table_filter = new KMFListView( m_widgetStack, "m_lv_table_filter" );
	m_lv_table_filter->show();

	connect( m_lv_table_filter, SIGNAL( contextMenuRequested ( QListViewItem*, const QPoint&, int ) ),
	         this, SLOT( slotRuleRBM( QListViewItem*, const QPoint&, int ) ) );

	connect( m_lv_table_filter, SIGNAL( itemRenamed ( QListViewItem*, int, const QString& ) ),
	         this, SLOT( slotRenameRule( QListViewItem*, int, const QString& ) ) );

	connect( m_lv_table_filter, SIGNAL( clicked( QListViewItem* ) ),
	         this, SLOT( slotNewItemSelected( QListViewItem* ) ) );

	m_widgetStack->addWidget( m_lv_table_filter );


	m_lv_table_nat = new KMFListView( m_widgetStack, "m_lv_table_nat" );
	m_lv_table_nat->show();

	connect( m_lv_table_nat, SIGNAL( contextMenuRequested ( QListViewItem*, const QPoint&, int ) ),
	         this, SLOT( slotRuleRBM( QListViewItem*, const QPoint&, int ) ) );

	connect( m_lv_table_nat, SIGNAL( itemRenamed ( QListViewItem*, int, const QString& ) ),
	         this, SLOT( slotRenameRule( QListViewItem*, int, const QString& ) ) );

	connect( m_lv_table_nat, SIGNAL( clicked( QListViewItem* ) ),
	         this, SLOT( slotNewItemSelected( QListViewItem* ) ) );

	m_widgetStack->addWidget( m_lv_table_nat );

	m_lv_table_mangle = new KMFListView( m_widgetStack, "m_lv_table_mangle" );
	m_lv_table_mangle->show();

	connect( m_lv_table_mangle, SIGNAL( contextMenuRequested ( QListViewItem*, const QPoint&, int ) ),
	         this, SLOT( slotRuleRBM( QListViewItem*, const QPoint&, int ) ) );

	connect( m_lv_table_mangle, SIGNAL( itemRenamed ( QListViewItem*, int, const QString& ) ),
	         this, SLOT( slotRenameRule( QListViewItem*, int, const QString& ) ) );

	connect( m_lv_table_mangle, SIGNAL( clicked( QListViewItem* ) ),
	         this, SLOT( slotNewItemSelected( QListViewItem* ) ) );

	m_widgetStack->addWidget( m_lv_table_mangle );
	
	m_splitter->setResizeMode( gb_options, QSplitter::KeepSize );

	m_editchain = new KMFChainEdit( this, "chianditor", 0 );
	kdDebug() << "CONNECTING CHAINEDITOR" << endl;
	connect( m_editchain, SIGNAL( sigHideMe() ),
	         this, SLOT( slotShowOverview() ) );
	m_widgetStack->addWidget( m_editchain );


	m_object_info = new KMFObjectInfo( this, "rule info" );
	connect( m_object_info, SIGNAL( sigHideMe() ),
	         this, SLOT( slotShowOverview() ) );

	m_widgetStack->addWidget( m_object_info );

	m_new_chain = new KMFNewChainDlg();
	connect( m_new_chain, SIGNAL( sigUpdateView() ),
	         this, SIGNAL( sigUpdateView() ) );


	m_check_input = new KMFCheckInput();
	m_contextMenu = new KPopupMenu( this );
	
	connect( cb_log_rule, SIGNAL( clicked() ),
	         this, SLOT( slotLogRuleChanged() ) );
	connect( cb_disable_rule, SIGNAL( clicked() ),
	         this, SLOT( slotEnableRuleChanged() ) );
	rb_filter->setChecked( true );
	
	loadPlugins();
	
	m_rule = 0;
	m_chain = 0;
	m_table = 0;
	kmfdoc = 0;
	m_widgetStack->show();
	slotNewTableSelected();
	slotShowOverview();
	adjustSize();
	show();
}

KMFRuleEdit::~KMFRuleEdit() {}

void KMFRuleEdit::slotSelectionInvalid() {
	m_rule = 0;
	m_chain = 0;
	m_table = 0;
}

void KMFRuleEdit::loadDoc( KMFIPTDoc* doc ) {
	kdDebug() << "void KMFRuleEdit::loadDoc(KMFIPTDoc* doc)" << endl;
	if ( doc == 0 ) {
		m_err->setErrType(KMFError::NORMAL );
		const QString& msg = i18n( "KMFRuleEdit:::loadDoc(KMFIPTDoc* doc)\n"
		                           "KMFIPTDoc* doc == 0. This is a bug." );
		m_err->setErrMsg( msg );
		m_err_handler->showError( m_err );
		setEnabled( false );
		return ;
	}

	if ( !isEnabled() )
		setEnabled( true );
	kmfdoc = doc;
// 	m_output_viewer->loadDoc( kmfdoc );

	rb_filter->setEnabled( kmfdoc->useFilter() );
	rb_mangle->setEnabled( kmfdoc->useMangle() );
	rb_nat->setEnabled( kmfdoc->useNat() );
	if ( kmfdoc->useModules() ) {
		m_led_modules->setColor( green );
		m_led_modules->on();
	} else {
		m_led_modules->setColor( red );
		m_led_modules->off();
	}

	if ( kmfdoc->useIPFwd() ) {
		m_led_fwd->setColor( green );
		m_led_fwd->on();
	} else {
		m_led_fwd->setColor( red );
		m_led_fwd->off();
	}

	if ( kmfdoc->useSynCookies() ) {
		m_led_syn->setColor( green );
		m_led_syn->on();
	} else {
		m_led_syn->setColor( red );
		m_led_syn->off();
	}

	if ( kmfdoc->useRPFilter() ) {
		m_led_rp->setColor( green );
		m_led_rp->on();
	} else {
		m_led_rp->setColor( red );
		m_led_rp->off();
	}

	if ( kmfdoc->useMartians() ) {
		m_led_martians->setColor( green );
		m_led_martians->on();
	} else {
		m_led_martians->setColor( red );
		m_led_martians->off();
	}
	

	
	IPTable *filter = 0;
	filter = kmfdoc->table( "filter" );
	if ( filter ) {
		m_lv_table_filter->clearAllItems();
		m_lv_table_filter->slotLoadNode( filter );
	}

//	IPTable *def = 0;
	IPTable *nat = 0;
	nat = kmfdoc->table( "nat" );
	if ( nat ) {
		m_lv_table_nat->clearAllItems();
		m_lv_table_nat->slotLoadNode( nat );
	}
	
	IPTable *mangle = 0;
	mangle = kmfdoc->table( "mangle" );
	if ( mangle ) {
		m_lv_table_mangle->clearAllItems();
		m_lv_table_mangle->slotLoadNode( mangle );
	}
	
	m_rule = 0;
	m_chain = 0;
	m_table = 0;
	
	enableRuleEdit( false );
	slotShowOverview();
	// if ( KMFAppState::upAndRunning() ) {
		rb_filter->setChecked( true );
		slotNewTableSelected();
		emit sigUpdateView();
	//}
}

void KMFRuleEdit::slotLoadDocument( KMFIPTDoc * doc ) {
	kdDebug() << "KMFRuleEdit::slotLoadDocument( KMFIPTDoc* doc )" << endl;
	slotShowOverview();
	loadDoc( doc );
}


void KMFRuleEdit::loadPlugins() {
	kdDebug() << "KMFRuleEdit::loadPlugins()" << endl;
	
	QPtrListIterator<KMFRuleOptionEditInterface> it( *KMFPluginFactory::KMFRuleOptionEditors( this ) );
	while( it.current() ) {
		registerRuleOptionPlugin( it.current() );
		++it;
	}
	
	QPtrListIterator<KMFRuleTargetOptionEditInterface> it2(  *KMFPluginFactory::KMFRuleTargetOptionEditors( this ) );
	while( it2.current() ) {
		registerRuleTargetOptionPlugin( it2.current() );
		++it2;
	}
	
}

void KMFRuleEdit::registerRuleOptionPlugin( KMFRuleOptionEditInterface* edit ) {
	m_widgetStack->addWidget( edit->editWidget() );
	m_editPlugins.append( edit );
	kb_optSelect->insertItem( i18n("Edit %1").arg( edit->optionEditName() ) );
}

void KMFRuleEdit::registerRuleTargetOptionPlugin( KMFRuleTargetOptionEditInterface* edit ) {
	m_ws_target_opt->addWidget( edit->editWidget() );
	m_editTargetPlugins.append( edit );
}



KMFListView* KMFRuleEdit::currTableView() {
	if ( rb_filter->isChecked() && rb_filter->isEnabled() ) {
		return m_lv_table_filter;
	} else if ( rb_nat->isChecked() && rb_nat->isEnabled() ) {
		return m_lv_table_nat;
	} else if ( rb_mangle->isChecked() && rb_mangle->isEnabled() ) {
		return m_lv_table_mangle;
	} else {
		kdDebug() << "ERROR: currTableView() returning fallbvack table: filter !!!" << endl;
		return m_lv_table_filter;
	}
}





void KMFRuleEdit::slotNewTableSelected() {
	kdDebug() << "void KMFRuleEdit::slotNewTableSelected()" << endl;
	if ( kmfdoc == 0 ) {
		setEnabled( false );
		return ;
	}
	QString table = "filter";
	if ( !rb_filter->isEnabled() )
		rb_filter->setChecked( false );
	if ( !rb_nat->isEnabled() )
		rb_nat->setChecked( false );
	if ( !rb_mangle->isEnabled() )
		rb_mangle->setChecked( false );


	if ( rb_filter->isChecked() && rb_filter->isEnabled() ) {
		table = "filter";
		kdDebug() << "Enabling Filter View" << endl;
		setCurrTableView( m_lv_table_filter );
	} else if ( rb_nat->isChecked() && rb_nat->isEnabled() ) {
		setEnabled( true );
		table = "nat";
		setCurrTableView( m_lv_table_nat );
	} else if ( rb_mangle->isChecked() && rb_mangle->isEnabled() ) {
		setEnabled( true );
		table = "mangle";
		setCurrTableView( m_lv_table_mangle );
	} else {
		setEnabled( true );
		table = "filter";
		setCurrTableView( m_lv_table_filter );
		return;
	}

	IPTable *tab = kmfdoc->table( table );
	if ( tab == 0 ) {
		setEnabled( false );
		kdDebug() << "Table: " << table << " not found in document!!" << table << endl;
		return ;
	}

	m_table = tab;
	slotShowOverview();
}
void KMFRuleEdit::setCurrTableView( KMFListView* lv ) {
	kdDebug() << "void KMFRuleEdit::setCurrTableView( KMFListView* lv )" << endl;
	if ( lv == m_lv_table_filter ) {
		setEnabled( true );
		kdDebug() << "Enabling Filter View" << endl;
		m_lv_table_filter->setEnabled( true );
		connect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_filter, SLOT( slotUpdateView() ) );
		connect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_filter, SLOT( slotUpdateView( NetfilterObject* ) ) );

		kdDebug() << "Disabling Nat View" << endl;
		m_lv_table_nat->setEnabled( false );
		disconnect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_nat, SLOT( slotUpdateView() ) );
		disconnect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_nat, SLOT( slotUpdateView( NetfilterObject* ) ) );

		kdDebug() << "Disabling Mangle View" << endl;
		m_lv_table_mangle->setEnabled( false );
		disconnect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_mangle, SLOT( slotUpdateView() ) );
		disconnect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_mangle, SLOT( slotUpdateView( NetfilterObject* ) ) );
	} else if  ( lv == m_lv_table_nat ) {
		setEnabled( true );
		kdDebug() << "Disabling Filter View" << endl;
		m_lv_table_filter->setEnabled( false );
		disconnect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_filter, SLOT( slotUpdateView() ) );
		disconnect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_filter, SLOT( slotUpdateView( NetfilterObject* ) ) );

		kdDebug() << "Enabling Nat View" << endl;
		m_lv_table_nat->setEnabled( true );
		connect( this, SIGNAL( sigUpdateView() ),
			m_lv_table_nat, SLOT( slotUpdateView() ) );
		connect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
			m_lv_table_nat, SLOT( slotUpdateView( NetfilterObject* ) ) );

		kdDebug() << "Disabling Mangle View" << endl;
		m_lv_table_mangle->setEnabled( false );
		disconnect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_mangle, SLOT( slotUpdateView() ) );
		disconnect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_mangle, SLOT( slotUpdateView( NetfilterObject* ) ) );
	} else if  ( lv == m_lv_table_mangle ) {
		setEnabled( true );

		kdDebug() << "Disabling Filter View" << endl;
		m_lv_table_filter->setEnabled( false );
		disconnect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_filter, SLOT( slotUpdateView() ) );
		disconnect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_filter, SLOT( slotUpdateView( NetfilterObject* ) ) );

		kdDebug() << "Disabling Nat View" << endl;
		m_lv_table_nat->setEnabled( false );
		disconnect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_mangle, SLOT( slotUpdateView() ) );
		disconnect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_mangle, SLOT( slotUpdateView( NetfilterObject* ) ) );

		kdDebug() << "Enabling Mangle View" << endl;
		m_lv_table_mangle->setEnabled( true );
		connect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_mangle, SLOT( slotUpdateView() ) );
		connect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_mangle, SLOT( slotUpdateView( NetfilterObject* ) ) );
	} else  if ( ! lv ){
		kdDebug() << "Disabling Filter View" << endl;
		m_lv_table_filter->setEnabled( false );
		disconnect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_filter, SLOT( slotUpdateView() ) );
		disconnect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_filter, SLOT( slotUpdateView( NetfilterObject* ) ) );

		kdDebug() << "Disabling Nat View" << endl;
		m_lv_table_nat->setEnabled( false );
		disconnect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_mangle, SLOT( slotUpdateView() ) );
		disconnect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_mangle, SLOT( slotUpdateView( NetfilterObject* ) ) );

		kdDebug() << "Disabling Mangle View" << endl;
		m_lv_table_mangle->setEnabled( false );
		disconnect( this, SIGNAL( sigUpdateView() ),
	         m_lv_table_mangle, SLOT( slotUpdateView() ) );
		disconnect( this, SIGNAL( sigUpdateView( NetfilterObject* ) ),
	         m_lv_table_mangle, SLOT( slotUpdateView( NetfilterObject* ) ) );
	}
}

void KMFRuleEdit::slotNewItemSelected( QListViewItem* item ) {
	kdDebug() << "KMFRuleEdit::slotNewItemSelected( QListViewItem* item )" << endl;
	if ( ! item )
		return ;
	if ( KMFListViewItem * kmf_item = dynamic_cast<KMFListViewItem*>( item ) ) {
		IPTRuleOption * opt = 0;
		switch( kmf_item->type() ) {
			case KMFListViewItem::TABLE:
				m_rule = 0;
				m_chain = 0;
				m_table = kmf_item->table();
				slotEditRule();
				break;
			case KMFListViewItem::CHAIN:
				m_rule = 0;
				m_chain = kmf_item->chain();
				m_table = m_chain->table();
				slotEditRule();
				break;
			case KMFListViewItem::RULE:
				m_rule = kmf_item->rule();
				m_chain = m_rule->chain();
				m_table = m_rule->chain() ->table();
				slotEditRule();
				break;
			case KMFListViewItem::RULEOPTION:
				opt = kmf_item->ruleOption();
				m_rule = opt->rule();
				m_chain = opt->rule() ->chain();
				m_table = opt->rule() ->chain() ->table();
				slotEditRule();
				break;
			default:
				kdDebug() << "Strange? KMFListViewItem * kmf_item>type() NOT VALID" << endl;
				m_rule = 0;
				m_chain = 0;
				m_table = 0;
				break;
		}
	}
}

void KMFRuleEdit::slotAddRule() {
	kdDebug() << "KMFRuleEdit::slotAddRule()" << endl;
	if ( ! m_chain ) {
		KMessageBox::sorry( this, i18n( "<qt>No Chain Found to add the Rule.<br>"
		                                "Please make sure that you selected a Chain or Rule before you try to add a Rule." ),
		                    i18n( "Sorry" ) );
		return ;
	}
	bool ok = FALSE;
	const QString greeting = i18n( "New Rule" );
	const QString label = i18n( "Please enter a name for the new rule:" );
	QString text = QInputDialog::getText( greeting, label, QLineEdit::Normal, QString::null, &ok, this, "dsa" );
	if ( ok && !text.isEmpty() ) {
		kdDebug() << "Adding Rule Named: " << text << endl;
		QString ch = m_chain->name();
		kdDebug() << "For Chain: " << ch << endl;
		QString tab = m_chain->table() ->name();
		kdDebug() << "In Table: " << tab << endl;
		QString target = "ACCEPT";
		kdDebug() << "With Target: " << target << endl;
		if ( !text.isEmpty() && !ch.isEmpty() && !tab.isEmpty() && !target.isEmpty() ) {
			m_check_input->checkInput( text, "RULENAME", m_err );
			if ( m_err_handler->showError( m_err ) ) {
				kmfdoc->startTransaction();
				m_chain->saveState();
				IPTRule *inserted = m_chain->addRule( text, m_err );
				if ( m_err_handler->showError( m_err ) ) {
					if ( m_rule ) {
						m_chain->moveRule( inserted, ( m_rule->ruleNum() ) -inserted->ruleNum() );
					}
					kmfdoc->changed();
				}
				kmfdoc->endTransaction();
				m_rule = inserted;
				emit sigUpdateView( m_chain );
			}
		} else {
			KMessageBox::sorry( this, i18n( "An error occurred while trying to setup a new rule." ), i18n( "Rule Editor" ) );
		}
	}
}

void KMFRuleEdit::slotAddChain() {
	if ( m_table ) {
		m_new_chain->loadDoc( m_table->kmfDoc() );
		m_new_chain->exec();
	}
}

void KMFRuleEdit::slotDelChain() {
	kdDebug() << "void KMFView::slotDelChain()" << endl;
	if ( ! m_chain ) {
		KMessageBox::sorry( this, i18n( "<qt>No Chain Found for deleting.<br>"
		                                "Please make sure that you selected a Chain or Rule before you try to delete the current chain." ),
		                    i18n( "Sorry" ) );
		return ;
	}

	if ( m_chain->isBuildIn() ) {
		KMessageBox::sorry( this, i18n( "<qt><b>Cannot delete built-in chain: %1</b><br>"
		                                "Built-in chains cannot be deleted; you can only delete chains "
		                                "that you have defined yourself." ).arg( m_chain->name() ),
		                    i18n( "Sorry" ) );
		return ;
	}
	int doit = KMessageBox::questionYesNo ( this , i18n( "<p>Are you sure that you want to delete "
	                                        "chain: <b>%1</b> from table: <b>%2</b>?<br>"
	                                        "<b>Note:</b> By deleting the chain all rules that belong "
	                                        "to the chain will be deleted too." ).arg( m_chain ->name() ).arg( m_chain ->table() ->name() ),
	                                        i18n( "Delete Chain" ), KStdGuiItem::yes(), KStdGuiItem::no(), "main_view_delete_chain" );
	kdDebug() << "Message Box returned: " << doit << endl;
	if ( doit == 3 ) {
		kdDebug() << "Try to delete Chain" << endl;
		kmfdoc->startTransaction();
		m_table->saveState();
		m_err = kmfdoc->table( m_chain->table()->name() )->delChain( m_chain );
		if ( m_err_handler ->showError( m_err ) ) {
			emit sigUpdateView();
			m_chain = 0;
			m_rule = 0;
			m_table = 0;
		}
		kmfdoc->endTransaction();
	}
}

void KMFRuleEdit::slotEditRule() {
	m_ws_target_opt->setEnabled(false);	
	if ( ! KMFAppState::upAndRunning() || ! KMFAppState::hasOpenDoc() ) {
		slotSelectionInvalid();
		return;
	}


	if ( m_rule ) {
		l_editing_rule->setText( "<b>Chain: </b>" + m_rule->chain()->name() + "<br><b>Rule: </b>" + m_rule->name() );
		kb_optSelect->setEnabled( true );
		cb_log_rule ->setEnabled( true );
		cb_disable_rule ->setEnabled( true );
		cb_target ->setEnabled( true );
		cb_frag ->setEnabled( true );
		QString target = m_rule->target();
		cb_target->clear();
		const QStringList& list = m_rule->availableTargets();
		cb_target->insertStringList( list );
		bool found = false;
		for ( int i = 0; i < cb_target->count() && ! found; i++ ) {
			if ( !cb_target->text( i ).isNull() && cb_target->text( i ) == m_rule->target( ) ) {
				cb_target->setCurrentItem( i );
				found = true;
			}
		}

		slotEditTargetOption();
		IPTRuleOption *opt = m_rule->getOptionForName( "frag_opt" );
		if ( !opt->isEmpty() ) {
			QStringList vals = opt->getValues();
			if ( *vals.at( 0 ) == "bool:on" && *vals.at( 0 ) == "bool:off" ) {
				cb_frag->setChecked( true );
				cb_frag_inv->setChecked( false );
			} else if ( *vals.at( 0 ) == "bool:off" && *vals.at( 1 ) == "bool:on" ) {
				cb_frag->setChecked( true );
				cb_frag_inv->setChecked( true );
			} else {
				cb_frag->setChecked( false );
				cb_frag_inv->setChecked( false );
			}
		} else {
			cb_frag->setChecked( false );
			cb_frag_inv->setChecked( false );
		}

		cb_disable_rule->setChecked( ! m_rule->enabled() );
		cb_log_rule->setChecked( m_rule->logging() );
		enableRuleEdit( true );

		//*********************************
	} else if ( m_chain ) {
		l_editing_rule->setText( "<b>Chain: </b>" + m_chain->name() + "<br><b>Rule: </b>No rule selected" );
		kb_optSelect->setEnabled( false );
		cb_log_rule ->setEnabled( false );
		cb_disable_rule ->setEnabled( false );
		cb_target ->setEnabled( false );
		cb_frag ->setEnabled( false );
		m_ws_target_opt->setEnabled( false );
		enableRuleEdit( false );
	} else {
		l_editing_rule->setText( "<b>Chain: </b>No chain selected<br><b>Rule: </b>No rule selected" );
		kb_optSelect->setEnabled( false );
		cb_log_rule ->setEnabled( false );
		cb_disable_rule ->setEnabled( false );
		cb_target ->setEnabled( false );
		cb_frag ->setEnabled( false );
		m_ws_target_opt->setEnabled( false );
		enableRuleEdit( false );
	}
}

void KMFRuleEdit::enableRuleEdit( bool on ) {
	if ( on ) {
		b_move_up->setEnabled( true );
		b_move_down->setEnabled( true );
		kb_optSelect->setEnabled( true );
		cb_log_rule ->setEnabled( true );
		cb_disable_rule ->setEnabled( true );
		cb_target ->setEnabled( true );
		cb_frag ->setEnabled( true );
	} else {
		kb_optSelect->setEnabled( false );
		b_move_up->setEnabled( false );
		b_move_down->setEnabled( false );
		cb_log_rule ->setEnabled( false );
		cb_disable_rule ->setEnabled( false );
		cb_target ->setEnabled( false );
		cb_frag ->setEnabled( false );
		m_ws_target_opt->setEnabled( false );
	}
}

void KMFRuleEdit::slotMoveRuleDown() {
	kdDebug() << "KMFRuleEdit::slotMoveRuleDown()" << endl;
	if ( m_rule  && kb_optSelect->isEnabled() ) {
		kmfdoc->startTransaction();
		m_chain->saveState();
		if ( m_chain->moveRule( m_rule, 1 ) ) {
			kmfdoc->changed();
			KMFListViewItem* item = currTableView() ->findKMFItem( m_rule->name(),2, m_rule->objectID() );
			if ( item )
				currTableView()->setSelected( item, true);
			item->loadNetfilterObject( m_rule );
			emit sigUpdateView( m_rule->chain() );
		}
		kmfdoc->endTransaction();
	}
}

void KMFRuleEdit::slotMoveRuleUp() {
	kdDebug() << "KMFRuleEdit::slotMoveRuleUp()" << endl;
	if ( m_rule && kb_optSelect->isEnabled() ) {
		KMFListViewItem* item = currTableView() ->findKMFItem( m_rule->name(),2, m_rule->objectID() );
		if ( item ) {
			kmfdoc->startTransaction();
			m_chain->saveState();
			if ( m_chain->moveRule( m_rule, -1 ) ) {
				kmfdoc->changed();
				currTableView()->setSelected( item, true );
				item->loadNetfilterObject( m_rule );
				emit sigUpdateView( m_rule->chain()  );
			}
			kmfdoc->endTransaction();
		}
	}
}

void KMFRuleEdit::slotDelRule() {
	kdDebug() << "KMFRuleEdit::slotDelRule()" << endl;
	if ( ! m_rule || ! m_chain ) {
		KMessageBox::sorry( this, i18n( "<qt>No Rule defined to delete.<br>"
		                                "Please make sure that you selected a Rule before you try to delete one." ),
		                    i18n( "Sorry" ) );
		return ;
	} else {
		int doit = KMessageBox::questionYesNo ( this , i18n( "<p>Are you sure that you want to delete "
		                                        "rule: <b>%1</b> from chain: <b>%2</b>?</p>").arg( m_rule->name() ).arg( m_rule->chain() ->name() ),
		                                        i18n( "Delete Rule" ), KStdGuiItem::yes(), KStdGuiItem::no(), "rule_edit_delete_rule" );
		kdDebug() << "Message Box returned: " << doit << endl;
		if ( doit == 3 ) { // OK clicked
			kdDebug() << "clicked ok" << endl;
			kmfdoc->startTransaction();
			m_chain->saveState();
			m_err = m_chain->delRule( m_rule );
			m_err_handler->showError( m_err );
			kmfdoc->changed();
			kdDebug() << "KMFRuleEdit::slotDelRule()\nCalling: kmfdoc->updateView()" << endl;
			m_rule = 0;
			slotEditRule();
			kmfdoc->endTransaction();
			if ( m_chain )
				emit sigUpdateView( m_chain );
			else
				emit sigUpdateView();
		}
	}
}
void KMFRuleEdit::showOverview() {
	slotShowOverview();
}

void KMFRuleEdit::slotShowOverview() {
	kdDebug() << "\nKMFRuleEdit::slotShowOverview()\n" << endl;
	if ( rb_filter->isChecked() ) {
		m_widgetStack->raiseWidget( m_lv_table_filter );
	} else if ( rb_nat->isChecked() ) {
		m_widgetStack->raiseWidget( m_lv_table_nat );
	} else if ( rb_mangle->isChecked() ) {
		m_widgetStack->raiseWidget( m_lv_table_mangle );
	}
	if ( kmfdoc )
		kmfdoc->endTransaction();
	if ( m_table )
		emit sigUpdateView();
	slotEditRule();
}

void KMFRuleEdit::slotNewOptionType( int index ) {
	kdDebug() << "KMFRuleEdit::slotNewOptionType( index " << index << " )" << endl;
	if ( index > -1 ) {
		slotEditRule();
		if ( ! m_rule )
			return;
		m_editPlugins.at( index )->loadRule( m_rule );
		m_widgetStack->raiseWidget( m_editPlugins.at( index )->editWidget() );
	}
}



// void KMFRuleEdit::slotEditCustomOpt() {
/*	kdDebug() << "KMFRuleEdit::slotEditTosOpt()" << endl;
	slotEditRule();
	if ( ! m_rule )
		return;
	KMessageBox::information ( this , i18n( "<qt><p>You are about to define custom options for this rule.<br>"
	                                        "There will be <b>no sanity checks</b> for your input, so please make sure "
	                                        "that your options are working and the syntax is correct.</p></qt>" ),
	                           i18n( "Information" ), "custom_option_warning" );
	m_custom_opt->loadRule( m_rule );
	m_widgetStack->raiseWidget( m_custom_opt );*/
// }

void KMFRuleEdit::slotEditRuleInfo() {
	slotEditRule();
	if ( ! m_rule )
		return;
	m_object_info->loadNetfilterObject( m_rule );
	m_widgetStack->raiseWidget( m_object_info );
}

void KMFRuleEdit::slotEditChainInfo() {
	slotEditRule();
	if ( ! m_chain )
		return;
	m_object_info->loadNetfilterObject( m_chain );
	m_widgetStack->raiseWidget( m_object_info );
}

void KMFRuleEdit::slotEditTargetOption() {
	kdDebug() << "void KMFRuleEdit::slotEditTargetOption()\n Target: " << cb_target->currentText() << endl;
	if ( ! m_rule )
		return;
	QString target = cb_target->currentText();
	QPtrListIterator<KMFRuleTargetOptionEditInterface> it( m_editTargetPlugins );
	m_ws_target_opt->setEnabled( false );
	while ( it.current() ) {
		KMFRuleTargetOptionEditInterface *edit = it.current();
		++it;
		if ( edit->manageTarget( target ) ) {
			m_ws_target_opt->setEnabled( true );
			edit->setTarget( target );
			edit->loadRule( m_rule );
			m_ws_target_opt->raiseWidget( edit->editWidget() );
			return;
		}
	}
	
	
	
	
	
// 	if ( target == "LOG" ) {
// 		m_ws_target_opt->setEnabled( true );
// 		m_tglog ->loadRule( m_rule );
// 		m_ws_target_opt->raiseWidget( m_tglog );
// 	} else if ( target == "SNAT" ) {
// 		m_ws_target_opt->setEnabled( true );
// 		m_tgnat ->setMode( true );
// 		m_tgnat ->loadRule( m_rule );
// 		m_ws_target_opt->raiseWidget( m_tgnat );
// 	} else if ( target == "DNAT" ) {
// 		m_ws_target_opt->setEnabled( true );
// 		m_tgnat ->setMode( false );
// 		m_tgnat ->loadRule( m_rule );
// 		m_ws_target_opt->raiseWidget( m_tgnat );
// 	} else if ( target == "TOS" ) {
// 		m_ws_target_opt->setEnabled( true );
// 		m_tosed->setType( "SETTOS" );
// 		m_tosed->loadRule( m_rule );
// 		m_ws_target_opt->raiseWidget( m_tosed );
// 	} else if ( target == "REJECT" ) {
// 		m_ws_target_opt->setEnabled( true );
// 		m_tosed->setType( "REJECTTYPE" );
// 		m_tosed->loadRule( m_rule );
// 		m_ws_target_opt->raiseWidget( m_tosed );
// 	} else if ( target == "MARK" ) {
// 		m_ws_target_opt->setEnabled( true );
// 		m_tgmark->loadRule( m_rule );
// 		m_ws_target_opt->raiseWidget( m_tgmark );
// 	} else {
// 		m_ws_target_opt->setEnabled( false );
// 	}
}


void KMFRuleEdit::slotEditChain() {
	kdDebug() << "void KMFRuleEdit::slotEditChain()" << endl;
	if ( ! m_chain )
		return;
	m_editchain -> loadChain( m_chain );
	m_widgetStack->raiseWidget( m_editchain );
}

// Slots For Rule Edit Changes
void KMFRuleEdit::slotFragChanged() {
	kdDebug() << "KMFRuleEdit::slotFragChanged(bool frag)" << endl;
	if ( !m_rule )
		return ;
	bool frag = cb_frag->isChecked();
	bool frag_inv = cb_frag_inv->isChecked();

	QPtrList<QString>* vals = new QPtrList<QString>;
	QString* cmd = new QString( "frag_opt" );
	if ( frag ) {
		if ( frag_inv ) {
			vals->append( new QString( "bool:off" ) );
			vals->append( new QString( "bool:on" ) );
		} else {
			vals->append( new QString( "bool:on" ) );
			vals->append( new QString( "bool:off" ) );
		}
	} else {
		vals->append( new QString( "bool:off" ) );
		vals->append( new QString( "bool:off" ) );
	}
	kmfdoc->startTransaction();
	m_rule->saveState();
	m_rule->addRuleOption( *cmd, *vals );
	kmfdoc->changed();
	kmfdoc->endTransaction();
	emit sigUpdateView( m_rule );
}

void KMFRuleEdit::slotLogRuleChanged() {
	if ( !m_rule )
		return ;
	kmfdoc->startTransaction();
	m_rule->saveState();
	if ( cb_log_rule->isChecked() )
		m_rule->setLogging( true );
	else
		m_rule->setLogging( false );
	kmfdoc->changed();
	kmfdoc->endTransaction();
	emit sigUpdateView( m_rule );
}

void KMFRuleEdit::slotEnableRuleChanged() {
	if ( !m_rule )
		return ;
	kmfdoc->startTransaction();
	m_rule->saveState();
	if ( cb_disable_rule->isChecked() ) {
		m_rule->setEnabled( false );
	} else {
		m_rule->setEnabled( true );
	}
	kmfdoc->changed();
	kmfdoc->endTransaction();
	emit sigUpdateView( m_rule );
	slotEditRule();
}

void KMFRuleEdit::slotTargetChanged( const QString & tg ) {
	kdDebug() << "KMFRuleEdit::slotTargetChanged(const QString&)" << endl;
	if ( !m_rule )
		return ;

	if ( !tg.isEmpty() ) {
		if ( tg == m_rule->chain() ->name() ) {
			KMessageBox::sorry( this, i18n( "<qt><p>Sorry, you <b>cannot</b> set the target of this rule to be its own chain. "
			                                "Constructing endless loops is not allowed.</qt>" ) );
			return ;
		}
		if ( m_rule->target() == "LOG" || m_rule->target() == "REJECT" ||
		        m_rule->target() == "SNAT" || m_rule->target() == "DNAT" ||
		        m_rule->target() == "MARK" || m_rule->target() == "TOS" ) {
			int ans = KMessageBox::questionYesNo( this, i18n( "<qt>By changing the Target of the Rule all previous"
			                                      " defined <b>Target Options</b> will be deleted.<br>"
			                                      "Click <b>Continue</b> to change the Target.<br>"
			                                      "Click <b>Cancel</b> keep your current Target. </qt>" ), i18n( "Warning" ), KStdGuiItem::cont(), KStdGuiItem::cancel(), "change_target_option_warning" );
			kdDebug() << "\n\n\nKMessageBox:: Returned" << ans << "\n\n\n" << endl;
			switch ( ans ) {

			case 3:
				kdDebug() << "Clicked Continue" << endl;
				if ( m_rule->target() != tg ) {
					kmfdoc->startTransaction();
					m_rule->saveState();
					m_rule->setTarget( tg );
					kmfdoc->changed();
					emit sigUpdateView();
					kmfdoc->endTransaction();
				}
				break;
			case 2:
				kdDebug() << "Canceled Target Change" << endl;
				slotEditRule();
				slotEditTargetOption();
				return ;
				break;
			}
		} else {
			if ( m_rule->target() != tg ) {
				kmfdoc->startTransaction();
				m_rule->saveState();
				m_rule->setTarget( tg );
				kmfdoc->changed();
				emit sigUpdateView();
				kmfdoc->endTransaction();
			}
		}
		slotEditTargetOption();
	}
}

void KMFRuleEdit::addRuleOption(QString* name, QPtrList< QString >* values){
	slotAddRuleOption( name, values );
}

void KMFRuleEdit::slotAddRuleOption( QString * name, QPtrList<QString>* values ) {
	kdDebug() << "KMFRuleEdit::slotAddRuleOption(QString* name, QPtrList<QString>* values)" << endl;
	m_rule->addRuleOption( *name, *values );
	kmfdoc->changed();
	emit sigUpdateView( m_rule );
}

void KMFRuleEdit::addRuleTargetOption(QString* name, QPtrList< QString >* values ){
	slotAddTargetOption( name, values );
} 

void KMFRuleEdit::slotAddTargetOption( QString * name, QPtrList<QString>* values ) {
	kdDebug() << "KMFRuleEdit::slotAddTargetOption(QString* name, QPtrList<QString>* values)" << endl;
	m_rule->addTargetOption( *name, *values );
	emit sigUpdateView( m_rule );
}

void KMFRuleEdit::slotRuleRBM( QListViewItem * item, const QPoint & point, int ) {
	kdDebug() << "void KMFRuleEdit::RBM(QListViewItem* item, const QPoint & point, int)" << endl;
	if ( ! item ) {
		 if ( m_table ) {
			createRBM( m_table );
			m_contextMenu->popup( point );
		} else {
			return ;
		}
	}
	if ( KMFListViewItem * tmp_item = dynamic_cast<KMFListViewItem*>( item ) ) {
		slotNewItemSelected( item );
		if ( ( tmp_item->type() == KMFListViewItem::RULE || tmp_item->type() == KMFListViewItem::RULEOPTION )&& m_rule ) {
			createRBM( m_rule );
			m_contextMenu->popup( point );
		} else if ( tmp_item->type() == KMFListViewItem::CHAIN && m_chain ) {
			createRBM( m_chain );
			m_contextMenu->popup( point );
		} else if ( tmp_item->type() == KMFListViewItem::TABLE && m_table ) {
			createRBM( m_table );
			m_contextMenu->popup( point );
		} else {
			m_contextMenu->clear();
		}
	} else  {
		kdDebug() << "CAST ERROR: KMFRuleEdit::slotRuleRBM(...) " << endl;
	}
}


void KMFRuleEdit::createRBM( NetfilterObject* obj ) {
	kdDebug() << "void createRBM( IPTChain* ){" << endl;
	if ( ! obj )
		return;
	switch( obj->type() ) {
		case NetfilterObject::TABLE:
		if ( IPTable* table =  dynamic_cast<IPTable*> ( obj ) ) {
			m_contextMenu->clear();
			QString name = table->name();
			QString lab_str = i18n("Table: %1").arg( name );

			m_contextMenu->insertTitle( lab_str );
			m_contextMenu->insertItem( icon_new, i18n( "Add Chain..." ), this, SLOT( slotAddChain() ) );
		}
		break;
		case NetfilterObject::CHAIN:
		if ( IPTChain* chain =  dynamic_cast<IPTChain*> ( obj ) ) {
			m_contextMenu->clear();
			QString name = chain->name();
			QString lab_str = i18n("Chain: %1").arg( name );

			m_contextMenu->insertTitle( icon_chain, lab_str );
			m_contextMenu->insertItem( icon_new, i18n( "Add Rule..." ), this, SLOT( slotAddRule() ) );
			m_contextMenu->insertSeparator();
			if ( ! chain->isBuildIn() )
				m_contextMenu->insertItem( icon_edit, i18n( "Chain Documentation" ), this, SLOT( slotEditChainInfo() ) );
			m_contextMenu->insertItem( icon_new, i18n( "Add Chain..." ), this, SLOT( slotAddChain() ) );
			m_contextMenu->insertItem( icon_edit, i18n( "Edit Chain" ), this, SLOT( slotEditChain() ) );
			if ( ! chain->isBuildIn() )
				m_contextMenu->insertItem( icon_del, i18n( "Delete Chain" ), this, SLOT( slotDelChain() ) );
		}
		case NetfilterObject::RULE:
		if ( IPTRule* rule =  dynamic_cast<IPTRule*> ( obj ) ) {
			m_contextMenu->clear();
			QString name = rule->name();
			QString lab_str = i18n("Rule: %1").arg( name );
			m_contextMenu->insertTitle( icon_rule, lab_str );

			KPopupMenu *sub_edit = new KPopupMenu( m_contextMenu );
			sub_edit->insertTitle( i18n( "Edit Rule Option" ) );
			for( uint i = 0; i < m_editPlugins.count(); i++ ) {
				sub_edit->insertItem( icon_edit, i18n( "Edit %1" ).arg(m_editPlugins.at(i)->optionEditName() ), i );
			}
			connect( sub_edit,SIGNAL(activated( int ) ), 
				this,SLOT(slotNewOptionType( int ) ) );			
			m_contextMenu->insertItem( i18n( "Edit Rule Option" ), sub_edit );
			// m_contextMenu->insertItem( icon_new, i18n( "Add Rule..." ), this, SLOT( slotAddRule() ) );
			m_contextMenu->insertItem( icon_new, i18n( "Insert Rule..." ), this, SLOT( slotAddRule() ) );
//			m_contextMenu->insertSeparator();
			m_contextMenu->insertItem( icon_del, i18n( "Delete Rule" ), this, SLOT( slotDelRule() ) );
			m_contextMenu->insertSeparator();
			m_contextMenu->insertItem( icon_rename, i18n( "Rename Rule" ), this, SLOT( slotRenameRule() ) );
			m_contextMenu->insertItem( icon_edit, i18n( "Rule Documentation" ), this, SLOT( slotEditRuleInfo() ) );
			m_contextMenu->insertItem( icon_up, i18n( "Move Up" ), this, SLOT( slotMoveRuleUp() ) );
			m_contextMenu->insertItem( icon_down, i18n( "Move Down" ), this, SLOT( slotMoveRuleDown() ) );
			m_contextMenu->insertSeparator();
			m_contextMenu->insertItem( icon_edit, i18n( "Edit Chain" ), this, SLOT( slotEditChain() ) );
			if ( ! rule->chain()->isBuildIn() )
				m_contextMenu->insertItem( icon_del, i18n( "Delete Chain" ), this, SLOT( slotDelChain() ) );
			m_contextMenu->insertSeparator();

			KPopupMenu *sub_copy = new KPopupMenu( m_contextMenu );
			connect( sub_copy, SIGNAL( activated( int ) ), this, SLOT( slotCopyRule( int ) ) );
			sub_copy->insertTitle( i18n( "Copy to Chain" ) );
			QPtrList<IPTChain> chains = m_table ->chains();
			for ( uint i = 0; i < chains.count(); i++ ) {
				QString tmp_name = chains.at( i ) ->name();
				sub_copy->insertItem( tmp_name, i );
			}
			m_contextMenu->insertItem( icon_copy, i18n( "Copy Rule" ), sub_copy );

			KPopupMenu *sub_move = new KPopupMenu( m_contextMenu );
			connect( sub_move, SIGNAL( activated( int ) ), this, SLOT( slotMoveRule( int ) ) );
			sub_move->insertTitle( i18n( "Move to Chain" ) );
			QPtrList<IPTChain> chains2 = m_table->chains();
			for ( uint i = 0; i < chains2.count(); i++ ) {
				QString tmp_name = chains2.at( i ) ->name();
				sub_move->insertItem( tmp_name, i );
			}
			m_contextMenu->insertItem( icon_move, i18n( "Move Rule" ), sub_move );
		}
	}
}


void KMFRuleEdit::slotMoveRule( int index ) {
	kdDebug() << "void KMFRuleEdit::slotCopyRule( int )" << endl;
	kdDebug() << "Move Rule  to Chain Nr: " << index << endl;
	IPTChain *chain_target = 0;
	chain_target = kmfdoc->table( m_table->name() ) ->chains().at( index );
	if ( chain_target ) {
		kmfdoc->startTransaction();
		m_rule->chain()->table()->saveState();
		chain_target->saveState();
		m_err = m_rule->chain() ->table() ->moveRuleToChain( m_rule, chain_target );
		m_err_handler->showError( m_err );
		kmfdoc->changed();
		kmfdoc->endTransaction();
		emit sigUpdateView();
	}
}

void KMFRuleEdit::slotCopyRule( int index ) {
	kdDebug() << "void KMFRuleEdit::slotCopyRule( int )" << endl;
	kdDebug() << "Move Rule  to Chain Nr: " << index << endl;
	IPTChain *chain_target = 0;
	chain_target = kmfdoc->table( m_table->name() ) ->chains().at( index );
	if ( chain_target ) {
		kmfdoc->startTransaction();
		m_rule->chain()->table()->saveState();
		chain_target->saveState();
		m_err = m_rule->chain() ->table() ->copyRuleToChain( m_rule, chain_target );
		m_err_handler->showError( m_err );
		kmfdoc->changed();
		kmfdoc->endTransaction();
		emit sigUpdateView();
	}
}

void KMFRuleEdit::slotRenameRule() {
	if ( ! m_rule )
		return;
	if ( KMFListViewItem* rule_item = currTableView()->findKMFItem( m_rule->name(),2,m_rule->objectID() ) ) {

		rule_item->startRename(2);
	}
}

void KMFRuleEdit::slotRenameRule( QListViewItem* , int, const QString& name ) {
	kdDebug() << "void KMFRuleEdit::slotRenameRule( QListViewItem* item, int, const QString& name )" << endl;
	if ( name.isNull() || name.isEmpty() ) {
		kdDebug() << "Rename rejected: Name was NULL or empty" << endl;
		return;
	}

// 	 if ( ! m_rule ) {
// 		kdDebug() << "Rename rejected: m_rule == 0:" << endl;
// 		return;
// 	}

	if ( KMFListViewItem* rule_item = currTableView()->findKMFItem( name ,2,m_rule->objectID() ) ) {
		kdDebug() << "Found Rule Item: " << name <<  " ID " << m_rule->objectID() << endl;
		QPtrList<IPTRule>& rules = rule_item->rule()->chain()->chainRuleset();
		IPTRule *rule = 0;
		for ( rule = rules.first(); rule; rule = rules.next() ) {
			if ( rule->name() == name ) {
				KMessageBox::sorry( this, i18n( "<qt><p>Sorry, there is already a rule named: <b>%1</b> in the chain.<br>"
												"Please make sure that the new rule name is unique in its chain.</qt>" ).arg( name ) );
				rule_item->setText( 2, rule_item->rule()->name() );
				emit sigUpdateView( rule_item->rule()->chain() );
				return ;
			}
		}
		kmfdoc->startTransaction();
		rule_item->rule()->saveState();
		QString origName = rule_item->rule()->name();
		m_err = rule_item->rule()->setName( name );
		if ( m_err_handler->showError( m_err ) ) {
			kmfdoc->changed();
		} else {
			rule_item->setText( 2, origName );
		}
		kmfdoc->endTransaction();
		emit sigUpdateView( rule_item->rule()->chain()->table() );
	}
}

void KMFRuleEdit::slotUpdateView() {
	kdDebug() << "void KMFRuleEdit::slotUpdateView()" << endl;
	kdDebug() << "upAndRunning(): " << KMFAppState::upAndRunning() << endl;
	kdDebug() << "hasOpenDoc()" << KMFAppState::hasOpenDoc() <<  endl;
	if ( ! KMFAppState::upAndRunning() || ! KMFAppState::hasOpenDoc() ) {
		m_lv_table_filter->clearAllItems();
		m_lv_table_nat->clearAllItems();
		m_lv_table_mangle->clearAllItems();
		m_lv_table_filter->setEnabled( false );
		m_lv_table_nat->setEnabled( false );
		m_lv_table_mangle->setEnabled( false );
		slotSelectionInvalid();
		setEnabled( false );
		return;
	}


	rb_filter->setEnabled( kmfdoc->useFilter() );
	rb_mangle->setEnabled( kmfdoc->useMangle() );
	rb_nat->setEnabled( kmfdoc->useNat() );


	if ( kmfdoc->useModules() ) {
		m_led_modules->setColor( green );
		m_led_modules->on();
	} else {
		m_led_modules->setColor( red );
		m_led_modules->off();
	}

	if ( kmfdoc->useIPFwd() ) {
		m_led_fwd->setColor( green );
		m_led_fwd->on();
	} else {
		m_led_fwd->setColor( red );
		m_led_fwd->off();
	}

	if ( kmfdoc->useSynCookies() ) {
		m_led_syn->setColor( green );
		m_led_syn->on();
	} else {
		m_led_syn->setColor( red );
		m_led_syn->off();
	}

	if ( kmfdoc->useRPFilter() ) {
		m_led_rp->setColor( green );
		m_led_rp->on();
	} else {
		m_led_rp->setColor( red );
		m_led_rp->off();
	}

	if ( kmfdoc->useMartians() ) {
		m_led_martians->setColor( green );
		m_led_martians->on();
	} else {
		m_led_martians->setColor( red );
		m_led_martians->off();
	}

// 	setCurrTableView( currTableView() );

	if ( ! rb_filter->isEnabled() && ! rb_nat->isEnabled() ) {
		rb_mangle->setChecked( true );
		setCurrTableView( m_lv_table_mangle );
	} else if ( ! rb_filter->isEnabled() &&   ! rb_mangle->isEnabled() ) {
		rb_nat->setChecked( true );
		setCurrTableView( m_lv_table_nat );
	} else if ( ! rb_nat->isEnabled() &&   ! rb_mangle->isEnabled() ) {
		rb_filter->setChecked( true );
		setCurrTableView( m_lv_table_filter );
	}

	emit sigUpdateView();
// 	slotEditRule();
}

/*
 *  Main event handler. Reimplemented to handle application
 *  font changes
 */
bool KMFRuleEdit::event( QEvent* ev ) {
	bool ret = QWidget::event( ev );
	if ( ev->type() == QEvent::ApplicationFontChange ) {}
	return ret;
}

void KMFRuleEdit::slotHelp() {
	kdDebug() << "void KMFRuleEdit::slotHelp()" << endl;
	kapp->invokeHelp( "rules" );
}
void KMFRuleEdit::loadIcons() {
	kdDebug() << "void KMFRuleEdit::loadIcons()" << endl;
	KIconLoader *loader = KGlobal:: iconLoader();
	QString icon_name;

	icon_name = "up";
	icon_up = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "down";
	icon_down = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "editdelete";
	icon_del = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "filenew";
	icon_new = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "edit";
	icon_edit = loader->loadIcon( icon_name, KIcon::Small );


	icon_name = "filter";
	icon_filter = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "text";
	icon_rename = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "rule-22";
	icon_rule = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "view_tree";
	icon_chain = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "reject";
	icon_reject = loader->loadIcon( icon_name, KIcon::User );

	icon_name = "target";
	icon_target = loader->loadIcon( icon_name, KIcon::User );

	icon_name = "stop";
	icon_drop = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "button_ok";
	icon_accept = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "filesaveas";
	icon_log = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "undo";
	icon_return = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "editclear";
	icon_cmd = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "filter";
	icon_filter = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "pipe";
	icon_queue = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "editcopy";
	icon_copy = loader->loadIcon( icon_name, KIcon::Small );

	icon_name = "forward";
	icon_move = loader->loadIcon( icon_name, KIcon::Small );

}
#include "kmfruleedit.moc"
