/*
 * This file is a part of VyQChat.
 *
 * Copyright (C) 2002-2004 Pawel Stolowski <yogin@linux.bydg.org>
 *
 * VyQChat is free software; you can redestribute it and/or modify it
 * under terms of GNU General Public License by Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY. See GPL for more details.
 */

#include "global.h"
#include "settingsdlg.h"
#include "settings.h"
#include <iostream>
#include <qlayout.h>
#include <qcheckbox.h>
#include <qlabel.h>
#include <qlistbox.h>
#include <qtooltip.h>
#include <qvalidator.h>
#include <qhostaddress.h>
#include <qradiobutton.h>
#include <qvbox.h>
#include <qvbuttongroup.h>
#include <qpushbutton.h>
#include <qfontdialog.h>
#include <qcombobox.h>
#include <qspinbox.h>
#include <qlineedit.h>
#include <qfiledialog.h>
#include <qtextcodec.h>
#include <qlistview.h>
#include <qbuttongroup.h>

SettingsDialog::EvtString SettingsDialog::btns[] = {
		{QT_TRANSLATE_NOOP("SettingsDialog", "Chat"),        EventChatline},
		{QT_TRANSLATE_NOOP("SettingsDialog", "Message"),     EventMessage},
		{QT_TRANSLATE_NOOP("SettingsDialog", "Join"),        EventJoin},
		{QT_TRANSLATE_NOOP("SettingsDialog", "Leave"),       EventLeave},
		{QT_TRANSLATE_NOOP("SettingsDialog", "Beep"),        EventBeep},
		{QT_TRANSLATE_NOOP("SettingsDialog", "Info"),        EventInfo},
		{QT_TRANSLATE_NOOP("SettingsDialog", "RegexpMatch"), EventRegexpMatch}
	};

SettingsDialog::SettingsDialog(QWidget *parent, Settings *s): QTabDialog(parent, NULL, true), settings(s) /*{{{*/
{
	setCaption(tr("VyQchat settings"));

	setupNetworkTab(new QWidget(this));
	setupSoundDeviceTab(new QWidget(this));
	setupSoundsTab(new QWidget(this));
	setupScriptsTab(new QWidget(this));
	setupLookTab(new QWidget(this));
	setupMiscTab(new QWidget(this));

	//
	// final setup
	setOkButton();
	setCancelButton();
	setDefaultButton();
	connect(this, SIGNAL(applyButtonPressed()), this, SLOT(slotApply()));
	connect(this, SIGNAL(defaultButtonPressed()), this, SLOT(slotDefaults()));
}/*}}}*/

SettingsDialog::~SettingsDialog()/*{{{*/
{
	delete b_scrbrgroup; //deleted manually, because it is hidden widget with no parent
	delete b_screngroup;
}
/*}}}*/

void SettingsDialog::setupNetworkTab(QWidget *p)/*{{{*/
{
	QGridLayout *grid1 = new QGridLayout(p, 9, 2, 5);
	grid1->addWidget(new QLabel(tr("Nickname"), p), 0, 0);
	grid1->addWidget(le_nick = new QLineEdit(settings->getNick(), p), 0, 1);
	grid1->addWidget(new QLabel(tr("Gender"), p), 1, 0);
	
	//
	// gender buttons
	QButtonGroup *bgrp0 = new QButtonGroup(p);
	bgrp0->hide();
	QHBox *box0 = new QHBox(p);
	b_female = new QRadioButton(tr("Female"), box0);
	b_male = new QRadioButton(tr("Male"), box0);
	bgrp0->insert(b_female);
	bgrp0->insert(b_male);
	if (settings->getGender() == GENDER_MALE)
		b_male->setChecked(true);
	else
		b_female->setChecked(true);
	grid1->addWidget(box0, 1, 1);

	grid1->addWidget(new QLabel(tr("Hostname"), p), 2, 0);
	grid1->addWidget(le_hostname = new QLineEdit(settings->getHostname(), p), 2, 1);
	grid1->addWidget(new QLabel(tr("IP"), p), 3, 0);
	grid1->addWidget(le_ip = new QLineEdit(settings->getIP().toString(), p), 3, 1);
	grid1->addWidget(new QLabel(tr("UDP port"), p), 4, 0);
	grid1->addWidget(sp_port = new QSpinBox(1025, 65535, 1, p), 4, 1);
	sp_port->setValue(settings->getPort());
	QButtonGroup *bgrp1 = new QButtonGroup(2, Qt::Horizontal, p);
	bt_broadcast = new QRadioButton(tr("Use Broadcast"), bgrp1);
	bt_multicast = new QRadioButton(tr("Use Multicast"), bgrp1);
	bt_multicast->setDisabled(true); //multicast doesn't work yet
	grid1->addMultiCellWidget(bgrp1, 5, 5, 0, 1);
	if (settings->getNetworkMethod() == 0)
		bt_broadcast->setChecked(true);
	else
		bt_multicast->setChecked(true);
	
	grid1->addWidget(new QLabel(tr("Broadcast"), p), 6, 0);
	grid1->addWidget(le_broadcast = new QLineEdit(settings->getBroadcast().toString(), p), 6, 1);
	grid1->addWidget(new QLabel(tr("Multicast group"), p), 7, 0);
	grid1->addWidget(le_multicast = new QLineEdit(settings->getMulticastGroup().toString(), p), 7, 1);
	grid1->addWidget(new QLabel(tr("Users-List Refresh"), p), 8, 1);
	grid1->addWidget(sp_refresh = new QSpinBox(0, 300, 30, p), 8, 1);
	sp_refresh->setValue(settings->getRefresh());
	sp_refresh->setMinimumWidth(100);
	sp_refresh->setSuffix(" sec.");
	QRegExp rx("[a-zA-Z]*");
	QRegExpValidator *v_nick = new QRegExpValidator(rx, this);
	le_nick->setValidator(v_nick);
	
	slotUseBroadcastToggled(bt_broadcast->isChecked());
	connect(bt_broadcast, SIGNAL(toggled(bool)), this, SLOT(slotUseBroadcastToggled(bool)));

	QToolTip::add(le_ip, tr("IP address of your network\ninterface, e.g. 192.168.0.1"));
	QToolTip::add(le_broadcast, tr("Broadcast address of your network\ninterface, e.g. 192.168.0.255"));
	QToolTip::add(le_multicast, tr("Multicast address of your group\ne.g. 224.0.0.1"));
	QToolTip::add(sp_refresh, tr("Update interval for users\nlist (0 for no update)"));

	addTab(p, tr("Network"));
}/*}}}*/

void SettingsDialog::setupSoundDeviceTab(QWidget *p)/*{{{*/
{
	QVBoxLayout *box1 = new QVBoxLayout(p, 5);
	opt_snddev = new QVButtonGroup(p);
	QRadioButton *rb_nosnd = new QRadioButton("No sound", opt_snddev);
	QRadioButton *rb_pcs = new QRadioButton("PC speaker", opt_snddev);
	QRadioButton *rb_libao = new QRadioButton("libao", opt_snddev);
	QRadioButton *rb_arts = new QRadioButton("aRts", opt_snddev);
	QRadioButton *rb_cmd = new QRadioButton("External command", opt_snddev);
	
	QHBox *box2 = new QHBox(p);
	new QLabel("Command", box2);
	le_playcmd = new QLineEdit(box2);
	le_playcmd->setText(settings->getPlayCommand());
	le_playcmd->setDisabled(true);

#	ifndef HAVE_LIBAO
	rb_libao->setDisabled(true);
#	endif
#	ifndef HAVE_ARTS
	rb_arts->setDisabled(true);
#	endif
	switch (settings->getSoundType())
	{
		case Sound::NoSound: rb_nosnd->setChecked(true); break;
		case Sound::PCSpeaker: rb_pcs->setChecked(true); break;
		case Sound::LibAo: rb_libao->setChecked(true); break;
		case Sound::Arts: rb_arts->setChecked(true); break;
		case Sound::Command: rb_cmd->setChecked(true);
			le_playcmd->setDisabled(false); break;
		default: rb_pcs->setChecked(true); break;
	}
	QToolTip::add(opt_snddev, tr("Preffered sound output"));
	QToolTip::add(le_playcmd, tr("External command to play sound file.\nMust take file name as last argument"));

	connect(opt_snddev, SIGNAL(clicked(int)), this, SLOT(slotSoundSystemClicked(int)));
	box1->addWidget(opt_snddev, 0, 0);
	box1->addWidget(box2, 1, 0);

	addTab(p, tr("Sound device"));
}/*}}}*/

void SettingsDialog::setupSoundsTab(QWidget *p)/*{{{*/
{
	const QString strenable(tr("Enable"));

	b_wavbrgroup = new QButtonGroup(NULL);
	b_wavengroup = new QButtonGroup(NULL);
	QGridLayout *grid1 = new QGridLayout(p, 7, 4, 5);

	for (int i=0; i<7; i++)
	{
		grid1->addWidget(cb_wav[i] = new QCheckBox(strenable, p), i, 0);
		grid1->addWidget(new QLabel(tr(btns[i].name), p), i, 1);
		grid1->addWidget(le_wav[i] = new QLineEdit(p), i, 2);
		le_wav[i]->setText(settings->getSampleFileName(btns[i].evt));
		grid1->addWidget(b_browsewav[i] = new QPushButton("Browse", p), i, 3);
		b_wavbrgroup->insert(b_browsewav[i], i);
		b_wavengroup->insert(cb_wav[i], i);
		//
		// apply checkbox setting
		cb_wav[i]->setChecked(settings->getSampleEnabled(btns[i].evt));
		slotSampleEnable(i);
	}
	
	connect(b_wavbrgroup, SIGNAL(clicked(int)), this, SLOT(slotBrowseSample(int)));
	connect(b_wavengroup, SIGNAL(clicked(int)), this, SLOT(slotSampleEnable(int)));

	addTab(p, tr("Sounds"));
}/*}}}*/

void SettingsDialog::setupScriptsTab(QWidget *p)/*{{{*/
{
	const QString strenable(tr("Enable"));

	b_scrbrgroup = new QButtonGroup(NULL);
	b_screngroup = new QButtonGroup(NULL);
	QGridLayout *grid1 = new QGridLayout(p, 7, 4, 5);

	for (int i=0; i<7; i++)
	{
		grid1->addWidget(cb_scr[i] = new QCheckBox(strenable, p), i, 0);
		grid1->addWidget(new QLabel(tr(btns[i].name), p), i, 1);
		grid1->addWidget(le_scr[i] = new QLineEdit(p), i, 2);
		le_scr[i]->setText(settings->getScriptFileName(btns[i].evt));
		grid1->addWidget(b_browsescr[i] = new QPushButton("Browse", p), i, 3);
		b_scrbrgroup->insert(b_browsescr[i], i);
		b_screngroup->insert(cb_scr[i], i);
		//
		// apply checkbox setting
		cb_scr[i]->setChecked(settings->getScriptEnabled(btns[i].evt));
		slotScriptEnable(i);
	}
	
	connect(b_scrbrgroup, SIGNAL(clicked(int)), this, SLOT(slotBrowseScript(int)));
	connect(b_screngroup, SIGNAL(clicked(int)), this, SLOT(slotScriptEnable(int)));
	
	addTab(p, tr("Scripts"));
}/*}}}*/

void SettingsDialog::setupLookTab(QWidget *p)/*{{{*/
{
	//p->setDisabled(true);
	QVBoxLayout *box0 = new QVBoxLayout(p);
	QGroupBox *box1 = new QGroupBox(2, Qt::Vertical, "Icons", p);
	box0->addWidget(box1);
	themes_list = new QComboBox(box1);
	themes_list->setEditable(false);
	theme_info = new QLabel(box1);
	theme_info->setFrameStyle(QFrame::Panel | QFrame::Sunken);
	theme_info->setFixedHeight(60);

	//
	// fill-up the list of themes, mark actual one
	themes = Icons::getThemes();
	int item = -1;
	int i = 0;
	for (ThemesList::Iterator it = themes.begin(); it!=themes.end(); ++it)
	{
		themes_list->insertItem((*it).getName());
		if ((item < 0) && (*it).getName() == settings->getIconThemeName())
			item = i;
		++i;
	}
	if (item > 0)
		themes_list->setCurrentItem(item); //highlight current theme

	connect(themes_list, SIGNAL(highlighted(int)), this, SLOT(slotThemeSelected(int)));
	
/*	const QString change("Set");
	QGridLayout *grid4 = new QGridLayout(p, 4, 3, 5);mA
	grid4->addWidget(new QLabel("Chat window", p), 0, 0);
	QLineEdit *le_chatfont = new QLineEdit("....", p);
	QPushButton *b_chatfont = new QPushButton(change, p);
	grid4->addWidget(le_chatfont, 0, 1);
	grid4->addWidget(b_chatfont, 0 ,2);
	grid4->addWidget(new QLabel("Users list", p), 1, 0);
	QLineEdit *le_usersfont = new QLineEdit("....", p);
	QPushButton *b_usersfont = new QPushButton(change, p);
	grid4->addWidget(le_usersfont, 1, 1);
	grid4->addWidget(b_usersfont, 1 ,2);*/

/*	const QString change("Set");
	QWidget *p = new QWidget(this);

	QVGroupBox *group1 = new QVGroupBox("Fonts", p);
	QHBox *box1 = new QHBox(group1);
		
	new QLabel("Chat window", box1);
	QLineEdit *le_chatfont = new QLineEdit("....", box1);
	QPushButton *b_chatfont = new QPushButton(change, box1);*/

	addTab(p, tr("Look"));
}/*}}}*/

void SettingsDialog::setupMiscTab(QWidget *p)/*{{{*/
{
	QVBoxLayout *box = new QVBoxLayout(p, 6);
	QHBox *box1 = new QHBox(p);
	new QLabel(tr("ANSI Character encoding"), box1);
	box->addWidget(box1);
	
	int selected = 0;
	l_enc = new QComboBox(box1);
	l_enc->insertItem(tr("System default"));
	QTextCodec *codec;

	const QString utf("UTF-8");
	for (int i=0; codec = QTextCodec::codecForIndex(i); i++)
	{
		if (codec->name() != utf)
		{
			l_enc->insertItem(codec->name());
			if (strcmp(codec->name(), settings->getEncoding().latin1()) == 0)
				selected = i+1;
		}
	}
	l_enc->setCurrentItem(selected);

	b_useutf = new QCheckBox(tr("Always use UTF"), p);
	b_useutf->setChecked(settings->getUseUTF());
	box->addWidget(b_useutf);
	
	b_hide = new QCheckBox(tr("Hide your channels list"), p);
	b_hide->setChecked(settings->getHideChannels());
	box->addWidget(b_hide);
	b_popup = new QCheckBox(tr("Pop-up windows for messages"), p);
	b_popup->setChecked(settings->getPopupsOn());
	box->addWidget(b_popup);
	b_popupdnd = new QCheckBox(tr("No pop-ups when DND/Away/Offline"), p);
	b_popupdnd->setChecked(settings->getNoDNDpopups());
	box->addWidget(b_popupdnd);
	b_systray = new QCheckBox(tr("System tray icon"), p);
	b_systray->setChecked(settings->getUseSystray());
	box->addWidget(b_systray);
	b_confirmexit = new QCheckBox(tr("Confirm exit"), p);
	b_confirmexit->setChecked(settings->getConfirmExit());
	box->addWidget(b_confirmexit);
	
	slotPopupCheckBoxChanged(settings->getPopupsOn());

	QToolTip::add(b_useutf, tr("Encodes text using Unicode, which allows characters from any language.\nThis is recommended option, but it may cause incompatibility with\nVypress Chat 1.5.x and older."));
	QToolTip::add(l_enc, tr("Character encoding used for non-UTF aware users"));
	QToolTip::add(b_hide, tr("Doesn't allow anyone to see channels\nyou are on when requesting info"));
	QToolTip::add(b_popup, tr("Enables separate windows (pop-ups) for\nmessages that others send to you"));
	QToolTip::add(b_popupdnd, tr("Disables message windows when they would disturb you.\nMessages will still be visible in main chat area"));
	QToolTip::add(b_confirmexit, tr("Enables confirmation when closing VyQChat window or\nleaving main channel"));
	QToolTip::add(b_systray, tr("Docks VyQChat in system tray area\n(KDE/GNOME and other compliant WMs)"));
	
	connect(b_popup, SIGNAL(toggled(bool)), this, SLOT(slotPopupCheckBoxChanged(bool)));
	addTab(p, tr("Misc"));
}/*}}}*/

void SettingsDialog::slotApply()/*{{{*/
{
	bool themechanged = false;
	bool netcfgchanged = false;
	bool sndcfgchanged = false;
	
	settings->setNick(le_nick->text());
	
	char gender = b_male->isChecked() ? GENDER_MALE : GENDER_FEMALE;
	if (settings->getGender() != gender)
		settings->setGender(gender);

	settings->setHostname(le_hostname->text());

	if (settings->getIconThemeName() != themes_list->currentText())
	{
		settings->setIconThemeName(themes_list->currentText());
		themechanged = true;
	}
	if (settings->getIP().toString() != le_ip->text())
	{
		settings->setIP(le_ip->text());
		netcfgchanged = true;
	}
	if (settings->getBroadcast().toString() != le_broadcast->text())
	{
		settings->setBroadcast(le_broadcast->text());
		netcfgchanged = true;
	}

	NetworkingMethod method = bt_broadcast->isChecked() ? NET_BROADCAST : NET_MULTICAST;
	if (settings->getNetworkMethod() != method)
	{
		settings->setNetworkMethod(method);
		netcfgchanged = true;
	}
	if (settings->getPort() != sp_port->value())
	{
		settings->setPort(sp_port->value());
		netcfgchanged = true;
	}
	if (settings->getPlayCommand() != le_playcmd->text())
	{
		settings->setPlayCommand(le_playcmd->text());
		sndcfgchanged = true;
	}
	settings->setRefresh(sp_refresh->value());
	
	if (settings->getSoundType() != static_cast<Sound::SoundType>(opt_snddev->id(opt_snddev->selected())))
	{
		settings->setSoundType(static_cast<Sound::SoundType>(opt_snddev->id(opt_snddev->selected())));
		sndcfgchanged = true;
	}
	settings->setEncodingName(l_enc->currentItem() ? l_enc->currentText() : QString(""));
	if (b_useutf->isChecked() != settings->getUseUTF())
		settings->setUseUTF(b_useutf->isChecked());
	settings->setHideChannels(b_hide->isChecked());
	settings->setPopups(b_popup->isChecked());
	settings->setNoDNDpopups(b_popupdnd->isChecked());

	//
	// sounds and scripts
	for (int i=0; i<7; i++)
	{
		if (settings->getSampleFileName(btns[i].evt) != le_wav[i]->text())
		{
			settings->setSampleFileName(btns[i].evt, le_wav[i]->text());
			sndcfgchanged = true;
		}
		if (settings->getSampleEnabled(btns[i].evt) != cb_wav[i]->isChecked())
			settings->setSampleEnabled(btns[i].evt, cb_wav[i]->isChecked());

		if (settings->getScriptFileName(btns[i].evt) != le_scr[i]->text())
			settings->setScriptFileName(btns[i].evt, le_scr[i]->text());

		if (settings->getScriptEnabled(btns[i].evt) != cb_scr[i]->isChecked())
			settings->setScriptEnabled(btns[i].evt, cb_scr[i]->isChecked());
	}

	if (settings->getUseSystray() != b_systray->isChecked())
	{
		settings->setUseSystray(b_systray->isChecked());
		emit systraySettingsChanged();
	}
	
	if (netcfgchanged)
		emit networkSettingsChanged();
	if (sndcfgchanged)
		emit soundSettinsChanged();
	if (themechanged)
		emit themeChanged();
	
	close();
}/*}}}*/

void SettingsDialog::slotDefaults()/*{{{*/
{
	/*le_nick->setText(settings->def_nick);
	le_hostname->setText(settings->def_hostname);
	le_ip->setText(settings->def_ip);
	le_broadcast->setText(settings->def_broadcast);
	sp_refresh->setValue(300);
	opt_snddev->setButton(0);
	l_enc->setCurrentItem(0);*/
}/*}}}*/

/*
 * disables or enables "No popups when DND...." 
 * according to "Popup windows for..." state */
void SettingsDialog::slotPopupCheckBoxChanged(bool state)/*{{{*/
{
	b_popupdnd->setDisabled(!state);
}/*}}}*/

/*
 * mouse-click on sound subsystems list
 */
void SettingsDialog::slotSoundSystemClicked(int index)/*{{{*/
{
	le_playcmd->setDisabled(index!=4);
}/*}}}*/

/*
 * toggling of Broadcast/Multicast radio group
 */
void SettingsDialog::slotUseBroadcastToggled(bool state)/*{{{*/
{
	le_broadcast->setDisabled(!state);
	le_multicast->setDisabled(state);
}/*}}}*/

/*
 * updates icon theme info according to highlighted theme
 */
void SettingsDialog::slotThemeSelected(int index)/*{{{*/
{
	theme_info->setText(themes[index].getInfo());
}/*}}}*/

void SettingsDialog::slotSampleEnable(int id)/*{{{*/
{
	bool flag = !cb_wav[id]->isChecked();
	le_wav[id]->setDisabled(flag);
	b_browsewav[id]->setDisabled(flag);
}/*}}}*/

void SettingsDialog::slotBrowseSample(int id)/*{{{*/
{
	QString start(le_wav[id]->text());

	if (start.isEmpty())
		start = QString(DATADIR);

	QString selected = QFileDialog::getOpenFileName(start, 
			"Wav files (*.wav); All files (*.*)", this, 0, "Select sound file");
	if (!selected.isNull())
		le_wav[id]->setText(selected);
}/*}}}*/

/*
 * action for script "browse" button
 */
void SettingsDialog::slotBrowseScript(int id)/*{{{*/
{
	QString start(le_scr[id]->text());

	if (start.isEmpty())
		start = QString(DATADIR);

	QString selected = QFileDialog::getOpenFileName(start, 
			QString::null /*"All files (*.*)"*/, this, 0, "Select script file");
	if (!selected.isNull())
		le_scr[id]->setText(selected);
}/*}}}*/

/*
 * action for script checkbox button, enables or disables name field and
 * browse button
 */
void SettingsDialog::slotScriptEnable(int id)/*{{{*/
{
	bool flag = !cb_scr[id]->isChecked();
	le_scr[id]->setDisabled(flag);
	b_browsescr[id]->setDisabled(flag);
}/*}}}*/



syntax highlighted by Code2HTML, v. 0.9.1