/***************************************************************************
 *   Copyright (C) 2005 by Nicolas Ternisien                               *
 *   nicolas.ternisien@gmail.com                                           *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   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.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
 ***************************************************************************/

//TQt includes
#include <tqpainter.h>
#include <tqlayout.h>
#include <tqhbox.h>
#include <tqlabel.h>
#include <tqstring.h>
#include <tqwhatsthis.h>
#include <tqtooltip.h>

#include <tqlistview.h>

#include <tqpixmap.h>

//KDE includes
#include <kurl.h>

#include <ktrader.h>
#include <klibloader.h>
#include <kmessagebox.h>
#include <krun.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kdebug.h>
//For compatibility with old versions of KDE
#include <kdeversion.h>

//Project includes
#include "view.h"

#include "logListItem.h"
#include "logLine.h"
#include "viewToolTip.h"

#include "ksystemlogConfig.h"
#include "ksystemlog.h"


View::View(TQWidget *parent) :
	DCOPObject("KSystemLogInterface"),
	TQWidget(parent),
	logManager(NULL),
	table(NULL),
	columns(NULL),
	firstLoad(true)
	{

	// setup our layout manager to automatically add our widgets
	TQVBoxLayout* topLayout = new TQVBoxLayout(this);
	topLayout->setAutoAdd(true);
	
	
#if defined(KDE_MAKE_VERSION) && KDE_VERSION >= KDE_MAKE_VERSION(3,3,0)
	filterBar=new TQHBox(this);
	filterBar->setSpacing(5);
	filterBar->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Fixed ) );
	
	
	clearSearch=new KToolBarButton( TQApplication::reverseLayout() ? "clear_left" : "locationbar_erase", 0, filterBar);
	clearSearch->setText(i18n("Clear the filter"));
	
	TQWhatsThis::add(clearSearch, i18n("This button clears the filter in one click."));
	TQToolTip::add(clearSearch, i18n("Clear the filter"));
	
	
	TQLabel* label=new TQLabel(i18n("Filter:"), filterBar);
	
	search=new LogLineFilter(filterBar, (KListView*)NULL);
	label->setBuddy(search);
	
	TQWhatsThis::add(search, i18n("Allows you to select only list items that match the content of this text."));
	TQToolTip::add(search, i18n("Type your item filter here"));
	
	label=new TQLabel(i18n("Column:"), filterBar);
	
	this->initSearchFilter(filterBar);
	
	label->setBuddy(searchFilter);
	
	toggleFilterBar();
#endif
	
	
	this->initLogList();


#if defined(KDE_MAKE_VERSION) && KDE_VERSION >= KDE_MAKE_VERSION(3,3,0)
	//We initialize the table after, after the initialization of the table
	search->setListView(table);
	
	//Connect the pressed signal of the clear button to the clear slot of "clear"
	connect(clearSearch, TQT_SIGNAL(pressed()), search, TQT_SLOT(clear()));
#endif

}


View::~View() {
#if defined(KDE_MAKE_VERSION) && (KDE_VERSION >= KDE_MAKE_VERSION(3,3,0))
	delete clearSearch;
	
	delete search;
		
	delete searchFilter;

	delete filterBar;
#endif
	
	kdDebug() << "Destroying View" << endl;
}

void View::saveConfig() {
	kdDebug() << "Saving View Layout..." << endl;
	
	KSystemLogConfig* configXT=KSystemLogConfig::self();
	KConfig* config=configXT->config();
	TQString group="List";
	group.append(logManager->getIndex());
	
	table->saveLayout(config, group);

}

void View::setLogManager(LogManager* manager) {
	logManager=manager;
}

//TODO Deprecate this method as soon as possible
void View::openURL(TQString url) {
	kdDebug() << "DCOP Interface : " << url << endl;
}

bool View::isTooltipEnabled() {
	return(logManager->isTooltipEnabled());
}

void View::toggleFilterBar() {
#if defined(KDE_MAKE_VERSION) && KDE_VERSION >= KDE_MAKE_VERSION(3,3,0)
	//The newly created bar is only displayed if the config file allow it
	if (KSystemLogConfig::toggleFilterBar()==true)
		filterBar->show();
	else
		filterBar->hide();
#endif
}



/**
 * Delete the "count" first items
 */
void View::deleteOldItems(int count) {
	TQListViewItem* item;
	for(int i=0; i<count; i++) {
		item=table->lastItem();
		table->takeItem(item);
	}
}

int View::getItemCount() {

	int count=0;
	
	if (logManager->getGroupBy()==NO_GROUP_BY) {
		count=table->childCount();
	}
	else {
		TQPtrList<TQListViewItem> lst;
		TQListViewItemIterator it(table);
		while (it.current()!=NULL) {
			count+=it.current()->childCount();
			++it;
		}
	}
		
	return(count);
}



void View::setColumns(LogViewColumns* list) {
	kdDebug() << "Change columns" << endl;
	
	columns=list;

	updateList();

	//TODO Maybe with the deleting of the config group, this boolean is useless
	if (firstLoad==true) {
		KSystemLogConfig* configXT=KSystemLogConfig::self();
		TQString group="List";
		group.append(logManager->getIndex());
		
		//We first restore the layout from the config
		table->restoreLayout(configXT->config(), group);
		
		//Then we delete it from config, to avoid reloading problem
		configXT->config()->deleteGroup(group);
		
		firstLoad=false;
	}
	
	updateSearchFilter();
	
}

void View::setFirstItemVisible() {
	table->ensureItemVisible(table->firstChild());
}

void View::setLastItemVisible() {
	table->ensureItemVisible(table->lastItem());
}

void View::setFirstItemSelected() {
	table->setCurrentItem(table->firstChild());
	table->setSelected(table->firstChild(), true);
	table->ensureItemVisible(table->firstChild());
}

void View::setLastItemSelected() {
	table->setCurrentItem(table->lastItem());
	table->setSelected(table->lastItem(), true);
	table->ensureItemVisible(table->lastItem());
}

void View::updateSearchFilter() {
#if defined(KDE_MAKE_VERSION) && KDE_VERSION >= KDE_MAKE_VERSION(3,3,0)
	//We first delete all items
	int count=searchFilter->count() - 1;
	while (count>=0) {
		searchFilter->removeItem(count);
		count--;
	}
	
	//Then we insert the default items
	searchFilter->insertItem(i18n("All"));
	
	LogViewColumns::Iterator it = columns->begin();
	
	LogViewColumn* column;
	while(it!=columns->end()) {
		column=*it;
		if (column->isFiltred==true)
			searchFilter->insertItem(column->columnName);
		it++;
	}

	searchFilter->setCurrentItem(0);
#endif
}


void View::updateList() {
	
	//First, delete all current columns
	int count=table->columns() - 1;
	while (count>=0) {
		table->removeColumn(count);
		count--;
	}
	

	LogViewColumns::Iterator it = columns->begin();
	
	LogViewColumn* column;
	//Add all columns of the columns list object
	while(it!=columns->end()) {
		column=*it;
		table->addColumn(column->columnName, -1);
		it++;
	}
	
	//Adjust them to the size of the current maximum item
	int i=0;
	while (i<table->columns()) {
		table->adjustColumn(i);
		i++;
	}
	
	//TODO Try to reduce size of first column with a 
}

void View::initLogList() {
	
	table=new KListView(this, "log_list");

	TQWhatsThis::add(table, i18n("<qt><p>This is the main view of KSystemLog. It displays the last lines of the selected log. Please see the documentation to discovers the meaning of each icons and existing log.</p><p>Log lines in <b>bold</b> are the last added to the list.</p></qt>"));
	
	table->addColumn("Message");
	
	table->setSorting(0, true);

	//table->setRootIsDecorated(true);
	table->setShowSortIndicator(true);
	table->setAllColumnsShowFocus(true);
	
	//This method is not implemented for the moment by KListView class
	table->setAutoOpen(false);
	
	//This is buggy but it's not my fault (I hope :-)
	table->setFullWidth(true);

	//TODO Find a color from TQColorGroup
	TQColor* alternate=new TQColor(246,246,255);
	table->setAlternateBackground(*alternate);
	
	table->setSelectionModeExt(KListView::Extended);
	
	toolTip=new ViewToolTip(this->getLogList()->viewport(), this);

}


LogListItem* View::getFirstSelectedItem() {
	TQListViewItemIterator it(table, TQListViewItemIterator::Selected);
	
	//Returns the first selected item or NULL is there is no item selected
	return(static_cast<LogListItem*> (it.current()));
}

LogListItem* View::getLastSelectedItem() {
	TQListViewItemIterator it(table, TQListViewItemIterator::Selected);
	
	TQListViewItem* item=NULL;
	while (it.current()) {
		item=it.current();
		
		it++;
	}
	
	//Returns the last selected item or NULL is there is no item selected
	return(static_cast<LogListItem*> (item));
}


void View::setSortEnabled(bool enabled) {
	if (enabled==true)
		table->setSorting(table->columns()+1);
	else
		table->setSorting(-1);
}

void View::initSearchFilter(TQWidget* filterBox) {
#if defined(KDE_MAKE_VERSION) && KDE_VERSION >= KDE_MAKE_VERSION(3,3,0)
	searchFilter=new TQComboBox(filterBox);
		
	TQWhatsThis::add(searchFilter, i18n("<qt>Allows you to apply the item filter only on the specified column here. \"<i>All</i>\" column means no specific filter.</qt>"));
	TQToolTip::add(searchFilter, i18n("Choose the filtered column here"));
	
	searchFilter->insertItem(i18n("All"));
	
	//TODO 0 is not a very good value... Improve that. and of course, try to find a better solution
	searchFilter->setMinimumSize(70, 0);

	connect(searchFilter, TQT_SIGNAL(activated(int)), search, TQT_SLOT(setFocus()));
	connect(searchFilter, TQT_SIGNAL(activated(int)), this, TQT_SLOT(changeColumnFilter(int)));
	connect(searchFilter, TQT_SIGNAL(activated(int)), search, TQT_SLOT(updateSearch()));
#endif

}


void View::addElement(TQStringList* entries, TQPixmap* icon) {
	TQStringList::Iterator it = entries->begin();
	
	KListViewItem* item=new KListViewItem(table, *(it++), *(it++), *(it++), *(it++), *(it++));
	if (icon!=NULL)
		item->setPixmap(0, *icon);
	
}

void View::addElementAtEnd(TQStringList* entries, TQPixmap* icon) {
	TQStringList::Iterator it = entries->begin();
	
	KListViewItem* item=new KListViewItem(table, table->lastItem(), *(it++), *(it++), *(it++), *(it++), *(it++));
	if (icon!=NULL)
		item->setPixmap(0, *icon);
}

KListView* View::getLogList() {
	return(table);
}


void View::changeColumnFilter(int column) {
#if defined(KDE_MAKE_VERSION) && KDE_VERSION >= KDE_MAKE_VERSION(3,3,0)
	TQValueList<int> filterColumns;
	
	//The user select all columns
	if (column==0) {
		search->setSearchColumns(filterColumns);
	}
	else {
		TQString columnName=searchFilter->currentText();
		
		LogViewColumns::Iterator it;
		LogViewColumn* column;
		int position=0;
		for(it=columns->begin(); it!=columns->end(); it++) {
			column=*it;
			if (column->columnName==columnName)
				break;
				
			position++;
		}
		
		filterColumns.append(position);

		search->setSearchColumns(filterColumns);
	}
	
	//search->updateSearch();
#endif
}



void View::print(TQPainter* /*p*/, int /*height*/, int /*width*/) {
	//Print log files here
}

void View::slotOnURL(const TQString& url) {
	emit changeStatusbar(url);
}

void View::slotSetTitle(const TQString& title) {
	emit changeCaption(title);
}

void View::clearLogList( ) {
	table->clear();
}



#include "view.moc"
