#include "opt_iconset.h"
#include "common.h"
#include "iconwidget.h"
#include "psicon.h"

#include <qbuttongroup.h>
#include <qwhatsthis.h>
#include <qcheckbox.h>
#include <qradiobutton.h>
#include <qcombobox.h>
#include <qlineedit.h>
#include <qfileinfo.h>
#include <qlistview.h>
#include <qheader.h>
#include <qapplication.h>
#include <qthread.h>
#include <qmutex.h>
#include <qevent.h>
#include <qprogressbar.h>
#include <qcursor.h>
#include <qpalette.h>
#include <qtabwidget.h>

#include "opt_iconset_emo.h"
#include "opt_iconset_system.h"
#include "opt_iconset_roster.h"
#include "ui_isdetails.h"

static void isDetails(const Iconset &is, QWidget *parent)
{
	IconsetDetailsDlg *isd = new IconsetDetailsDlg(parent, "IconsetDetailsDlg", false, QWidget::WDestructiveClose);
	isd->setIconset(is);
	isd->show();
}

static QStringList dirs;

static int countIconsets(QString addDir, QStringList excludeList)
{
	int count = 0;

	QStringList::Iterator it = dirs.begin();
	for ( ; it != dirs.end(); ++it) {
		QString fileName = *it + "/iconsets" + addDir;
		QDir dir (fileName);

		QStringList list = dir.entryList("*");
		QStringList::Iterator it2 = list.begin();
		for ( ; it2 != list.end(); ++it2) {
			if ( *it2 == "." || *it2 == ".." )
				continue;

			bool found = false;
			QStringList::Iterator it3 = excludeList.begin();
			for ( ; it3 != excludeList.end(); ++it3) {
				if ( *it2 == *it3 ) {
					found = true;
					break;
				}
			}

			if ( found )
				continue;

			count++;
			excludeList << *it2;
		}
	}

	return count;
}

//----------------------------------------------------------------------------
// IconsetLoadEvent
//----------------------------------------------------------------------------

class IconsetLoadEvent : public QEvent
{
public:
	IconsetLoadEvent(IconsetLoadThread *par, Iconset *i)
	: QEvent(QEvent::User)
	{
		p  = par;
		is = i;
	}

	IconsetLoadThread *thread() const { return p; }

	// if iconset() is '0' then it means that iconset wans't loaded successfully
	Iconset *iconset() const { return is; }

private:
	IconsetLoadThread *p;
	Iconset *is;
};

//----------------------------------------------------------------------------
// IconsetFinishEvent
//----------------------------------------------------------------------------

class IconsetFinishEvent : public QEvent
{
public:
	IconsetFinishEvent()
	: QEvent( (QEvent::Type)(QEvent::User + 1) )
	{
	}
};


//----------------------------------------------------------------------------
// IconsetLoadThreadDestroyEvent
//----------------------------------------------------------------------------

class IconsetLoadThreadDestroyEvent : public QEvent
{
public:
	IconsetLoadThreadDestroyEvent(QThread *t)
	: QEvent( (QEvent::Type)(QEvent::User + 2) )
	{
		thread = t;
	}

	~IconsetLoadThreadDestroyEvent()
	{
		thread->wait();
		delete thread;
	}

private:
	QThread *thread;
};

//----------------------------------------------------------------------------
// IconsetLoadThread
//----------------------------------------------------------------------------

class IconsetLoadThread : public QThread
{
public:
	IconsetLoadThread(QObject *parent, QString addPath);
	void excludeIconsets(QStringList);

	bool cancelled;

protected:
	void run();
	void postEvent(QEvent *);

private:
	QObject *parent;
	QString addPath;
	QStringList excludeList;
};

IconsetLoadThread::IconsetLoadThread(QObject *p, QString path)
{
	cancelled = false;
	parent  = p;
	addPath = path;
}

void IconsetLoadThread::excludeIconsets(QStringList l)
{
	excludeList += l;
}

static QMutex threadCancelled, threadMutex;

void IconsetLoadThread::postEvent(QEvent *e)
{
	threadCancelled.lock();
	bool cancel = cancelled;
	threadCancelled.unlock();

	if ( cancel ) {
		delete e;
		return;
	}

	QApplication::postEvent(parent, e);
}

void IconsetLoadThread::run()
{
	threadMutex.lock();
	QStringList dirs = ::dirs;
	threadMutex.unlock();

	QStringList::Iterator it = dirs.begin();
	for ( ; it != dirs.end(); ++it) {
		QString fileName = *it + "/iconsets" + addPath;
		QDir dir (fileName);

		QStringList list = dir.entryList("*");
		QStringList::Iterator it2 = list.begin();
		for ( ; it2 != list.end(); ++it2) {
			if ( *it2 == "." || *it2 == ".." )
				continue;

			threadCancelled.lock();
			bool cancel = cancelled;
			threadCancelled.unlock();

			if ( cancel )
				goto getout;

			bool found = false;
			QStringList::Iterator it3 = excludeList.begin();
			for ( ; it3 != excludeList.end(); ++it3) {
				if ( *it2 == *it3 ) {
					found = true;
					break;
				}
			}

			if ( found )
				continue;

			IconsetLoadEvent *event = 0;
			Iconset *is = new Iconset;

			if ( is->load (fileName + "/" + *it2) ) {
				excludeList << *it2;

				// don't forget to delete iconset in ::event()!
				event = new IconsetLoadEvent(this, is);
			}
			else {
				delete is;
				event = new IconsetLoadEvent(this, 0);

				// without excluding corrupted iconset,
				// counter will go nuts! read more comments
				// about that...
				excludeList << *it2;
				// TODO: there is possibility,
				// that there's a bunch of same-named
				// iconsets, and some of them are corrupted.
				// It is possible to write a hack that
				// loads iconset even in that case.

				// logic:
				//   tried to load iconset --> unable to load
				//   checking if there's same-named iconsets in
				//   other directories
				//   emit IconsetLoadEvent() only on success
				//   or when last corrupted iconset was unable
				//   to load
			}

			postEvent(event);
		}
	}

getout:
	postEvent(new IconsetFinishEvent());
	QApplication::postEvent(qApp, new IconsetLoadThreadDestroyEvent(this)); // self destruct
}

//----------------------------------------------------------------------------
// OptionsTabIconsetSystem
//----------------------------------------------------------------------------

OptionsTabIconsetSystem::OptionsTabIconsetSystem(QObject *parent)
: OptionsTab(parent, "iconset_system", "", tr("System Icons"), tr("Select the system iconset"))
{
	w = 0;
	thread = 0;

	if ( dirs.isEmpty() ) {
		dirs << ".";
		dirs << g.pathHome;
		dirs << g.pathBase;
	}
}

OptionsTabIconsetSystem::~OptionsTabIconsetSystem()
{
	cancelThread();
}

QWidget *OptionsTabIconsetSystem::widget()
{
	if ( w )
		return 0;

	w = new IconsetSystemUI;
	IconsetSystemUI *d = (IconsetSystemUI *)w;

	connect(d->pb_sysDetails, SIGNAL(clicked()), SLOT(previewIconset()));

	// TODO: add QWhatsThis

	return w;
}

void OptionsTabIconsetSystem::applyOptions(Options *opt)
{
	if ( !w || thread )
		return;

	IconsetSystemUI *d = (IconsetSystemUI *)w;
	const Iconset *is = d->iss_system->iconset();
	if ( is ) {
		QFileInfo fi( is->fileName() );
		opt->systemIconset = fi.fileName();
	}
}

void OptionsTabIconsetSystem::restoreOptions(const Options *opt)
{
	if ( !w || thread )
		return;

	o = (Options *)opt;
	IconsetSystemUI *d = (IconsetSystemUI *)w;
	d->iss_system->clear();
	QStringList loaded;

	d->setCursor(WaitCursor);

	QPalette customPal = d->palette();
	customPal.setDisabled(customPal.inactive());
	d->iss_system->setEnabled(false);
	d->iss_system->setPalette(customPal);

	d->pb_sysDetails->setEnabled(false);
	d->pb_sysDetails->setPalette(customPal);

	d->progress->show();
	d->progress->setProgress( 0 );

	numIconsets = countIconsets("/system", loaded);
	iconsetsLoaded = 0;

	cancelThread();

	thread = new IconsetLoadThread(this, "/system");
	thread->start();
}

bool OptionsTabIconsetSystem::event(QEvent *e)
{
	IconsetSystemUI *d = (IconsetSystemUI *)w;
	if ( e->type() == QEvent::User ) { // iconset load event
		IconsetLoadEvent *le = (IconsetLoadEvent *)e;

		if ( thread != le->thread() )
			return false;

		if ( !numIconsets )
			numIconsets = 1;
		d->progress->setProgress( (int)((float)100 * ++iconsetsLoaded / numIconsets) );

		Iconset *i = le->iconset();
		if ( i ) {
			is->stripFirstAnimFrame(i);
			d->iss_system->insert(*i);

			QFileInfo fi( i->fileName() );
			if ( fi.fileName() == o->systemIconset )
				d->iss_system->setSelected(d->iss_system->count()-1, true);

			delete i;
		}

		return true;
	}
	else if ( e->type() == QEvent::User + 1 ) { // finish event
		d->iss_system->setEnabled(true);
		d->iss_system->unsetPalette();

		d->pb_sysDetails->setEnabled(true);
		d->pb_sysDetails->unsetPalette();

		connect(d->iss_system, SIGNAL(selectionChanged()), SIGNAL(dataChanged()));

		d->progress->hide();

		d->unsetCursor();
		thread = 0;

		return true;
	}

	return false;
}

void OptionsTabIconsetSystem::previewIconset()
{
	IconsetSystemUI *d = (IconsetSystemUI *)w;
	const Iconset *is = d->iss_system->iconset();
	if ( is )
		isDetails(*is, parentWidget);
}

void OptionsTabIconsetSystem::setData(PsiCon *, QWidget *p)
{
	parentWidget = p;
}

void OptionsTabIconsetSystem::cancelThread()
{
	if ( thread ) {
		threadCancelled.lock();
		thread->cancelled = true;
		threadCancelled.unlock();

		thread = 0;
	}
}

//----------------------------------------------------------------------------
// OptionsTabIconsetEmoticons
//----------------------------------------------------------------------------

OptionsTabIconsetEmoticons::OptionsTabIconsetEmoticons(QObject *parent)
: OptionsTab(parent, "iconset_emoticons", "", tr("Emoticons"), tr("Select your emoticon iconsets"))
{
	w = 0;
	thread = 0;
}

OptionsTabIconsetEmoticons::~OptionsTabIconsetEmoticons()
{
	cancelThread();
}

QWidget *OptionsTabIconsetEmoticons::widget()
{
	if ( w )
		return 0;

	w = new IconsetEmoUI;
	IconsetEmoUI *d = (IconsetEmoUI *)w;

	connect(d->pb_emoUp, SIGNAL(clicked()), d->iss_emoticons, SLOT(moveItemUp()));
	connect(d->pb_emoUp, SIGNAL(clicked()), SIGNAL(dataChanged()));
	connect(d->pb_emoDown, SIGNAL(clicked()), d->iss_emoticons, SLOT(moveItemDown()));
	connect(d->pb_emoDown, SIGNAL(clicked()), SIGNAL(dataChanged()));
	connect(d->pb_emoDetails, SIGNAL(clicked()), SLOT(previewIconset()));

	QWhatsThis::add(d->ck_useEmoticons,
		tr("<P>Emoticons are short sequences of characters that are used to convey an emotion or idea.</P>"
		"<P>Enable this option if you want Psi to replace common emoticons with a graphical image.</P>"
		"<P>For example, <B>:-)</B> would be replaced by <icon name=\"psi/smile\"></P>"));

	// TODO: add QWhatsThis

	return w;
}

void OptionsTabIconsetEmoticons::applyOptions(Options *opt)
{
	if ( !w || thread )
		return;

	IconsetEmoUI *d = (IconsetEmoUI *)w;
	opt->useEmoticons = d->ck_useEmoticons->isChecked();

	opt->emoticons.clear();
	IconWidgetItem *item = (IconWidgetItem *)d->iss_emoticons->firstItem();
	while ( item ) {
		if ( item->isSelected() ) {
			const Iconset *is = item->iconset();
			if ( is ) {
				QFileInfo fi( is->fileName() );
				opt->emoticons << fi.fileName();
			}
		}

		item = (IconWidgetItem *)item->next();
	}

}

void OptionsTabIconsetEmoticons::restoreOptions(const Options *opt)
{
	if ( !w || thread )
		return;

	IconsetEmoUI *d = (IconsetEmoUI *)w;
	d->ck_useEmoticons->setChecked( opt->useEmoticons );

	// fill in the iconset view
	d->iss_emoticons->clear();

	{
		QPtrListIterator<Iconset> it ( is->emoticons );
		Iconset *is;
		for ( ; (is = it.current()); ++it) {
			d->iss_emoticons->insert(*is);
			d->iss_emoticons->setSelected(d->iss_emoticons->count()-1, true);
		}
	}


	{
		QStringList loaded;
		{
			QPtrListIterator<Iconset> it( is->emoticons );
			Iconset *tmp;
			for ( ; (tmp = it.current()); ++it) {
				QFileInfo fi ( tmp->fileName() );
				loaded << fi.fileName();
			}
		}

		d->setCursor(WaitCursor);

		QPalette customPal = d->palette();
		customPal.setDisabled(customPal.inactive());
		d->ck_useEmoticons->setEnabled(false);
		d->ck_useEmoticons->setPalette(customPal);

		d->groupBox9->setEnabled(false);
		d->groupBox9->setPalette(customPal);

		d->progress->show();
		d->progress->setProgress( 0 );

		numIconsets = countIconsets("/emoticons", loaded);
		iconsetsLoaded = 0;

		cancelThread();

		thread = new IconsetLoadThread(this, "/emoticons");
		thread->excludeIconsets(loaded);
		thread->start();
	}
}

bool OptionsTabIconsetEmoticons::event(QEvent *e)
{
	IconsetEmoUI *d = (IconsetEmoUI *)w;
	if ( e->type() == QEvent::User ) { // iconset load event
		IconsetLoadEvent *le = (IconsetLoadEvent *)e;

		if ( thread != le->thread() )
			return false;

		if ( !numIconsets )
			numIconsets = 1;
		d->progress->setProgress( (int)((float)100 * ++iconsetsLoaded / numIconsets) );

		Iconset *is = le->iconset();
		if ( is ) {
			PsiIconset::removeAnimation(is);
			d->iss_emoticons->insert(*is);
			delete is;
		}

		return true;
	}
	else if ( e->type() == QEvent::User + 1 ) { // finish event
		d->ck_useEmoticons->setEnabled(true);
		d->ck_useEmoticons->unsetPalette();

		d->groupBox9->setEnabled(true);
		d->groupBox9->unsetPalette();

		connect(d->iss_emoticons, SIGNAL(selectionChanged()), SIGNAL(dataChanged()));

		bool checked = d->ck_useEmoticons->isChecked();
		d->ck_useEmoticons->setChecked( true );
		d->ck_useEmoticons->setChecked( checked );

		d->progress->hide();

		d->unsetCursor();
		thread = 0;

		return true;
	}

	return false;
}

void OptionsTabIconsetEmoticons::previewIconset()
{
	IconsetEmoUI *d = (IconsetEmoUI *)w;
	const Iconset *is = d->iss_emoticons->iconset();
	if ( is )
		isDetails(*is, parentWidget);
}

void OptionsTabIconsetEmoticons::setData(PsiCon *, QWidget *p)
{
	parentWidget = p;
}

void OptionsTabIconsetEmoticons::cancelThread()
{
	if ( thread ) {
		threadCancelled.lock();
		thread->cancelled = true;
		threadCancelled.unlock();

		thread = 0;
	}
}

//----------------------------------------------------------------------------
// OptionsTabIconsetRoster
//----------------------------------------------------------------------------

OptionsTabIconsetRoster::OptionsTabIconsetRoster(QObject *parent)
: OptionsTab(parent, "iconset_roster", "", tr("Roster Icons"), tr("Select iconsets for your roster"))
{
	w = 0;
	thread = 0;
}

OptionsTabIconsetRoster::~OptionsTabIconsetRoster()
{
	cancelThread();
}

QWidget *OptionsTabIconsetRoster::widget()
{
	if ( w )
		return 0;

	w = new IconsetRosterUI;
	IconsetRosterUI *d = (IconsetRosterUI *)w;

	connect(d->pb_defRosterDetails, SIGNAL(clicked()), SLOT(defaultDetails()));

	connect(d->iss_servicesRoster, SIGNAL(selectionChanged(QListBoxItem *)), SLOT(isServices_iconsetSelected(QListBoxItem *)));
	connect(d->lv_isServices, SIGNAL(selectionChanged(QListViewItem *)), SLOT(isServices_selectionChanged(QListViewItem *)));
	connect(d->pb_servicesDetails, SIGNAL(clicked()), SLOT(servicesDetails()));
	isServices_selectionChanged(0);

	connect(d->iss_customRoster, SIGNAL(selectionChanged(QListBoxItem *)), SLOT(isCustom_iconsetSelected(QListBoxItem *)));
	connect(d->lv_customRoster, SIGNAL(selectionChanged(QListViewItem *)), SLOT(isCustom_selectionChanged(QListViewItem *)));
	connect(d->pb_customRosterDetails, SIGNAL(clicked()), SLOT(customDetails()));
	connect(d->le_customRoster, SIGNAL(textChanged(const QString &)), SLOT(isCustom_textChanged()));
	connect(d->pb_customRosterAdd, SIGNAL(clicked()), SLOT(isCustom_add()));
	connect(d->pb_customRosterDelete, SIGNAL(clicked()), SLOT(isCustom_delete()));
	isCustom_selectionChanged(0);

	QWhatsThis::add(d->ck_useTransportIconsForContacts,
		tr("Toggles use of transport icons to the contacts, that use that transports."));

	// TODO: add QWhatsThis

	return w;
}

void OptionsTabIconsetRoster::applyOptions(Options *opt)
{
	if ( !w || thread )
		return;

	IconsetRosterUI *d = (IconsetRosterUI *)w;
	opt->useTransportIconsForContacts = d->ck_useTransportIconsForContacts->isChecked();

	// roster - default
	{
		const Iconset *is = d->iss_defRoster->iconset();
		if ( is ) {
			QFileInfo fi( is->fileName() );
			opt->defaultRosterIconset = fi.fileName();
		}
	}

	// roster - services
	{
		opt->serviceRosterIconset.clear();

		QListViewItemIterator it( d->lv_isServices );
		for ( ; it.current(); ++it) {
			QListViewItem *item = it.current();

			opt->serviceRosterIconset[item->text(2)] = item->text(3);
		}
	}

	// roster - custom
	{
		opt->customRosterIconset.clear();

		QListViewItemIterator it( d->lv_customRoster );
		for ( ; it.current(); ++it) {
			QListViewItem *item = it.current();

			opt->customRosterIconset[item->text(2)] = item->text(3);
		}
	}
}

void OptionsTabIconsetRoster::restoreOptions(const Options *opt)
{
	if ( !w || thread )
		return;

	o = (Options *)opt;
	IconsetRosterUI *d = (IconsetRosterUI *)w;
	d->ck_useTransportIconsForContacts->setChecked( opt->useTransportIconsForContacts );

	d->iss_defRoster->clear();
	d->iss_servicesRoster->clear();
	d->iss_customRoster->clear();

	QStringList loaded;

	d->setCursor(WaitCursor);

	QPalette customPal = d->palette();
	customPal.setDisabled(customPal.inactive());
	d->tabWidget3->setEnabled(false);
	d->tabWidget3->setPalette(customPal);

	d->progress->show();
	d->progress->setProgress( 0 );

	numIconsets = countIconsets("/roster", loaded);
	iconsetsLoaded = 0;

	cancelThread();

	thread = new IconsetLoadThread(this, "/roster");
	thread->start();
}

bool OptionsTabIconsetRoster::event(QEvent *e)
{
	IconsetRosterUI *d = (IconsetRosterUI *)w;
	if ( e->type() == QEvent::User ) { // iconset load event
		IconsetLoadEvent *le = (IconsetLoadEvent *)e;

		if ( thread != le->thread() )
			return false;

		if ( !numIconsets )
			numIconsets = 1;
		d->progress->setProgress( (int)((float)100 * ++iconsetsLoaded / numIconsets) );

		Iconset *i = le->iconset();
		if ( i ) {
			is->stripFirstAnimFrame(i);
			QFileInfo fi( i->fileName() );

			// roster - default
			d->iss_defRoster->insert(*i);
			if ( fi.fileName() == o->defaultRosterIconset )
				d->iss_defRoster->setSelected(d->iss_defRoster->count()-1, true);

			// roster - service
			d->iss_servicesRoster->insert(*i);

			// roster - custom
			d->iss_customRoster->insert(*i);

			delete i;
		}

		return true;
	}
	else if ( e->type() == QEvent::User + 1 ) { // finish event
		// roster - service
		{
			// fill the QListView
			QListViewItemIterator it( d->lv_isServices );
			for ( ; it.current(); ++it) {
				QListViewItem *i = it.current();
				if ( !i->text(2).isEmpty() ) {
					Iconset *iss = is->roster[o->serviceRosterIconset[i->text(2)]];
					if ( iss ) {
						i->setText(1, iss->name());

						QFileInfo fi ( iss->fileName() );
						i->setText(3, fi.fileName());
					}
				}
			}

			QHeader *head = d->lv_isServices->header();
			head->removeLabel(2);
		}

		// roster - custom
		{
			// Then, fill the QListView
			QListViewItem *last = 0;
			QMap<QString, QString>::ConstIterator it = o->customRosterIconset.begin();
			for ( ; it != o->customRosterIconset.end(); ++it) {
				QListViewItem *item = new QListViewItem(d->lv_customRoster, last);
				last = item;

				item->setText(0, clipCustomText(it.key())); // RegExp
				item->setText(2, it.key());

				Iconset *iss = is->roster[it.data()];
				if ( iss ) {
					item->setText(1, iss->name());

					QFileInfo fi ( iss->fileName() );
					item->setText(3, fi.fileName());
				}
			}
		}

		d->tabWidget3->setEnabled(true);
		d->tabWidget3->unsetPalette();

		connect(d->iss_defRoster, SIGNAL(selectionChanged()), SIGNAL(dataChanged()));
		connect(d->iss_servicesRoster, SIGNAL(selectionChanged()), SIGNAL(dataChanged()));
		connect(d->iss_customRoster, SIGNAL(selectionChanged()), SIGNAL(dataChanged()));

		d->progress->hide();

		d->unsetCursor();
		thread = 0;

		return true;
	}

	return false;
}

void OptionsTabIconsetRoster::setData(PsiCon *, QWidget *p)
{
	parentWidget = p;
}

void OptionsTabIconsetRoster::defaultDetails()
{
	IconsetRosterUI *d = (IconsetRosterUI *)w;
	const Iconset *is = d->iss_defRoster->iconset();
	if ( is )
		isDetails(*is, parentWidget);
}

void OptionsTabIconsetRoster::servicesDetails()
{
	IconsetRosterUI *d = (IconsetRosterUI *)w;
	const Iconset *is = d->iss_servicesRoster->iconset();
	if ( is )
		isDetails(*is, parentWidget);
}

void OptionsTabIconsetRoster::customDetails()
{
	IconsetRosterUI *d = (IconsetRosterUI *)w;
	const Iconset *is = d->iss_customRoster->iconset();
	if ( is )
		isDetails(*is, parentWidget);
}

//------------------------------------------------------------

void OptionsTabIconsetRoster::isServices_iconsetSelected(QListBoxItem *item)
{
	if ( !item )
		return;

	IconsetRosterUI *d = (IconsetRosterUI *)w;
	QListViewItem *it = d->lv_isServices->selectedItem();
	if ( !it )
		return;

	const Iconset *is = ((IconWidgetItem *)item)->iconset();
	if ( !is )
		return;

	it->setText(1, is->name());
	QFileInfo fi ( is->fileName() );
	it->setText(3, fi.fileName());
}

void OptionsTabIconsetRoster::isServices_selectionChanged(QListViewItem *it)
{
	IconsetRosterUI *d = (IconsetRosterUI *)w;
	d->iss_servicesRoster->setEnabled( it != 0 );
	d->pb_servicesDetails->setEnabled( it != 0 );
	d->iss_servicesRoster->clearSelection();
	if ( !it )
		return;

	if ( it->text(3).isEmpty() )
		return;

	QString name = it->text(3);

	emit noDirty(true);
	IconWidgetItem *item = (IconWidgetItem *)d->iss_servicesRoster->firstItem();
	for ( ; item; item = (IconWidgetItem *)item->next()) {
		const Iconset *is = item->iconset();
		if ( is ) {
			QFileInfo fi ( is->fileName() );
			if ( fi.fileName() == name ) {
				emit noDirty(true);
				d->iss_servicesRoster->setSelected(item, true);
				d->iss_servicesRoster->ensureCurrentVisible();
				emit noDirty(false);
				break;
			}
		}
	}
	qApp->processEvents();
	emit noDirty(false);
}

//------------------------------------------------------------

void OptionsTabIconsetRoster::isCustom_iconsetSelected(QListBoxItem *item)
{
	if ( !item )
		return;

	IconsetRosterUI *d = (IconsetRosterUI *)w;
	QListViewItem *it = d->lv_customRoster->selectedItem();
	if ( !it )
		return;

	const Iconset *is = ((IconWidgetItem *)item)->iconset();
	if ( !is )
		return;

	it->setText(1, is->name());
	QFileInfo fi ( is->fileName() );
	it->setText(3, fi.fileName());
}

void OptionsTabIconsetRoster::isCustom_selectionChanged(QListViewItem *it)
{
	IconsetRosterUI *d = (IconsetRosterUI *)w;
	d->iss_customRoster->setEnabled( it != 0 );
	d->pb_customRosterDetails->setEnabled( it != 0 );
	//d->pb_customRosterAdd->setEnabled( it != 0 );
	d->pb_customRosterDelete->setEnabled( it != 0 );
	d->le_customRoster->setEnabled( it != 0 );
	d->iss_customRoster->clearSelection();
	if ( !it )
		return;

	if ( it->text(3).isEmpty() )
		return;

	emit noDirty(true);
	d->le_customRoster->setText(it->text(2));
	QString name = it->text(3);

	IconWidgetItem *item = (IconWidgetItem *)d->iss_customRoster->firstItem();
	for ( ; item; item = (IconWidgetItem *)item->next()) {
		const Iconset *is = item->iconset();
		if ( is ) {
			QFileInfo fi ( is->fileName() );
			if ( fi.fileName() == name ) {
				d->iss_customRoster->setSelected(item, true);
				d->iss_customRoster->ensureCurrentVisible();
				break;
			}
		}
	}
	qApp->processEvents();
	emit noDirty(false);
}

void OptionsTabIconsetRoster::isCustom_textChanged()
{
	IconsetRosterUI *d = (IconsetRosterUI *)w;
	QListViewItem *item = d->lv_customRoster->selectedItem();
	if ( !item )
		return;

	item->setText( 0, clipCustomText(d->le_customRoster->text()) );
	item->setText( 2, d->le_customRoster->text() );
}

void OptionsTabIconsetRoster::isCustom_add()
{
	IconsetRosterUI *d = (IconsetRosterUI *)w;

	QString def;
	const Iconset *iconset = d->iss_defRoster->iconset();
	if ( is ) {
		QFileInfo fi( iconset->fileName() );
		def = fi.fileName();
	}
	else
		qWarning("OptionsTabIconsetRoster::isCustom_add(): 'def' is null!");

	QListViewItem *item = new QListViewItem(d->lv_customRoster, d->lv_customRoster->lastItem());
	const Iconset *i = is->roster[def];
	if ( i ) {
		item->setText(1, i->name());

		QFileInfo fi(i->fileName());
		item->setText(3, fi.fileName());
	}

	d->lv_customRoster->setSelected(item, true);
	emit dataChanged();

	d->le_customRoster->setFocus();
}

void OptionsTabIconsetRoster::isCustom_delete()
{
	IconsetRosterUI *d = (IconsetRosterUI *)w;
	QListViewItem *item = d->lv_customRoster->selectedItem();
	if ( !item )
		return;

	delete item;
	isCustom_selectionChanged(0);
	emit dataChanged();
}

QString OptionsTabIconsetRoster::clipCustomText(QString s)
{
	if ( s.length() > 10 ) {
		s = s.left(9);
		s += "...";
	}

	return s;
}

void OptionsTabIconsetRoster::cancelThread()
{
	if ( thread ) {
		threadCancelled.lock();
		thread->cancelled = true;
		threadCancelled.unlock();

		thread = 0;
	}
}
