/*
 * setupdlg.cpp
 * Copyright (C) 1999 Kurt Granroth <granroth@kde.org>
 *
 * This file contains the implementation of the setup dialog
 * class for KBiff.
 *
 * $Id: setupdlg.cpp,v 1.60 2000/06/06 19:02:46 kiefer Exp $
 */
#include "setupdlg.h"

#include "Trace.h"

#include <qgroupbox.h>
#include <qfileinfo.h>
#include <qmessagebox.h>
#include <qlineedit.h>
#include <qcheckbox.h>
#include <qpushbutton.h>
#include <qcombobox.h>
#include <qheader.h>
#include <qtabwidget.h>

#include <qpixmap.h>
#include <qfont.h>
#include <qlabel.h>
#include <qstrlist.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qdict.h>
#include <qlist.h>
#include <qwhatsthis.h>
#include <qstylesheet.h>

#include <kmessagebox.h>
#include <kfiledialog.h>
#include <kapp.h>
#include <kglobal.h>
#include <klocale.h>
#include <kstddirs.h>
#include <ksimpleconfig.h>
#include <kbiffurl.h>
#include <kprocess.h>
#include <krun.h>
#include <kurllabel.h>

#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>

#define CONFIG_FILE "kbiffrc"

#ifdef HAVE_PATHS_H
#include <paths.h>
#endif

#ifndef _PATH_MAILDIR
#define _PATH_MAILDIR "/var/spool/mail"
#endif

///////////////////////////////////////////////////////////////////////////
// KBiffSetup
///////////////////////////////////////////////////////////////////////////
KBiffSetup::KBiffSetup(const QString& profile, bool secure)
	: QDialog(0, 0, true, 0)
{
TRACEINIT("KBiffSetup::KBiffSetup()");
	// set the icon just to be cute
	setIcon(kapp->miniIcon());

	// make sure the profile is *something*
	QString the_profile;
	if (profile.isEmpty())
		the_profile = getSomeProfile();
	else
		the_profile = profile;

	setCaption(i18n("KBiff Setup"));

	// The profile combo box and buttons all go in this groupbox
	QGroupBox* profile_groupbox = new QGroupBox(i18n("Profile"), this);

	// combo box to hold the profile names
	comboProfile = new QComboBox(false, profile_groupbox);
	comboProfile->setSizeLimit(10);

    QString whatsthis = i18n(
        "This is a list of all of the KBiff <b>profiles</b><p>"
        "A profile is a logical grouping of settings for either one "
        "mailbox or several mailboxes.  Each profile gets one icon "
        "and one new mail sound and one... well, everything");
    QWhatsThis::add(comboProfile, whatsthis);

	// Add New Profile button
	QPushButton *new_profile_button = new QPushButton(i18n("&New..."),
	                                                  profile_groupbox);
    whatsthis = i18n("Create a new profile");
    QWhatsThis::add(new_profile_button, whatsthis);
	connect(new_profile_button, SIGNAL(clicked()),
	                            SLOT(slotAddNewProfile()));

	// Renam Profile button
	QPushButton *rename_profile_button = new QPushButton(i18n("&Rename..."),
	                                                     profile_groupbox);
    whatsthis = i18n("Rename the current profile");
    QWhatsThis::add(rename_profile_button, whatsthis);
	connect(rename_profile_button, SIGNAL(clicked()),
	                               SLOT(slotRenameProfile()));

	// Delete Profile button
	QPushButton *delete_profile_button = new QPushButton(i18n("&Delete"),
	                                                     profile_groupbox);
    whatsthis = i18n("Delete the current profile");
    QWhatsThis::add(delete_profile_button, whatsthis);
	connect(delete_profile_button, SIGNAL(clicked()),
	                               SLOT(slotDeleteProfile()));

	// setup the tabs
	QTabWidget *tabctl = new QTabWidget(this);
	generalTab = new KBiffGeneralTab(the_profile, tabctl);
	newmailTab = new KBiffNewMailTab(the_profile, tabctl);
	mailboxTab = new KBiffMailboxTab(the_profile, tabctl);
	aboutTab   = new KBiffAboutTab(tabctl); 

	connect(comboProfile, SIGNAL(highlighted(const QString&)),
	        generalTab, SLOT(readConfig(const QString&)));
	connect(comboProfile, SIGNAL(highlighted(const QString&)),
	        newmailTab, SLOT(readConfig(const QString&)));
	connect(comboProfile, SIGNAL(highlighted(const QString&)),
	        mailboxTab, SLOT(readConfig(const QString&)));

	// add the tabs
	tabctl->addTab(generalTab, i18n("General"));
	tabctl->addTab(newmailTab, i18n("New Mail"));
	tabctl->addTab(mailboxTab, i18n("Mailbox"));
	tabctl->addTab(aboutTab, i18n("About"));

	// help button
	QPushButton *help_button = new QPushButton(i18n("&Help"), this);
	connect(help_button, SIGNAL(clicked()), SLOT(invokeHelp()));

	// ok button
	QPushButton *ok_button = new QPushButton(i18n("&OK"), this);
	ok_button->setDefault(true);
	connect(ok_button, SIGNAL(clicked()), SLOT(slotDone()));

	// cancel button
	QPushButton *cancel_button = new QPushButton(i18n("&Cancel"), this);
	connect(cancel_button, SIGNAL(clicked()), SLOT(reject()));

	// are we secure?
	isSecure = secure;

	// NOW, SETUP ALL THE LAYOUTS!
	// This layout handles the buttons for the profile combobox
	QBoxLayout *pro_button_layout = new QBoxLayout(QBoxLayout::LeftToRight, 12);
	pro_button_layout->addWidget(new_profile_button);
	pro_button_layout->addWidget(rename_profile_button);
	pro_button_layout->addWidget(delete_profile_button);

	// This layout handles the upper profile groupbox
	QBoxLayout *profile_layout = new QBoxLayout(profile_groupbox,
	                                            QBoxLayout::Down, 12);
	profile_layout->addSpacing(8);
	profile_layout->addWidget(comboProfile);
	profile_layout->addLayout(pro_button_layout);

	// This layout handles the dialog buttons
	QBoxLayout *dialog_button_layout = new QBoxLayout(QBoxLayout::LeftToRight,
													  12);
	dialog_button_layout->addWidget(help_button);
	dialog_button_layout->addStretch(1);
	dialog_button_layout->addWidget(ok_button);
	dialog_button_layout->addWidget(cancel_button);

	// This is the outermost layout
	QBoxLayout *top_layout = new QBoxLayout(this, QBoxLayout::Down, 12);
	top_layout->addWidget(profile_groupbox);
	top_layout->addWidget(tabctl, 1);
	top_layout->addLayout(dialog_button_layout);

	// Read in the config for this profile
	readConfig(the_profile);
}

KBiffSetup::~KBiffSetup()
{
}

void KBiffSetup::slotPlaySoundRelay(const QString& play_sound)
{
	emit(signalPlaySound(play_sound));
}

const bool KBiffSetup::getSecure() const
{
	return isSecure;
}

const QString KBiffSetup::getProfile() const
{
	return comboProfile->currentText();
}

const KBiffURL KBiffSetup::getCurrentMailbox() const
{
	return mailboxTab->getMailbox();
}

const QList<KBiffURL> KBiffSetup::getMailboxList() const
{
	return mailboxTab->getMailboxList();
}

const QString KBiffSetup::getMailClient() const
{
	return generalTab->getMailClient();
}

const QString KBiffSetup::getNoMailIcon() const
{
	return generalTab->getButtonNoMail();
}

const QString KBiffSetup::getNewMailIcon() const
{
	return generalTab->getButtonNewMail();
}

const QString KBiffSetup::getOldMailIcon() const
{
	return generalTab->getButtonOldMail();
}

const QString KBiffSetup::getNoConnIcon() const
{
	return generalTab->getButtonNoConn();
}

const bool KBiffSetup::getSessionManagement() const
{
	return generalTab->getSessionManagement();
}

const bool KBiffSetup::getCheckStartup() const
{
	return generalTab->getCheckStartup();
}


const bool KBiffSetup::getDock() const
{
	return generalTab->getDock();
}

const unsigned int KBiffSetup::getPoll() const
{
	return generalTab->getPoll();
}

const QString KBiffSetup::getRunCommandPath() const
{
	return newmailTab->getRunCommandPath();
}

const QString KBiffSetup::getPlaySoundPath() const
{
	return newmailTab->getPlaySoundPath();
}

const bool KBiffSetup::getRunCommand() const
{
	return newmailTab->getRunCommand();
}

const bool KBiffSetup::getPlaySound() const
{
	return newmailTab->getPlaySound();
}

const bool KBiffSetup::getSystemBeep() const
{
	return newmailTab->getSystemBeep();
}

const bool KBiffSetup::getNotify() const
{
	return newmailTab->getNotify();
}

const bool KBiffSetup::getStatus() const
{
	return newmailTab->getStatus();
}

void KBiffSetup::invokeHelp()
{
	kapp->invokeHTMLHelp("kbiff/kbiff.html", "");
}

void KBiffSetup::readConfig(const QString& profile)
{
	QStrList profile_list;

	// open the config file
	KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE, true);
	config->setDollarExpansion(false);

	config->setGroup("General");

	// read in the mailboxes
	int number_of_mailboxes = config->readListEntry("Profiles", profile_list, ',');
	delete config;

	// check if we have any mailboxes to read in
	if (number_of_mailboxes > 0)
	{
		comboProfile->clear();

		// load up the combo box
		comboProfile->insertStrList(&profile_list);

		// read in the data from the first mailbox if we don't have a name
		for (int i = 0; i < comboProfile->count(); i++)
		{
			if (QString(profile) == comboProfile->text(i))
			{
				comboProfile->setCurrentItem(i);
				break;
			}
		}
	}
	else
		comboProfile->insertItem(profile);
}

QString KBiffSetup::getSomeProfile() const
{
TRACEINIT("KBiffSetup::getSomeProfile()");
	QStrList profile_list;

	// open the config file
	KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE, true);
	config->setGroup("General");

	// read in the mailboxes
	int number_of_mailboxes = config->readListEntry("Profiles", profile_list, ',');
	delete config;

TRACEF("first profile = %s", profile_list.getLast());
	// get the first mailbox if it exists
	if (number_of_mailboxes > 0)
		return QString(profile_list.getLast());
	else
		return QString("Inbox");
}

void KBiffSetup::saveConfig()
{
	// open the config file for writing
	KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE);

	config->setGroup("General");

	// get the list of profiles
	QStrList profile_list;
	for (int i = 0; i < comboProfile->count(); i++)
		profile_list.append(comboProfile->text(i));

	// write the mailboxes
	config->writeEntry("Profiles", profile_list, ',');

	delete config;
}

///////////////////////////////////////////////////////////////////////
// Protected slots
///////////////////////////////////////////////////////////////////////
void KBiffSetup::slotDone()
{
TRACEINIT("KBiffSetup::slotDone()");
	QString profile = comboProfile->currentText();
	saveConfig();
	generalTab->saveConfig(profile);
	newmailTab->saveConfig(profile);
	mailboxTab->saveConfig(profile);
	accept();
}

void KBiffSetup::slotAddNewProfile()
{
	KBiffNewDlg dlg;

	// popup the name chooser
	dlg.setCaption(i18n("New Profile"));
	if (dlg.exec())
	{
		QString profile_name = dlg.getName();

		// bail out if we already have this name
		for (int i = 0; i < comboProfile->count(); i++)
		{
			if (profile_name == comboProfile->text(i))
				return;
		}

		// continue only if we received a decent name
		if (profile_name.isEmpty() == false)
		{
			comboProfile->insertItem(profile_name, 0);

			saveConfig();
			readConfig(profile_name);
			generalTab->readConfig(profile_name);
			newmailTab->readConfig(profile_name);
			mailboxTab->readConfig(profile_name);
		}
	}
}

void KBiffSetup::slotRenameProfile()
{
	KBiffNewDlg dlg;
	QString title;
	QString old_profile = comboProfile->currentText();
	
	title = i18n("Rename Profile: %1").arg(old_profile);
	dlg.setCaption(title);
	// popup the name chooser
	if (dlg.exec())
	{
		QString profile_name = dlg.getName();

		// bail out if we already have this name
		for (int i = 0; i < comboProfile->count(); i++)
		{
			if (profile_name == comboProfile->text(i))
				return;
		}

		// continue only if we received a decent name
		if (profile_name.isNull() == false)
		{
			comboProfile->removeItem(comboProfile->currentItem());
			comboProfile->insertItem(profile_name, 0);

			// remove the reference from the config file
			KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE);
			// nuke the group
			config->deleteGroup(old_profile, true);
			delete config;

			// now save the profile settings
			saveConfig();
			generalTab->saveConfig(profile_name);
			newmailTab->saveConfig(profile_name);
			mailboxTab->saveConfig(profile_name);
		}
	}
}

void KBiffSetup::slotDeleteProfile()
{
	QString title, msg;
	QString profile = comboProfile->currentText();
	
	title = i18n("Delete Profile: %1").arg(profile);
	msg = i18n("Are you sure you wish to delete this profile?\n")
	             .arg(profile);
	
	switch (QMessageBox::warning(this, title, msg,
	                             QMessageBox::Yes | QMessageBox::Default,
	                             QMessageBox::No | QMessageBox::Escape))
	{
		case QMessageBox::Yes:
		{
			comboProfile->removeItem(comboProfile->currentItem());

			saveConfig();

			// remove the reference from the config file
			KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE);
			// nuke the group
			config->deleteGroup(profile, true);
			delete config;

			if (comboProfile->count() == 0)
			{
				readConfig("Inbox");
				generalTab->readConfig("Inbox");
				newmailTab->readConfig("Inbox");
				mailboxTab->readConfig("Inbox");
			}
			else
			{
				readConfig(comboProfile->currentText());
				generalTab->readConfig(comboProfile->currentText());
				newmailTab->readConfig(comboProfile->currentText());
				mailboxTab->readConfig(comboProfile->currentText());
			}

			break;
		}
		case QMessageBox::No:
		default:
			break;
	}
}
///////////////////////////////////////////////////////////////////////
// Protected (non-slot) functions
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
// KBiffGeneralTab
///////////////////////////////////////////////////////////////////////
KBiffGeneralTab::KBiffGeneralTab(const QString& profile, QWidget *parent)
	: QWidget(parent)
{
TRACEINIT("KBiffGeneralTab::KBiffGeneralTab()");
TRACEF("profile = %s", (const char*)profile);
	// the poll time (in seconds)
	QLabel* poll_label = new QLabel(i18n("P&oll (sec):"), this);
	editPoll = new QLineEdit(this);
	poll_label->setBuddy(editPoll);
    QString whatsthis = i18n(
        "This is the interval (in seconds) that KBiff will check "
        "for new mail.  Typically, this can be quite small (under "
        "60 seconds) for local mailboxes but should be around 5 "
        "minutes (300 seconds) for remote mailboxes");
    QWhatsThis::add(editPoll, whatsthis);

	// the command to run when clicked
	QLabel *mail_label = new QLabel(i18n("&Mail client:"), this);
	editCommand = new QLineEdit(this);
	mail_label->setBuddy(editCommand);

	// do we dock automatically?
	checkDock = new QCheckBox(i18n("Doc&k in panel"), this);

	// should we support session management?
	checkNoSession = new QCheckBox(i18n("Use &session management"), this);

	// should we check at startup?
	checkNoStartup = new QCheckBox(i18n("Don't &check at startup"), this);
    whatsthis = i18n(
        "This option is for those people using KBiff to check their "
        "IMAP4 or POP3 account over a dial-up connection.  If KBiff "
        "tries to connect at startup and you are not connected, the "
        "DNS lookup will hang for a long time.  If this is checked, "
        "then KBiff will not check for new mail on startup.  You will "
        "need to manually start it every time you connect");
    QWhatsThis::add(checkNoStartup, whatsthis);

	// group box to hold the icons together
	QGroupBox* icons_groupbox = new QGroupBox(i18n("Icons:"), this);

	// "no mailbox" pixmap button
	QLabel* noconn_label = new QLabel(i18n("No Mail&box:"), icons_groupbox);
	buttonNoConn = new KIconButton(icons_groupbox);
	buttonNoConn->setFixedSize(50, 50);
	buttonNoConn->setIconType(KIcon::User, KIcon::Any);
	noconn_label->setBuddy(buttonNoConn);

	// "no mail" pixmap button
	QLabel* nomail_label = new QLabel(i18n("No M&ail:"), icons_groupbox);
	buttonNoMail = new KIconButton(icons_groupbox);
	buttonNoMail->setIconType(KIcon::User, KIcon::Any);
	buttonNoMail->setFixedSize(50, 50);
	nomail_label->setBuddy(buttonNoMail);

	// "old mail" pixmap button
	QLabel* oldmail_label = new QLabel(i18n("O&ld Mail:"), icons_groupbox);
	buttonOldMail = new KIconButton(icons_groupbox);
	buttonOldMail->setIconType(KIcon::User, KIcon::Any);
	buttonOldMail->setFixedSize(50, 50);
	oldmail_label->setBuddy(buttonOldMail);

	// "new mail" pixmap button
	QLabel* newmail_label = new QLabel(i18n("N&ew Mail:"), icons_groupbox);
	buttonNewMail = new KIconButton(icons_groupbox);
	buttonNewMail->setIconType(KIcon::User, KIcon::Any);
	buttonNewMail->setFixedSize(50, 50);
	newmail_label->setBuddy(buttonNewMail);

	// poll time layout
	QGridLayout *info_layout = new QGridLayout(5, 3, 8);
	info_layout->addWidget(poll_label, 0, 0);
	info_layout->addWidget(editPoll, 0, 1);
	info_layout->setColStretch(2, 1);

	info_layout->addWidget(mail_label, 1, 0);
	info_layout->addMultiCellWidget(editCommand, 1, 1, 1, 2);
	info_layout->addMultiCellWidget(checkDock, 2, 2, 1, 2);
	info_layout->addMultiCellWidget(checkNoSession, 3, 3, 1, 2);
	info_layout->addMultiCellWidget(checkNoStartup, 4, 4, 1, 2);

	// icons layout
	QVBoxLayout *no_conn_layout = new QVBoxLayout(12);
	no_conn_layout->addWidget(noconn_label);
	no_conn_layout->addWidget(buttonNoConn);

	QVBoxLayout *no_mail_layout = new QVBoxLayout(12);
	no_mail_layout->addWidget(nomail_label);
	no_mail_layout->addWidget(buttonNoMail);

	QVBoxLayout *old_mail_layout = new QVBoxLayout(12);
	old_mail_layout->addWidget(oldmail_label);
	old_mail_layout->addWidget(buttonOldMail);

	QVBoxLayout *new_mail_layout = new QVBoxLayout(12);
	new_mail_layout->addWidget(newmail_label);
	new_mail_layout->addWidget(buttonNewMail);

	QHBoxLayout *inner_icon_layout = new QHBoxLayout;
	inner_icon_layout->addStretch(1);
	inner_icon_layout->addLayout(no_conn_layout);
	inner_icon_layout->addStretch(1);
	inner_icon_layout->addLayout(no_mail_layout);
	inner_icon_layout->addStretch(1);
	inner_icon_layout->addLayout(old_mail_layout);
	inner_icon_layout->addStretch(1);
	inner_icon_layout->addLayout(new_mail_layout);
	inner_icon_layout->addStretch(1);

	QVBoxLayout *outer_icon_layout = new QVBoxLayout(icons_groupbox);
	outer_icon_layout->addStretch(1);
	outer_icon_layout->addLayout(inner_icon_layout);
	outer_icon_layout->addStretch(1);

	// main "outer" layout for this tab
	QVBoxLayout *top_layout = new QVBoxLayout(this, 12);
	top_layout->addLayout(info_layout);
	top_layout->addWidget(icons_groupbox);

	// now read in the config data for this profile
	readConfig(profile);
}

KBiffGeneralTab::~KBiffGeneralTab()
{
}

const bool KBiffGeneralTab::getSessionManagement() const
{
	return checkNoSession->isChecked();
}

const bool KBiffGeneralTab::getCheckStartup() const
{
	return checkNoStartup->isChecked();
}

const bool KBiffGeneralTab::getDock() const
{
	return checkDock->isChecked();
}

const QString KBiffGeneralTab::getButtonOldMail() const
{
	return buttonOldMail->icon();
}

const QString KBiffGeneralTab::getButtonNewMail() const
{
	return buttonNewMail->icon();
}

const QString KBiffGeneralTab::getButtonNoMail() const
{
	return buttonNoMail->icon();
}

const QString KBiffGeneralTab::getButtonNoConn() const
{
	return buttonNoConn->icon();
}

const QString KBiffGeneralTab::getMailClient() const
{
	return editCommand->text();
}

const int KBiffGeneralTab::getPoll() const
{
	return QString(editPoll->text()).toInt();
}

void KBiffGeneralTab::readConfig(const QString& profile)
{
TRACEINIT("KBiffGeneralTab::readConfig()");
	// open the config file
	KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE, true);

	config->setGroup(profile);

	editPoll->setText(config->readEntry("Poll", "60"));
	editCommand->setText(config->readEntry("MailClient", "kmail -check"));
	checkDock->setChecked(config->readBoolEntry("Docked", true));
	checkNoSession->setChecked(config->readBoolEntry("Sessions", true));
	checkNoStartup->setChecked(config->readBoolEntry("DontCheck", false));

	QString no_mail, old_mail, new_mail, no_conn;
	no_mail = config->readEntry("NoMailPixmap", "nomail");
	old_mail = config->readEntry("OldMailPixmap", "oldmail");
	new_mail = config->readEntry("NewMailPixmap", "newmail");
	no_conn = config->readEntry("NoConnPixmap", "noconn");

	buttonOldMail->setIcon(old_mail);
	buttonOldMail->setPixmap(UserIcon(no_mail));
	buttonNewMail->setIcon(new_mail);
	buttonNewMail->setPixmap(UserIcon(new_mail));
	buttonNoMail->setIcon(no_mail);
	buttonNoMail->setPixmap(UserIcon(no_mail));
	buttonNoConn->setIcon(no_conn);
	buttonNoConn->setPixmap(UserIcon(no_conn));

	delete config;
}

void KBiffGeneralTab::saveConfig(const QString& profile)
{
TRACEINIT("KBiffGeneralTab::saveConfig()");
	// open the config file for writing
	KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE);

	config->setGroup(profile);

	config->writeEntry("Poll", editPoll->text());
	config->writeEntry("MailClient", editCommand->text());
	config->writeEntry("Docked", checkDock->isChecked());
	config->writeEntry("Sessions", checkNoSession->isChecked());
	config->writeEntry("DontCheck", checkNoSession->isChecked());
	config->writeEntry("NoMailPixmap", buttonNoMail->icon());
	config->writeEntry("NewMailPixmap", buttonNewMail->icon());
	config->writeEntry("OldMailPixmap", buttonOldMail->icon());
	config->writeEntry("NoConnPixmap", buttonNoConn->icon());
	delete config;
}

///////////////////////////////////////////////////////////////////////
// KBiffNewMailTab
///////////////////////////////////////////////////////////////////////
KBiffNewMailTab::KBiffNewMailTab(const QString& profile, QWidget *parent)
	: QWidget(parent)
{
TRACEINIT("KBiffNewMailTab::KBiffNewMailTab()");
	// setup the Run Command stuff
	checkRunCommand = new QCheckBox(i18n("R&un Command"), this);
	editRunCommand = new QLineEdit(this);
	buttonBrowseRunCommand = new QPushButton(i18n("Browse"), this);

	// setup the Play Sound stuff
	checkPlaySound = new QCheckBox(i18n("&Play Sound"), this);
	editPlaySound = new QLineEdit(this);
	buttonBrowsePlaySound = new QPushButton(i18n("Browse"), this);

	buttonTestPlaySound = new QPushButton(this);
	buttonTestPlaySound->setPixmap(UserIcon("playsound"));
	buttonTestPlaySound->setMaximumSize(18, 20);

	// setup the System stuff
	checkBeep = new QCheckBox(i18n("System &Beep"), this);
	checkNotify = new QCheckBox(i18n("N&otify"), this);
	checkStatus = new QCheckBox(i18n("&Floating Status"), this);

	// connect some slots and signals
	connect(buttonBrowsePlaySound, SIGNAL(clicked()),
	                                 SLOT(browsePlaySound()));
	connect(buttonBrowseRunCommand, SIGNAL(clicked()),
	                                  SLOT(browseRunCommand()));
	connect(checkPlaySound, SIGNAL(toggled(bool)),
	                          SLOT(enablePlaySound(bool)));
	connect(buttonTestPlaySound, SIGNAL(clicked()),
	                             SLOT(testPlaySound()));
	connect(checkRunCommand, SIGNAL(toggled(bool)),
	                           SLOT(enableRunCommand(bool)));

	// NOW DO THE LAYOUT
	QHBoxLayout *run_command_layout = new QHBoxLayout(12);
	run_command_layout->addWidget(editRunCommand);
	run_command_layout->addWidget(buttonBrowseRunCommand);

	QHBoxLayout *play_sound_layout = new QHBoxLayout(12);
	play_sound_layout->addWidget(buttonTestPlaySound, 0);
	play_sound_layout->addWidget(editPlaySound, 1);
	play_sound_layout->addWidget(buttonBrowsePlaySound);

	QVBoxLayout *top_layout = new QVBoxLayout(this, 12);
	top_layout->addWidget(checkRunCommand);
	top_layout->addLayout(run_command_layout);
	top_layout->addStretch(1);

	top_layout->addWidget(checkPlaySound);
	top_layout->addLayout(play_sound_layout);
	top_layout->addStretch(1);

	top_layout->addWidget(checkBeep);
	top_layout->addWidget(checkNotify);
	top_layout->addWidget(checkStatus);
	top_layout->addStretch(1);

	readConfig(profile);
}

KBiffNewMailTab::~KBiffNewMailTab()
{
}

void KBiffNewMailTab::testPlaySound()
{
TRACEINIT("KBiffNewMailTab::testPlaySound()");
	emit(signalPlaySound(getPlaySoundPath()));
}

void KBiffNewMailTab::readConfig(const QString& profile)
{
TRACEINIT("KBiffNewMailTab::readConfig()");
	// open the config file
	KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE, true);

	TRACEF("profile = %s", (const char*)profile);
	config->setGroup(profile);

	checkRunCommand->setChecked(config->readBoolEntry("RunCommand", false));
	checkPlaySound->setChecked(config->readBoolEntry("PlaySound", false));
	checkBeep->setChecked(config->readBoolEntry("SystemBeep", true));
	checkNotify->setChecked(config->readBoolEntry("Notify", true));
	checkStatus->setChecked(config->readBoolEntry("Status", true));
	editRunCommand->setText(config->readEntry("RunCommandPath"));
	editPlaySound->setText(config->readEntry("PlaySoundPath"));

	enableRunCommand(checkRunCommand->isChecked());
	enablePlaySound(checkPlaySound->isChecked());

	delete config;
}

void KBiffNewMailTab::saveConfig(const QString& profile)
{
TRACEINIT("KBiffNewMailTab::saveConfig()");
	KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE);

	config->setGroup(profile);

	config->writeEntry("RunCommand", checkRunCommand->isChecked());
	config->writeEntry("PlaySound", checkPlaySound->isChecked());
	config->writeEntry("SystemBeep", checkBeep->isChecked());
	config->writeEntry("Notify", checkNotify->isChecked());
	config->writeEntry("Status", checkStatus->isChecked());
	config->writeEntry("RunCommandPath", editRunCommand->text());
	config->writeEntry("PlaySoundPath", editPlaySound->text());

	delete config;
}

const bool KBiffNewMailTab::getRunCommand() const
{
	return checkRunCommand->isChecked();
}

const QString KBiffNewMailTab::getRunCommandPath() const
{
	return editRunCommand->text();
}

const bool KBiffNewMailTab::getPlaySound() const
{
	return checkPlaySound->isChecked();
}

const QString KBiffNewMailTab::getPlaySoundPath() const
{
	return editPlaySound->text();
}

const bool KBiffNewMailTab::getSystemBeep() const
{
	return checkBeep->isChecked();
}

const bool KBiffNewMailTab::getNotify() const
{
	return checkNotify->isChecked();
}

const bool KBiffNewMailTab::getStatus() const
{
	return checkStatus->isChecked();
}

void KBiffNewMailTab::enableRunCommand(bool enable)
{
	editRunCommand->setEnabled(enable);
	buttonBrowseRunCommand->setEnabled(enable);
}

void KBiffNewMailTab::enablePlaySound(bool enable)
{
	editPlaySound->setEnabled(enable);
	buttonBrowsePlaySound->setEnabled(enable);
	buttonTestPlaySound->setEnabled(enable);
}

void KBiffNewMailTab::browseRunCommand()
{
  TRACEINIT("KBiffNewMailTab::browseRunCommand()");
  
  KURL url = KFileDialog::getOpenURL();
  
  if( url.isEmpty() )
    return;

  if( !url.isLocalFile() )
  {
    KMessageBox::sorry( 0L, i18n( "Only local files can be executed." ) );
    return;
  }

  editRunCommand->setText( url.path() );
}

void KBiffNewMailTab::browsePlaySound()
{
  TRACEINIT("KBiffNewMailTab::browsePlaySound()");
  
  KURL url = KFileDialog::getOpenURL();
  
  if( url.isEmpty() )
    return;

  if( !url.isLocalFile() )
  {
    KMessageBox::sorry( 0L, i18n( "Only local files are supported yet." ) );
    return;
  }
  
  editPlaySound->setText( url.path() );
}

//////////////////////////////////////////////////////////////////////
// KBiffMailboxTab
//////////////////////////////////////////////////////////////////////
KBiffMailboxAdvanced::KBiffMailboxAdvanced()
	: QDialog(0, 0, true, 0)
{
TRACEINIT("KBiffMailboxAdvanced::KBiffMailboxAdvanced()");
	setCaption(i18n("Advanced Options"));

	QLabel *mailbox_label = new QLabel(i18n("Mailbox &URL:"), this);
    mailbox_label->setAlignment(AlignVCenter | AlignRight);
	mailbox = new QLineEdit(this);
	mailbox_label->setBuddy(mailbox);
    QString whatsthis = i18n(
        "KBiff uses URLs to specify a mailbox and the parameters "
        "to the mailbox.  This allows you to modify the URL directly. "
        "Do so <i>only</i> if you really really know what you're doing!");
    QWhatsThis::add(mailbox, whatsthis);

	QLabel *port_label = new QLabel(i18n("P&ort:"), this);
    port_label->setAlignment(AlignVCenter | AlignRight);
	port = new QLineEdit(this);
	port_label->setBuddy(port);
    whatsthis = i18n(
        "This allows you to specify the port of your socket protocol. "
        "It usually is correct, so the only time you would change it is "
        "if you are accessing a non-standard server or going through "
        "a proxy (or something similar");
    QWhatsThis::add(port, whatsthis);

    whatsthis = i18n(
        "IMAP4, POP3, and NNTP sockets each have their own timeout "
        "before they give up. If you have a slow connection, you might "
        "want to set this to some random high value");
	QLabel *timeout_label = new QLabel(i18n("&Timeout:"), this);
	timeout_label->setAlignment(AlignVCenter | AlignRight);
	timeout = new QLineEdit(this);
    QWhatsThis::add(timeout, whatsthis);
    timeout_label->setBuddy(timeout);

	preauth = new QCheckBox(i18n("&PREAUTH"), this);
	preauth->setEnabled(false);
    whatsthis = i18n(
        "Check this if you login to your IMAP4 or POP3 server before "
        "kbiff accesses it.");
    QWhatsThis::add(preauth, whatsthis);

	keepalive = new QCheckBox(i18n("&Keep Alive"), this);
	keepalive->setEnabled(false);
    whatsthis = i18n(
        "If this is checked, then the IMAP4, POP3, or NNTP client "
        "will not log off each time");
    QWhatsThis::add(keepalive, whatsthis);

	async = new QCheckBox(i18n("&Asynchronous"), this);
	async->setEnabled(false);
    whatsthis = i18n(
        "If this is checked, then the socket protocols will access "
        "the server asynchronously");
    QWhatsThis::add(async, whatsthis);

	QPushButton *ok = new QPushButton(i18n("&OK"), this);
	ok->setDefault(true);

	QPushButton *cancel = new QPushButton(i18n("&Cancel"), this);

	// connect all the slots to signals
	connect(preauth, SIGNAL(toggled(bool)), SLOT(preauthModified(bool)));
	connect(keepalive, SIGNAL(toggled(bool)), SLOT(keepaliveModified(bool)));
	connect(async, SIGNAL(toggled(bool)), SLOT(asyncModified(bool)));
	connect(port, SIGNAL(textChanged(const QString&)),
	              SLOT(portModified(const QString&)));
	connect(ok, SIGNAL(clicked()), SLOT(accept()));
	connect(cancel, SIGNAL(clicked()), SLOT(reject()));
	connect(timeout, SIGNAL(textChanged(const QString&)),
	                 SLOT(timeoutModified(const QString&)));

	// NOW DO THE LAYOUT
	QGridLayout *top_layout = new QGridLayout(this, 6, 4, 12);
	top_layout->addWidget(mailbox_label, 0, 0);
	top_layout->addMultiCellWidget(mailbox, 0, 0, 1, 3);
	top_layout->addWidget(port_label, 1, 0);
	top_layout->addWidget(port, 1, 1);
	top_layout->addWidget(timeout_label, 1, 2);
	top_layout->addWidget(timeout, 1, 3);
	top_layout->addWidget(preauth, 2, 1);
	top_layout->addWidget(keepalive, 3, 1);
	top_layout->addWidget(async, 4, 1);
	top_layout->addWidget(ok, 5, 2);
	top_layout->addWidget(cancel, 5, 3);
}

KBiffMailboxAdvanced::~KBiffMailboxAdvanced()
{
TRACEINIT("KBiffMailboxAdvanced::~KBiffMailboxAdvanced()");
}

const KBiffURL KBiffMailboxAdvanced::getMailbox() const
{
	KBiffURL url(mailbox->text());
	url.setPass(password);
	return url;
}

const unsigned int KBiffMailboxAdvanced::getPort() const
{
	return QString(port->text()).toInt();
}

void KBiffMailboxAdvanced::setMailbox(const KBiffURL& url)
{
	password = url.pass();
	KBiffURL new_url(url);
	new_url.setPass("");
	mailbox->setText(new_url.url());
}

void KBiffMailboxAdvanced::setPort(unsigned int the_port, bool enable)
{
	port->setEnabled(enable);
	port->setText(QString().setNum(the_port));
}

void KBiffMailboxAdvanced::portModified(const QString& text)
{
	KBiffURL url = getMailbox();
	url.setPort(QString(text).toInt());
	setMailbox(url);
}

void KBiffMailboxAdvanced::setTimeout(unsigned int the_to, bool enable)
{
	timeout->setEnabled(enable);
	timeout->setText(QString().setNum(the_to));
}

void KBiffMailboxAdvanced::timeoutModified(const QString& text)
{
	KBiffURL url = getMailbox();
	url.setSearchPar("timeout", text.local8Bit());
	setMailbox(url);
}

void KBiffMailboxAdvanced::preauthModified(bool is_preauth)
{
TRACEINIT("KBiffMailboxAdvanced::preauthModified()");
	KBiffURL url = getMailbox();
	if (is_preauth)
		url.setSearchPar("preauth", "yes");
	else
		url.setSearchPar("preauth", "no");
	setMailbox(url);
}

void KBiffMailboxAdvanced::keepaliveModified(bool is_keepalive)
{
	KBiffURL url = getMailbox();
	if (is_keepalive)
		url.setSearchPar("keepalive", "yes");
	else
		url.setSearchPar("keepalive", "no");
	setMailbox(url);
}

void KBiffMailboxAdvanced::asyncModified(bool is_async)
{
	KBiffURL url = getMailbox();
	if (is_async)
		url.setSearchPar("async", "yes");
	else
		url.setSearchPar("async", "no");
	setMailbox(url);
}

void KBiffMailboxAdvanced::setPreauth(bool on)
{
	preauth->setEnabled(true);
	preauth->setChecked(on);
}

void KBiffMailboxAdvanced::setKeepalive(bool on)
{
	keepalive->setEnabled(true);
	keepalive->setChecked(on);
}

void KBiffMailboxAdvanced::setAsync(bool on)
{
	async->setEnabled(true);
	async->setChecked(on);
}

bool KBiffMailboxAdvanced::getPreauth() const
{
	return preauth->isChecked();
}

KBiffMailboxTab::KBiffMailboxTab(const QString& profile, QWidget *parent)
	: QWidget(parent), mailboxHash(new QDict<KBiffMailbox>)
{
TRACEINIT("KBiffMailboxTab::KBiffMailboxTab()");
	if (mailboxHash)
		mailboxHash->setAutoDelete(true);

	mailboxes = new QListView(this);
	mailboxes->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
	mailboxes->addColumn(i18n("Mailbox:"));
	mailboxes->header()->hide();

	QPushButton *new_mailbox = new QPushButton(this);
	new_mailbox->setPixmap(UserIcon("mailbox"));
	new_mailbox->setFixedSize(35, 20);
	QToolTip::add(new_mailbox, i18n("New Mailbox"));

	QPushButton *delete_mailbox = new QPushButton(this);
	delete_mailbox->setPixmap(UserIcon("delete"));
	delete_mailbox->setFixedSize(35, 20);
	QToolTip::add(delete_mailbox, i18n("Delete Mailbox"));

	QLabel *protocol_label = new QLabel(i18n("Pro&tocol:"), this);
	comboProtocol = new QComboBox(this);
	comboProtocol->insertItem("");
	comboProtocol->insertItem("mbox");
	comboProtocol->insertItem("maildir");	
	comboProtocol->insertItem("imap4");
	comboProtocol->insertItem("pop3");
	comboProtocol->insertItem("mh");
	comboProtocol->insertItem("file");
	comboProtocol->insertItem("nntp");
	protocol_label->setBuddy(comboProtocol);

	QLabel *mailbox_label = new QLabel(i18n("&Mailbox:"), this);
	editMailbox = new QLineEdit(this);
	mailbox_label->setBuddy(editMailbox);
	buttonBrowse = new QPushButton(i18n("..."), this);

	QLabel *server_label = new QLabel(i18n("&Server:"), this);
	editServer = new QLineEdit(this);
	server_label->setBuddy(editServer);

	QLabel *user_label = new QLabel(i18n("&User:"), this);
	editUser = new QLineEdit(this);
	user_label->setBuddy(editUser);

	QLabel *password_label = new QLabel(i18n("P&assword:"), this);
	editPassword = new QLineEdit(this);
	editPassword->setEchoMode(QLineEdit::Password);
	password_label->setBuddy(editPassword);

	checkStorePassword = new QCheckBox(i18n("S&tore password"), this);
	QPushButton *advanced_button = new QPushButton(i18n("&Advanced"), this);

	// connect all the signals
	connect(mailboxes, SIGNAL(selectionChanged(QListViewItem *)),
	                   SLOT(slotMailboxSelected(QListViewItem *)));
	connect(new_mailbox, SIGNAL(clicked()), SLOT(slotNewMailbox()));
	connect(delete_mailbox, SIGNAL(clicked()), SLOT(slotDeleteMailbox()));
	connect(comboProtocol, SIGNAL(highlighted(int)),
	                       SLOT(protocolSelected(int)));
	connect(buttonBrowse, SIGNAL(clicked()), SLOT(browse()));
	connect(advanced_button, SIGNAL(clicked()), SLOT(advanced()));

	// NOW DO THE LAYOUT
	QGridLayout *param_layout = new QGridLayout(7, 3, 12);
	param_layout->addWidget(protocol_label, 0, 0);
	param_layout->addWidget(comboProtocol, 0, 1, 1);
	param_layout->addWidget(buttonBrowse, 0, 2);
	param_layout->addWidget(mailbox_label, 1, 0);
	param_layout->addMultiCellWidget(editMailbox, 1, 1, 1, 2);
	param_layout->addWidget(server_label, 2, 0);
	param_layout->addMultiCellWidget(editServer, 2, 2, 1, 2);
	param_layout->addWidget(user_label, 3, 0);
	param_layout->addMultiCellWidget(editUser, 3, 3, 1, 2);
	param_layout->addWidget(password_label, 4, 0);
	param_layout->addMultiCellWidget(editPassword, 4, 4, 1, 2);
	param_layout->addMultiCellWidget(checkStorePassword, 5, 5, 1, 2);
	param_layout->addWidget(advanced_button, 6, 2);

	QGridLayout *mailbox_layout = new QGridLayout(2, 2);
	mailbox_layout->addMultiCellWidget(mailboxes, 0, 0, 0, 1);
	mailbox_layout->addWidget(new_mailbox, 1, 0);
	mailbox_layout->addWidget(delete_mailbox, 1, 1);

	QHBoxLayout *top_layout = new QHBoxLayout(this, 12);
	top_layout->addLayout(mailbox_layout);
	top_layout->addLayout(param_layout);

	readConfig(profile);
}

KBiffMailboxTab::~KBiffMailboxTab()
{
TRACEINIT("KBiffMailboxTab::~KBiffMailboxTab()");
	delete mailboxHash;
}

void KBiffMailboxTab::readConfig(const QString& profile)
{
TRACEINIT("KBiffMailboxTab::readConfig()");
	// initialize some variables that need initing
	oldItem = 0;

	// open the config file
	KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE, true);
	config->setDollarExpansion(false);

	mailboxHash->clear();
	mailboxes->clear();

	config->setGroup(profile);

	QStrList mailbox_list;

	int number_of_mailboxes = config->readListEntry("Mailboxes", mailbox_list, ',');

	if (number_of_mailboxes > 0)
	{
		for (unsigned int i = 0; i < mailbox_list.count(); i+=3)
		{
			KBiffMailbox *mailbox = new KBiffMailbox();
			QString key(mailbox_list.at(i));
			mailbox->url = KBiffURL(mailbox_list.at(i+1));
			QString password(scramble(mailbox_list.at(i+2), false));

			if (password.isEmpty())
				mailbox->store = false;
			else
			{
				mailbox->store = true;
				mailbox->url.setPass(password.data());
			}

			QListViewItem *item = new QListViewItem(mailboxes, key);
			item->setPixmap(0, QPixmap(UserIcon("mailbox")));

			mailboxHash->insert(key.data(), mailbox);
		}
	}
	else
	{
		KBiffMailbox *mailbox = new KBiffMailbox();
		mailbox->store = false;
		mailbox->url = defaultMailbox();
		mailboxHash->insert("Default", mailbox);

		QListViewItem *item = new QListViewItem(mailboxes, i18n("Default"));
		item->setPixmap(0, QPixmap(UserIcon("mailbox")));
	}

	mailboxes->setSelected(mailboxes->firstChild(), true);
	delete config;
}

void KBiffMailboxTab::saveConfig(const QString& profile)
{
TRACEINIT("KBiffMailboxTab::saveConfig()");
	// open the config file
	KSimpleConfig *config = new KSimpleConfig(CONFIG_FILE);
	config->setDollarExpansion(false);

	config->setGroup(profile);

	QStrList mailbox_list;

	for (QListViewItem *item = mailboxes->firstChild();
	     item;
		  item = item->nextSibling())
	{
		KBiffMailbox *mailbox = new KBiffMailbox();
		QString item_text(item->text(0));

		// if this mailbox is the current one, then use the current
		// settings instead of the hash
		if (item == mailboxes->currentItem())
		{
			mailbox->store = checkStorePassword->isChecked();
			mailbox->url   = getMailbox();

			mailboxHash->replace(item_text, mailbox);
		}

		mailbox = mailboxHash->find(item_text);

		QString password(scramble(mailbox->url.pass()));
		KBiffURL url = mailbox->url;
		url.setPass("");

		if (mailbox->store == false)
			password = "";
	
TRACEF("mailbox: %s -> %s", item_text.data(), url.url().data());
		mailbox_list.append(item_text);
		mailbox_list.append(url.url());
		mailbox_list.append(password);
	}

	config->writeEntry("Mailboxes", mailbox_list, ',');
	delete config;
}

void KBiffMailboxTab::setMailbox(const KBiffURL& url)
{
TRACEINIT("KBiff()");
	QString prot(url.protocol());

	if (prot == "mbox")
		protocolSelected(1);
	else if (prot == "maildir")
		protocolSelected(2);
	else if (prot == "imap4")
		protocolSelected(3);
	else if (prot == "pop3")
		protocolSelected(4);
	else if (prot == "mh")
		protocolSelected(5);
	else if (prot == "file")
		protocolSelected(6);
	else if (prot == "nntp")
		protocolSelected(7);
	else
		return;

	if (editMailbox->isEnabled())
	{
		QString path(url.path());
		if (((prot == "imap4") || (prot == "nntp")) && !path.isEmpty() && path[0] == '/')
				path.remove(0, 1);

		editMailbox->setText(path);
	}

	port = url.port();

	if (editServer->isEnabled())
		editServer->setText(url.host());
	if (editUser->isEnabled())
	{
		QString user(url.user());
		editUser->setText(user);
	}
	if (editPassword->isEnabled())
	{
		QString passwd(url.pass());
		editPassword->setText(passwd);
	}

	timeout = url.searchPar("timeout").toInt();
	preauth = !strcmp(url.searchPar("preauth"), "yes") ? true : false;
	keepalive = !strcmp(url.searchPar("keepalive"), "yes") ? true : false;
	async = !strcmp(url.searchPar("async"), "yes") ? true : false;
}

const KBiffURL KBiffMailboxTab::getMailbox() const
{
	KBiffURL url;

	url.setProtocol(comboProtocol->currentText());
	QString prot(url.protocol());

	if (editUser->isEnabled())
	{
		QString user(editUser->text());
		KBiffURL::encodeURLStrict(user);
		url.setUser(user);
	}

	if (editPassword->isEnabled())
	{
		QString passwd(editPassword->text());
		KBiffURL::encodeURLStrict(passwd);
		url.setPass(passwd);
	}

	if (editServer->isEnabled())
		url.setHost(editServer->text());

	url.setPort(port);

	if (editMailbox->isEnabled())
	{
		QString path(editMailbox->text());
		if (!path.isEmpty() && path[0] != '/')
			path.prepend("/");
		url.setPath(path);
	}

	if ((prot == "imap4") || (prot == "pop3") || (prot == "nntp"))
	{
		if (keepalive)
			url.setSearchPar("keepalive", "yes");
		else
			url.setSearchPar("keepalive", "no");

		if (async)
			url.setSearchPar("async", "yes");
		else
			url.setSearchPar("async", "no");

		url.setSearchPar("timeout", QString().setNum(timeout));
	}

	return url;
}

const QList<KBiffURL> KBiffMailboxTab::getMailboxList() const
{
TRACEINIT("KBiffMailboxTab::getMailboxList()");	
	QList<KBiffURL> url_list;

	for (QListViewItem *item = mailboxes->firstChild();
	     item;
		  item = item->nextSibling())
	{
		KBiffMailbox *mailbox = mailboxHash->find(item->text(0));
		KBiffURL *url = new KBiffURL(mailbox->url);
		url_list.append(url);
	}
	return url_list;
}

void KBiffMailboxTab::slotDeleteMailbox()
{
TRACEINIT("KBiffMailboxTab::slotDeleteMailbox()");
	/* I can't believe QListView doesn't have a 'count' member! */
	int count = 0;
	for (QListViewItem *it = mailboxes->firstChild();
	     it;
		  it = it->nextSibling(), count++);
	if (count == 1)
		return;

	/* need some "Are you sure?" code here */
	QListViewItem *item = mailboxes->currentItem();

	mailboxHash->remove(item->text(0));
	delete item;

	mailboxes->setSelected(mailboxes->firstChild(), true);
}

void KBiffMailboxTab::slotNewMailbox()
{
TRACEINIT("KBiffMailboxTab::slotNewMailbox()");
	KBiffNewDlg dlg;

	// popup the name chooser
	dlg.setCaption(i18n("New Mailbox"));
	if (dlg.exec())
	{
		QString mailbox_name = dlg.getName();

		// continue only if we received a decent name
		if (mailbox_name.isEmpty() == false)
		{
			QListViewItem *item = new QListViewItem(mailboxes, mailbox_name);
			item->setPixmap(0, QPixmap(UserIcon("mailbox")));

			KBiffMailbox *mailbox = new KBiffMailbox();
			mailbox->store = false;
			mailbox->url   = defaultMailbox();

			mailboxHash->insert(mailbox_name.data(), mailbox);
			mailboxes->setSelected(item, true);
		}
	}
}

void KBiffMailboxTab::slotMailboxSelected(QListViewItem *item)
{
TRACEINIT("KBiffMailboxTab::slotMailboxSelected()");
	KBiffMailbox *mailbox;

	// if an "old" item exists, save the current info as it
	if (oldItem && oldItem->text(0))
	{
		mailbox = mailboxHash->find(oldItem->text(0));

		if (mailbox)
		{
			// change the hash only if the item is different
			KBiffURL url(getMailbox());
			bool checked = checkStorePassword->isChecked();
			if (mailbox->url.url() != url.url() || mailbox->store != checked)
			{
				mailbox->url   = getMailbox();
				mailbox->store = checkStorePassword->isChecked();
			}
		}
	}

	mailbox = mailboxHash->find(item->text(0));

	if (mailbox)
	{
		setMailbox(mailbox->url);
		checkStorePassword->setChecked(mailbox->store);

		// save this as the "old" item
		oldItem = item;
	}
}

void KBiffMailboxTab::protocolSelected(int protocol)
{
TRACEINIT("KBiffMailboxTab::protocolSelected()");
	comboProtocol->setCurrentItem(protocol);

	switch (protocol)
	{
		case 1: // mbox
		case 2: // maildir
		case 5: // mh
		case 6: // file
			port = 0;
			buttonBrowse->setEnabled(true);
			editMailbox->setEnabled(true);
			editServer->setEnabled(false);
			editUser->setEnabled(false);
			editPassword->setEnabled(false);
			checkStorePassword->setEnabled(false);
			break;
		case 3: // IMAP4
			port = 143;
			timeout = 10;
			editMailbox->setEnabled(true);
			buttonBrowse->setEnabled(false);
			editServer->setEnabled(true);
			editUser->setEnabled(true);
			editPassword->setEnabled(true);
			checkStorePassword->setEnabled(true);
			break;
		case 7: // NNTP
			port = 119;
			timeout = 10;
			editMailbox->setEnabled(true);
			buttonBrowse->setEnabled(false);
			editServer->setEnabled(true);
			editUser->setEnabled(true);
			editPassword->setEnabled(true);
			checkStorePassword->setEnabled(true);
			break;
		case 4: // POP3
			port = 110;
			timeout = 10;
			editMailbox->setEnabled(false);
			buttonBrowse->setEnabled(false);
			editServer->setEnabled(true);
			editUser->setEnabled(true);
			editPassword->setEnabled(true);
			checkStorePassword->setEnabled(true);
			break;
		default: // blank
			port = 0;
			timeout = 0;
			editMailbox->setEnabled(false);
			buttonBrowse->setEnabled(false);
			editServer->setEnabled(false);
			editUser->setEnabled(false);
			editPassword->setEnabled(false);
			checkStorePassword->setEnabled(false);
			break;
	}
}

void KBiffMailboxTab::browse()
{
  KURL url = KFileDialog::getOpenURL();

  if( url.isEmpty() )
    return;

  if( !url.isLocalFile() )
  {
    KMessageBox::sorry( 0, i18n( "Only local files supported yet." ) );
    return;
  }
  
  if( !url.isEmpty() )
  {
    editMailbox->setText( url.path() );
  }
}

void KBiffMailboxTab::advanced()
{
	KBiffMailboxAdvanced advanced_dlg;
	QString prot(getMailbox().protocol());
	
	if (prot == "mbox" || prot == "maildir" || prot == "file" || prot == "mh")
	{
		advanced_dlg.setPort(port, false);
		advanced_dlg.setTimeout(timeout, false);
	}
	else
	{
		advanced_dlg.setPort(port);
		advanced_dlg.setTimeout(timeout);
	}

	if (prot == "imap4")
	{
		advanced_dlg.setPreauth(preauth);
		advanced_dlg.setKeepalive(keepalive);
		advanced_dlg.setAsync(async);
	}

	if ((prot == "pop3") || (prot == "nntp"))
	{
		advanced_dlg.setKeepalive(keepalive);
		advanced_dlg.setAsync(async);
	}

	advanced_dlg.setMailbox(getMailbox());
	if (advanced_dlg.exec())
	{
		port = advanced_dlg.getPort();
		setMailbox(advanced_dlg.getMailbox());
	}
}

const QString KBiffMailboxTab::scramble(const QString& password, bool encode)
{
	if (password.isEmpty())
		return QString::null;

	const char* pass_ptr = (const char*)password;
	char *ptr = new char[strlen(password) + 1];
	char *ret_ptr = ptr;

	while (*pass_ptr)
		*ptr++ = encode ? (*(pass_ptr++) - 4) : (*(pass_ptr++) + 4);
	*ptr = '\0';

	return ret_ptr;
}

const KBiffURL KBiffMailboxTab::defaultMailbox() const
{
	QFileInfo mailbox_info(getenv("MAIL"));
	if (mailbox_info.exists() == false)
	{
		QString s(_PATH_MAILDIR);
		s += "/";
		s += getpwuid(getuid())->pw_name;
		mailbox_info.setFile(s);
	}

	QString *default_path = mailbox_info.isDir() ? new QString("maildir:") :
	                                               new QString("mbox:");
	default_path->append(mailbox_info.absFilePath());

	return KBiffURL(*default_path);
}

//////////////////////////////////////////////////////////////////////
// KBiffAboutTab
//////////////////////////////////////////////////////////////////////
KBiffAboutTab::KBiffAboutTab(QWidget *parent)
	: QWidget(parent)
{
TRACEINIT("KBiffAboutTab::KBiffAboutTab()");

	// load in the kbiff pixmap
	QPixmap logo_pixmap(kapp->icon());

	QLabel *pixmap_label = new QLabel(this);
	pixmap_label->setPixmap(logo_pixmap);

	// we want a bigger logo
	QFont logo_font = QFont::defaultFont();
	logo_font.setPointSize(logo_font.pointSize() * 1.5);
	logo_font.setBold(true);

	KURLLabel *logo_label = new KURLLabel(this);
	logo_label->setURL("http://www.pobox.com/~kurt_granroth/kbiff");
	logo_label->setFont(logo_font);
	logo_label->setText("KBiff");
	logo_label->setUnderline(false);
	logo_label->setGlow(false);
	logo_label->setFloat(true);
	connect(logo_label, SIGNAL(leftClickedURL(const QString&)),
	                    SLOT(homepage(const QString&)));

	QLabel *version_label = new QLabel(this);
	version_label->setText(QString("Version %1\n\nCopyright (C) 1999\nKurt Granroth").arg("2.3.11cvs"));

	KURLLabel *email_label = new KURLLabel(this);
	email_label->setText("granroth@kde.org");
	email_label->setURL("granroth@kde.org");
	email_label->setUnderline(false);
	email_label->setGlow(false);
	email_label->setFloat(true);
	connect(email_label, SIGNAL(leftClickedURL(const QString&)),
	                     SLOT(mailTo(const QString&)));

	// about tab text layout
	QVBoxLayout *text_layout = new QVBoxLayout(0);
	text_layout->addWidget(version_label);
	text_layout->addWidget(email_label);

	// main about tab layout
	QGridLayout *about_layout = new QGridLayout(this, 3, 2, 12, 0);
	about_layout->addWidget(pixmap_label, 0, 0);
	about_layout->addWidget(logo_label, 0, 1);
	about_layout->addLayout(text_layout, 1, 1);
	about_layout->setRowStretch(2, 1);
}

KBiffAboutTab::~KBiffAboutTab()
{
}

void KBiffAboutTab::mailTo(const QString& url)
{
	// this kludge is necessary until KFM handles mailto: urls
	char *mailer = getenv("MAILER");
	if (mailer)
	{
		KProcess mailto;
		mailto << mailer << "-s" << "\"KBiff\"" << url;
		mailto.start(KProcess::DontCare);
	}
}

void KBiffAboutTab::homepage(const QString& url)
{
	(void) new KRun ( url );
}

KBiffNewDlg::KBiffNewDlg(QWidget* parent, const QString& name)
	: QDialog(parent, name, true, 0)
{
	// set my name
	setCaption(i18n("New Name"));

	QLabel* label = new QLabel(i18n("&New Name:"), this);
	editName = new QLineEdit(this);
	editName->setFocus();
	label->setBuddy(editName);

	// ok button
	QPushButton* button_ok = new QPushButton(i18n("&OK"), this);
	button_ok->setDefault(true);

	// cancel button
	QPushButton* button_cancel = new QPushButton(i18n("&Cancel"), this);

	connect(button_ok, SIGNAL(clicked()), SLOT(accept()));
	connect(button_cancel, SIGNAL(clicked()), SLOT(reject()));

	// NOW DO THE LAYOUT
	QGridLayout *top_layout = new QGridLayout(this, 2, 3, 12);
	top_layout->addWidget(label, 0, 0);
	top_layout->addMultiCellWidget(editName, 0, 0, 1, 2);
	top_layout->addWidget(button_ok, 1, 1);
	top_layout->addWidget(button_cancel, 1, 2);
}
