/*
    KAppfinder, the KDE application finder

	Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>

	Based on code written by Matthias Hoelzer-Kluepfel <hoelzer@kde.org>

    This program is free software; you can redistribute it and/or
    modify it under the terms of version 2 of the GNU General Public
    License as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

	$Id: toplevel.cpp,v 1.8.2.4 2003/06/29 21:53:07 deller Exp $
*/

#include <kapplication.h>
#include <kbuttonbox.h>
#include <kdebug.h>
#include <kdesktopfile.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kprogress.h>
#include <kservicegroup.h>
#include <kstandarddirs.h>
#include <kstartupinfo.h>

#include <qaccel.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qpushbutton.h>
#include <qdir.h>
#include <qregexp.h>

#include "toplevel.h"

TopLevel::TopLevel(QString _destDir, QWidget *parent, const char *name)
	: KDialog(parent, name, true)
{
	setCaption(i18n("KAppfinder"));
	QVBoxLayout* layout = new QVBoxLayout(this, marginHint());

	QLabel* l = new QLabel(i18n("The application finder looks for legacy "
				"applications on your system and adds "
				"them to the KDE menu system. "
				"Click 'Scan' to begin, select the desired applications and then click 'Apply'."), this);
	l->setAlignment(AlignAuto | WordBreak);
	layout->addWidget(l);

	layout->addSpacing(5);

	listview = new QListView(this, "ListView");
	listview->addColumn(i18n("Applications"));
	listview->addColumn(i18n("Descriptions"));
	listview->addColumn(i18n("Commands"));
	listview->setMinimumSize(300, 300);
	listview->setRootIsDecorated(true);
	layout->addWidget(listview);

	progress = new KProgress(this);
	layout->addWidget(progress);

	summary = new QLabel(i18n("Summary:"), this);
	layout->addWidget(summary);

	KButtonBox* bbox = new KButtonBox(this);
	bbox->addButton(i18n("&Cancel"), kapp, SLOT(quit()));
	bbox->addStretch(5);
	selectButton = bbox->addButton(i18n("S&elect All"), this, SLOT(slotSelectAll()));
	selectButton->setEnabled(false);
	unselectButton = bbox->addButton(i18n("&Unselect All"), this, SLOT(slotUnselectAll()));
	unselectButton->setEnabled(false);
	bbox->addStretch(5);
	applyButton = bbox->addButton(i18n("&Apply"), this, SLOT(slotCreate()));
	applyButton->setEnabled(false);
	scanButton = bbox->addButton(i18n("&Scan"), this, SLOT(slotScan()));
	bbox->layout();

	layout->addWidget(bbox);

	connect(kapp, SIGNAL(lastWindowClosed()), kapp, SLOT(quit()));

	appCache.setAutoDelete(true);

	adjustSize();

        destDir=_destDir.replace( QRegExp("^~/"), QDir::homeDirPath()+"/" );
	
	KStartupInfo::appStarted();

	QAccel *accel = new QAccel( this );
	accel->connectItem( accel->insertItem( Key_Q + CTRL ), kapp, SLOT( quit() ) );
}


TopLevel::~TopLevel()
{
	appCache.clear();
}

QListViewItem* TopLevel::addGroupItem(QListViewItem *parent, const QString& relPath, const QString& name)
{
	KServiceGroup::Ptr root = KServiceGroup::group(relPath);
	if( !root )
			return 0L;
	KServiceGroup::List list = root->entries();

	
	for (KServiceGroup::List::ConstIterator it = list.begin(); it != list.end(); ++it)
	{
		KSycocaEntry* p = (*it);
		if (p->isType(KST_KServiceGroup))
		{
			KServiceGroup* serviceGroup = static_cast<KServiceGroup*>(p);
			if (QString("%1%2/").arg(relPath).arg(name) == serviceGroup->relPath())
			{
				QListViewItem* retval;
				if (parent)
					retval = parent->firstChild();
				else
					retval = listview->firstChild();

				while (retval)
				{
					if (retval->text(0) == serviceGroup->caption())
						return retval;
					
					retval = retval->nextSibling();
				}

				QListViewItem* item;
				if (parent)
					item = new QListViewItem(parent, serviceGroup->caption());
				else
					item = new QListViewItem(listview, serviceGroup->caption());

				item->setPixmap(0, SmallIcon(serviceGroup->icon()));
				item->setOpen(true);
				return item;
			}
		}
	}

	return 0;
}

void TopLevel::slotScan()
{
	KIconLoader* loader = KGlobal::iconLoader();

	templates = KGlobal::dirs()->findAllResources("data", "kappfinder/apps/*.desktop", true);

	appCache.clear();

	found = 0;
	int count = templates.count();

	scanButton->setEnabled(false);
	progress->setRange(0, count);
	progress->setValue(0);

	listview->clear();

	for (QStringList::Iterator it = templates.begin(); it != templates.end(); ++it)
	{
		KDesktopFile desktop(*it, true);

		// eye candy
		progress->setValue(progress->value() + 1);

		// copy over the desktop file, if exists
		if (scanDesktopFile(appCache, *it, destDir))
		{
			QString relPath = *it;
			int pos = relPath.find("kappfinder/apps/");
			relPath = relPath.mid(pos+strlen("kappfinder/apps/"));
			relPath = relPath.left(relPath.findRev('/') + 1);
			QStringList dirList = QStringList::split('/', relPath);

			QListViewItem *dirItem = 0;
			QString tmpRelPath = QString::null;
			for (QStringList::Iterator tmpIt = dirList.begin(); tmpIt != dirList.end(); ++tmpIt)
			{
				dirItem = addGroupItem(dirItem, tmpRelPath, *tmpIt);
				tmpRelPath += *tmpIt + '/';
			}

			found++;

			QCheckListItem* item;
			if (dirItem)
				item = new QCheckListItem(dirItem, desktop.readName(), QCheckListItem::CheckBox);
			else
				item = new QCheckListItem(listview, desktop.readName(), QCheckListItem::CheckBox);

			item->setPixmap(0, loader->loadIcon(desktop.readIcon(), KIcon::Small));
			item->setText(1, desktop.readEntry("GenericName"));
			item->setText(2, desktop.readPathEntry("Exec"));
			if (desktop.readBoolEntry("X-StandardInstall"))
				item->setOn(true);

			AppLnkCache* cache = appCache.last();
			if (cache)
				cache->item = item;
		}

		// update summary
		QString sum(i18n("Summary: found %n application","Summary: found %n applications",found));
		summary->setText(sum);
	}

	// stop scanning
	progress->setValue(0);
	scanButton->setEnabled(true);

	if (found > 0) {
		applyButton->setEnabled(true);
		selectButton->setEnabled(true);
		unselectButton->setEnabled(true);
	}
}

void TopLevel::slotSelectAll()
{
	AppLnkCache* cache;
	for (cache = appCache.first(); cache; cache = appCache.next()) {
	  cache->item->setOn(true);
	}
}

void TopLevel::slotUnselectAll()
{
	AppLnkCache* cache;
	for (cache = appCache.first(); cache; cache = appCache.next()) {
	  cache->item->setOn(false);
	}
}

void TopLevel::slotCreate()
{
	// copy template files
	added = 0;
	createDesktopFiles(appCache, added);

	// decorate directories
	decorateDirs(destDir);

	QString message(i18n("%n application was added to the KDE menu system.",
	                     "%n applications were added to the KDE menu system.",added));
	KMessageBox::information(this,message,QString::null, "ShowInformation");
}
#include "toplevel.moc"
