/*
 * This file is part of QTGZManager, an open-source GUI for Slackware pkgtools.
 * Copyright (C) 2006  Alexandre Albuquerque Arnt
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact e-mail : Alexandre Albuquerque Arnt <aaarnt@gmail.com>
 * Program URL   : http://jtgzmanager.sf.net
 *
 */
#include <iostream>
#include "mainwindowimpl.h"
#include "package.h"
#include "tvpackagesitemdelegate.h"
#include <QtGui>
#include <QFutureWatcher>

using namespace QtConcurrent;

MainWindowImpl* MainWindowImpl::returnMainWindow(){
	static MainWindowImpl *w=0;
	if (w != 0) return w;
	
	foreach (QWidget *widget, QApplication::topLevelWidgets()) {
		if (widget->objectName() == "MainWindow") w = (MainWindowImpl*) widget;
	}  
	return w;
}

MainWindowImpl::MainWindowImpl( QWidget * parent, Qt::WFlags f) 
:	QMainWindow(parent, f), 
m_PackagesInDirFont(11),
m_InstalledPackagesFont(11),
m_DirectoryFont(10),
m_TodoFont(10),
m_PkgListFont(10),
APPLICATION_NAME("QTGZManager - Beta4"),
LABEL_LISTVIEW_PACKAGES(tr("0 Packages in Directory")),
TODO_INSTALL(tr("To be installed")), 
TODO_REMOVE(tr("To be removed")), 
TODO_DOWNGRADE(tr("To be downgraded")),
TODO_UPGRADE(tr("To be upgraded")), 
TODO_REINSTALL(tr("To be reinstalled")),
iconInternalError(QIcon(":/resources/images/internalerror.png")),
iconInferior(QIcon(":/resources/images/inferiorversion_red.png")),
iconSuperior(QIcon(":/resources/images/superiorversion.png")),
iconOtherVersion(QIcon(":/resources/images/agent.png")),
iconInstalled(QIcon(":/resources/images/installed.png")),
iconNotInstalled(QIcon(":/resources/images/notinstalled.png")),	
iconFolder(QIcon(":/resources/images/folder.png")),
iconBinary(QIcon(":/resources/images/binary.png")),
iconFrozen(QIcon(":/resources/images/tgz_frozen.png")),
iconUnFrozen(QIcon(":/resources/images/tgz3.png")),
iconRPM(QIcon(":/resources/images/rpm.png"))
{
	m_fw = new QFutureWatcher<QStringList>(this);
	QFile::remove(TEMP_ACTIONS_FILE);
	m_reallyWannaClose = false;
	frozenPkgList = FrozenPkgListSingleton::instance();
	m_clickedTab = -1;  
	m_PackageListOrderedCol = 1; m_InstalledPackageListOrderedCol = 1;
	m_PackageListSortOrder = Qt::AscendingOrder; m_InstalledPackageListSortOrder = Qt::AscendingOrder;
	findDialog = 0;
	setupUi( this );	  
	setWindowTitle(APPLICATION_NAME);
	dockPackages->setWindowTitle(LABEL_LISTVIEW_PACKAGES);
	menubar->setVisible( false ); //Doesn't this menubar thing seem useless ???
	QIcon icon(":/resources/images/QTGZManager.png"); //QTGZManager.png");
	setWindowIcon(icon);    
	psw = new QFileSystemWatcher(QStringList() << PACKAGES_DIR, this);
	fsw.addPath( QDir::homePath() );

	initializeActions();
	initializeToolBar();
	initializeDirTreeView();
	initializePackageListView();
	initializeInstalledPackagesListView();
	initializeTodoTreeView();
	showPackagesInDirectory();

	twTODO->setUsesScrollButtons(true);
	twTODO->setElideMode(Qt::ElideNone);
	m_tabBar = twTODO->findChild<QTabBar*>();
	m_tabBar->installEventFilter(this);
	btnCloseTab = new QToolButton( twTODO );
	btnCloseTab->setAutoRaise( true );
	btnCloseTab->setIcon(QIcon(":/resources/images/close.png"));
	twTODO->setCornerWidget( btnCloseTab );
	btnCloseTab->setToolTip(tr("Close tab"));
	btnCloseTab->setEnabled( false );
	btnCloseTab->show();

	lblStatus = new QLabel( this );
	lblStatus->setFrameStyle( QFrame::NoFrame );
	statusbar = new QSimpleStatusBar( this );
	setStatusBar( statusbar );
	statusBar()->addPermanentWidget( lblStatus, true );
	showMaximized();
	savedGeometry = this->saveGeometry();	

	systemTrayIcon = new QSystemTrayIcon( icon, this );
	systemTrayIcon->setToolTip( APPLICATION_NAME );
	systemTrayIcon->show();
	systemTrayIconMenu = new QMenu( this );
	actionAbout = new QAction( this );
	actionAbout->setIcon(QIcon((":/resources/images/QTGZManager.png")));
	actionAbout->setText( tr("About..."));
	systemTrayIconMenu->addAction( actionAbout );
	systemTrayIconMenu->addAction( actionExit );
	systemTrayIcon->setContextMenu( systemTrayIconMenu );

	//Connect all signals with their slots
	connect(tvDir, SIGNAL(clicked(const QModelIndex)), this, SLOT(changeDir()));
	connect(tvDir, SIGNAL(activated(const QModelIndex)), tvDir, SIGNAL(clicked(const QModelIndex)));
	connect(tvDir, SIGNAL(clicked(const QModelIndex)), this, SLOT(showPackagesInDirectory()));	
	connect( tvPackage->header(), SIGNAL( sectionClicked ( int )), 
			this, SLOT( headerViewPackageList_click( int ) ) );
	connect( tvInstalledPackages->header(), SIGNAL( sectionClicked ( int )), 
			this, SLOT( headerViewInstalledPackageList_click( int ) ) );
	//connect(tvPackage, SIGNAL(activated(const QModelIndex)), tvPackage, SIGNAL(clicked(const QModelIndex)));
	connect(tvPackage, SIGNAL(clicked(const QModelIndex)), this, SLOT(selectInstalledPackage()));
	//connect(tvPackage, SIGNAL(pressed(const QModelIndex)), tvPackage, SIGNAL(clicked(const QModelIndex)));
	connect(tvDir, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(execContextMenuDirectories(QPoint)));
	connect(tvTODO, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(execContextMenutvTODO(QPoint)));
	connect(tvPackage, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(execContextMenuPackages(QPoint)));
	connect(tvInstalledPackages, SIGNAL(customContextMenuRequested(QPoint)), 
		this, SLOT(execContextMenuInstalledPackages(QPoint)));
	connect ( psw, SIGNAL(directoryChanged ( const QString &)), 
		this, SLOT(fileSystemWatcher_packageDirectoryChanged ( const QString &) ));
	connect ( &fsw, SIGNAL(directoryChanged ( const QString &)), 
		this, SLOT(fileSystemWatcher_directoryChanged ( const QString &) ));
	connect(modelTodo, SIGNAL(rowsInserted ( const QModelIndex , int, int )), 
		this, SLOT(verifyStateTODO ( const QModelIndex , int, int )));
	connect(modelTodo, SIGNAL(rowsRemoved ( const QModelIndex , int, int )), 
		this, SLOT(verifyStateTODO ( const QModelIndex , int, int )));
	connect( btnCloseTab, SIGNAL(clicked()), this, SLOT(closeCurrentTab()) );
	connect( twTODO, SIGNAL(currentChanged(int)), this, SLOT(enableCloseTabButton(int)) );
	connect(actionAbout, SIGNAL(triggered()), this, SLOT(aboutQTGZManager()));
	connect ( systemTrayIcon , SIGNAL( activated( QSystemTrayIcon::ActivationReason ) ), 
		this, SLOT( execSystemTrayActivated ( QSystemTrayIcon::ActivationReason ) ) );

	m_verticalSplit = splitter1->saveState();
	m_horizontalSplit = splitter_21->saveState();
	m_timer = startTimer(1);
}

MainWindowImpl::~MainWindowImpl(){
	delete modelDir;
	delete modelPackage;
	delete modelInstalledPackages;
	delete install;
	delete remove;
	delete downgrade;
	delete upgrade;
	delete reinstall;
	delete modelTodo;
}

void MainWindowImpl::timerEvent(QTimerEvent*){
	tvDir->scrollTo(tvDir->currentIndex(), QAbstractItemView::PositionAtCenter);
	killTimer(m_timer);
}

void MainWindowImpl::changeDir(){
	leDir->setText(modelDir->filePath(tvDir->currentIndex()));
}

bool MainWindowImpl::hasTheExecutable( QString exeName ){
	QStringList slParam;
	QProcess* proc = new QProcess(this);  
	slParam << exeName;
	proc->start("whereis", slParam);
	proc->waitForFinished();
	QString out = proc->readAllStandardOutput();

	delete proc;
	if (out.count(exeName) == 1) return false;
	else return true;
}

bool MainWindowImpl::eventFilter(QObject*, QEvent *event){
	if (event->type() == QEvent::MouseButtonPress ){
		QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
		for (int i=0; i<m_tabBar->count(); i++){
			if ( m_tabBar-> tabRect(i).contains( mouseEvent->pos() ) ){
				m_clickedTab = i;
				break;
			}
		}
		if  ((mouseEvent != 0) && ( mouseEvent->button() == Qt::RightButton ) && 
				(m_clickedTab != 0) && (m_clickedTab != 1)) {
			QMenu *menu = new QMenu(this);
			connect(menu->addAction(QIcon(":/resources/images/close.png"), tr("Close tab")), SIGNAL(triggered()), this, SLOT(closeClickedTab()) );
			if (m_tabBar->count() > 3) 
				connect(menu->addAction(QIcon(":/resources/images/close.png"), tr("Close all tabs")), SIGNAL(triggered()), this, SLOT(closeAllTabs()) );
			menu->exec(mouseEvent->globalPos());
			m_clickedTab = -1;
		}
	}
	return false;	
}

void MainWindowImpl::fileSystemWatcher_directoryChanged ( const QString& ){
	showPackagesInDirectory();
}

void MainWindowImpl::fileSystemWatcher_packageDirectoryChanged( const QString& ){
	refreshInstalledPackageTreeView(); showPackagesInDirectory();
}

void MainWindowImpl::headerViewPackageList_click( int  col ){
	m_PackageListOrderedCol = col;
	m_PackageListSortOrder = tvPackage->header()->sortIndicatorOrder();
}

void MainWindowImpl::headerViewInstalledPackageList_click( int  col ){
	m_InstalledPackageListOrderedCol = col;
	m_InstalledPackageListSortOrder = tvInstalledPackages->header()->sortIndicatorOrder();
}

void MainWindowImpl::enableCloseTabButton( int ){
	if (twTODO->count() <= 2){
		btnCloseTab->setEnabled( false );
		twTODO->removeAction( actionCloseTab );
		lblStatus->setText("");
	}
	else if (twTODO->count() > 2){
		if (twTODO->currentIndex() > 1) btnCloseTab->setEnabled( true );
		else btnCloseTab->setEnabled( false );

		if (twTODO->count() >= 3){
			if ((twTODO->count() > 3) && (twTODO->currentWidget()->findChild<QAction*>("actionCloseAllTabs") == 0))
				twTODO->currentWidget()->addAction( actionCloseAllTabs );	

			//we verify if there is a tvPkgFileList active
			QTreeView *t = twTODO->currentWidget()->findChild<QTreeView*>("tvPkgFileList");
			if ( t != 0){ 
				t->setFocus();
				showFullPathOfObject( t->currentIndex() );
			}
			else{ 
				lblStatus->setText(""); 
			}
		}
		else twTODO->currentWidget()->removeAction( actionCloseAllTabs );
	}
}

void MainWindowImpl::verifyStateTODO( const QModelIndex , int, int ){
	if (( modelTodo->rowCount(modelTodo->item(0, 0)->index()) != 0 ) || ( modelTodo->rowCount(modelTodo->item(1, 0)->index()) != 0 ) || 
			( modelTodo->rowCount(modelTodo->item(2, 0)->index()) != 0 ) || ( modelTodo->rowCount(modelTodo->item(3, 0)->index()) != 0 ) || ( modelTodo->rowCount(modelTodo->item(4, 0)->index()) != 0 ) )
		actionExecuteActions->setEnabled( true );
	else actionExecuteActions->setEnabled( false );
}

void MainWindowImpl::insertInstallPackageAction(){		
	foreach(SelectedPackage sp, getSelectedPackage()){
		if ((modelTodo->findItems(sp.getCompleteFileName(), Qt::MatchRecursive).size()==0) 
			&& (Package::isValid(sp.getCompleteFileName())))
			install->appendRow(new QStandardItem(sp.getCompleteFileName()));				
	}

	if (!tvTODO->isExpanded(tvTODO->currentIndex())) tvTODO->expandAll();
	if (twTODO->currentIndex()!=0) twTODO->setCurrentIndex(0);
}

void MainWindowImpl::insertDowngradePackageAction(){		
	foreach(SelectedPackage sp, getSelectedPackage()){
		if ((modelTodo->findItems(sp.getCompleteFileName(), Qt::MatchRecursive).size()==0) 
			&& (Package::isValid(sp.getCompleteFileName())))
			downgrade->appendRow(new QStandardItem(sp.getCompleteFileName()));				
	}

	if (!tvTODO->isExpanded(tvTODO->currentIndex())) tvTODO->expandAll();
	if (twTODO->currentIndex()!=0) twTODO->setCurrentIndex(0);
}

void MainWindowImpl::insertRemovePackageAction(){		
	if (tvPackage->hasFocus()){
		foreach(SelectedPackage sp, getSelectedPackage()){  
			if (((modelTodo->findItems(sp.getCompleteFileName(), Qt::MatchRecursive).size()==0)) 
				&& (Package::isValid(sp.getCompleteFileName())))
				remove->appendRow(new QStandardItem(sp.getCompleteFileName()));
		}
	}
	else if (tvInstalledPackages->hasFocus()){
		foreach(SelectedPackage sp, getSelectedInstalledPackage()){      
			if ((modelTodo->findItems(sp.getCompleteFileName(), Qt::MatchRecursive).size()==0)) 
				remove->appendRow(new QStandardItem(sp.getCompleteFileName()));    
		} 
	}

	if (!tvTODO->isExpanded(tvTODO->currentIndex())) tvTODO->expandAll();
	if (twTODO->currentIndex()!=0) twTODO->setCurrentIndex(0);
}

void MainWindowImpl::insertUpgradePackageAction(){		
	foreach(SelectedPackage sp, getSelectedPackage()){
		if ((modelTodo->findItems(sp.getCompleteFileName(), Qt::MatchRecursive).size()==0) 
				&& (Package::isValid(sp.getCompleteFileName())))
			upgrade->appendRow(new QStandardItem(sp.getCompleteFileName()));		
	}

	if (!tvTODO->isExpanded(tvTODO->currentIndex())) tvTODO->expandAll();
	if (twTODO->currentIndex()!=0) twTODO->setCurrentIndex(0);
}

void MainWindowImpl::insertReinstallPackageAction(){		
	foreach(SelectedPackage sp, getSelectedPackage()){
		if ((modelTodo->findItems(sp.getCompleteFileName(), Qt::MatchRecursive).size()==0) 
				&& (Package::isValid(sp.getCompleteFileName())))
			reinstall->appendRow(new QStandardItem(sp.getCompleteFileName()));				
	}

	if (!tvTODO->isExpanded(tvTODO->currentIndex())) tvTODO->expandAll();
	if (twTODO->currentIndex()!=0) twTODO->setCurrentIndex(0);
}

void MainWindowImpl::execContextMenuDirectories(QPoint point){	
	showPackagesInDirectory();
	QModelIndex mi = tvDir->currentIndex();

	QMenu menu(this);            

	menu.addAction(actionOpenDirectory);
	menu.addAction(actionOpenTerminal);
	menu.addAction(actionCreate_Directory);
	menu.addAction(actionRemove_Directory);        		        		       		        		

	QPoint pt2 = tvDir->mapToGlobal(point);
	pt2.setY(pt2.y() + tvDir->header()->height());
	menu.exec(pt2);        	        	
}

void MainWindowImpl::diffAgainstEachOther(){
	tvPackage->repaint(tvPackage->rect());
	QCoreApplication::processEvents();	

	CPUIntensiveComputing ri;
	SelectedPackage pkg1 = getSelectedPackage()[0];
	SelectedPackage pkg2 = getSelectedPackage()[1];

	for (int c=2; c<twTODO->count(); c++)
		if (twTODO->tabText(c) == ( pkg1.getFileName() + " DIFF")){
			twTODO->setCurrentIndex ( c );			
			return;
		} 

	QStringList sl = Package::getContents(pkg1.getCompleteFileName());
	QCoreApplication::processEvents();	
	QStringList sl2 = Package::getContents(pkg2.getCompleteFileName());
	QCoreApplication::processEvents();	

	sl.sort();
	sl2.sort();
	QFile fPkg("/tmp/tempPkg");
	QFile fIPkg("/tmp/tempIPkg");

	fPkg.open(QIODevice::ReadWrite | QIODevice::Text);
	fIPkg.open(QIODevice::ReadWrite | QIODevice::Text);
	QTextStream tsp(&fPkg);
	QTextStream tsip(&fIPkg);

	foreach(QString s, sl) tsp << s << endl; 
	foreach(QString s, sl2) tsip << s << endl;

	QStringList slParam;
	QProcess proc(this);  

	slParam << "--suppress-common-lines";
	slParam << fPkg.fileName();
	slParam << fIPkg.fileName();

	proc.start("diff", slParam);
	proc.waitForStarted();
	proc.waitForFinished();

	QString out = proc.readAllStandardOutput();
	createTabPkgDiff(pkg1.getFileName(), pkg2.getFileName(), out);
	fPkg.close();
	fIPkg.close();
	fPkg.remove();
	fIPkg.remove();
}

void MainWindowImpl::diffAgainstInstalled(){
	tvPackage->repaint(tvPackage->rect());
	QCoreApplication::processEvents();	
	SelectedPackage pkg = getSelectedPackage()[0];

	for (int c=2; c<twTODO->count(); c++)
		if (twTODO->tabText(c) == ( pkg.getFileName() + " DIFF")){
			twTODO->setCurrentIndex ( c );			
			return;
		} 

	Package p;
	QDir d(modelDir->filePath(tvDir->currentIndex())); 				
	d.setFilter(QDir::Files);
	p.setTargetDir(d.absolutePath());
	Result res = p.getStatus(pkg.getFileName());	

	QStringList sl = Package::getContents(PACKAGES_DIR + QDir::separator() + res.getInstalledPackage(), true);
	QCoreApplication::processEvents();	
	QStringList sl2 = Package::getContents(pkg.getCompleteFileName());
	QCoreApplication::processEvents();	

	if ( sl2.isEmpty() ){
		QMessageBox::critical(this, tr("Package %1").arg(pkg.getFileName()), tr("This package seems corrupted!"));		
		return;
	}

	CPUIntensiveComputing ri;
	sl.sort();
	sl2.sort();

	QFile fPkg("/tmp/tempPkg");
	QFile fIPkg("/tmp/tempIPkg");

	fPkg.open(QIODevice::ReadWrite | QIODevice::Text);
	fIPkg.open(QIODevice::ReadWrite | QIODevice::Text);
	QTextStream tsp(&fPkg);
	QTextStream tsip(&fIPkg);

	foreach(QString s, sl2) tsp << s << endl; 
	foreach(QString s, sl) tsip << s << endl;

	//Here, we execute the diff
	QStringList slParam;
	QProcess proc(this);  

	slParam << "--suppress-common-lines";
	slParam << fPkg.fileName();
	slParam << fIPkg.fileName();

	proc.start("diff", slParam);
	proc.waitForStarted();
	proc.waitForFinished();

	QString out = proc.readAllStandardOutput();
	createTabPkgDiff(pkg.getFileName(), res.getInstalledPackage(), out);

	fPkg.close();
	fIPkg.close();
	fPkg.remove();
	fIPkg.remove();
}

void MainWindowImpl::execContextMenuPackages(QPoint point){
	if ((modelPackage->rowCount()==0) || (tvPackage->selectionModel()->selectedRows().count()==0)) return;

	QMenu *menu = new QMenu(this);            
	QIcon icon;  

	//Which actions do we have to put? It depends on package status
	bool allSameType=true;
	bool allTGZ=false;	int tgzCount=0;
	bool allRPM=false; int rpmCount=0;
	int lastType=-9999;

	QList<SelectedPackage> lsp = getSelectedPackage();	

	foreach(SelectedPackage ami, lsp){  
		if ((lastType != -9999) && (lastType != ami.getIcon().serialNumber())) allSameType = false; 
		if (ami.getIcon().serialNumber() == iconRPM.serialNumber()) 
			rpmCount++;
		else tgzCount++;
		
		lastType = ami.getIcon().serialNumber(); 
	}

	if ( tgzCount == lsp.count() ) {
		allTGZ = true;
		allRPM = false;
	}
	else if ( rpmCount == lsp.count() ) {
		allTGZ = false;
		allRPM = true;
	}

	if (allTGZ){
		//First Info, so when the user mistakenly clicks in it, QTGZ does less processing.
		menu->addAction(actionPackageContent);

		if (tgzCount == 1){
			menu->addAction(actionPackageInfo); 	 
		}
	}
	else if ( (allRPM) && (hasTheExecutable("rpm2tgz")) ){
		menu->addAction(actionTransformRPMinTGZ);
	}

	//menu->addAction(actionOpenDirectory);

	if ( lsp.count() == 1 ){   
		//Here, we include the logic for package diff against installed
		icon = lsp[0].getIcon();
		if ( (icon.serialNumber() == iconSuperior.serialNumber()) || 
				(icon.serialNumber() == iconInferior.serialNumber()) ||
				(icon.serialNumber() == iconOtherVersion.serialNumber()) ) {				
			menu->addAction(actionDiffAgainstInstalled);
		}
	}
	else if (( lsp.count() == 2 ) && (allTGZ) ) {  
		//Here, we include the logic for package diff against each other
		if ( lsp[0].getFileName() != lsp[1].getFileName()){
			QString s1 = Package::getBaseName(lsp[0].getFileName());
			QString s2 = Package::getBaseName(lsp[1].getFileName());
			if (s1 == s2) menu->addAction(actionDiffAgainstEachOther);
		}
	}

	if ((allSameType) && (allTGZ) ) {
		icon = lsp[0].getIcon();
		if (icon.serialNumber() == iconInferior.serialNumber()) {
			menu->addAction(actionDelete_file);
			menu->addAction(actionDowngrade_package);        		        		
		}
		else if (icon.serialNumber() == iconSuperior.serialNumber()){
			menu->addAction(actionDelete_file);
			menu->addAction(actionUpgrade_package);        		        		       		        		
		}
		else if (icon.serialNumber() == iconOtherVersion.serialNumber()){
			menu->addAction(actionDelete_file);
			menu->addAction(actionUpgrade_package);        		        		       		        		
		}
		else if (icon.serialNumber() == iconInstalled.serialNumber()){
			menu->addAction(actionDelete_file);
			menu->addAction(actionReinstall_package);
			menu->addAction(actionRemove_package);        		        		       		        		       		
		}
		else if (icon.serialNumber() == iconNotInstalled.serialNumber()){
			menu->addAction(actionDelete_file);
			menu->addAction(actionInstall_package);        		        		       		        		       		
		}        	
		else if (icon.serialNumber() == iconInternalError.serialNumber()) {
			menu->addAction(actionDelete_file);        		   		
		}
		else if (icon.serialNumber() == iconFrozen.serialNumber()) {
			menu->addAction(actionDelete_file);        		   		
		}
	}
	else{
		menu->addAction(actionDelete_file);
	}	

	QPoint pt2 = tvPackage->mapToGlobal(point);
	pt2.setY(pt2.y() + tvPackage->header()->height());
	menu->exec(pt2);        	
}

void MainWindowImpl::execContextMenuInstalledPackages(QPoint point){
	if ((modelInstalledPackages->rowCount()==0) || (tvInstalledPackages->selectionModel()->selectedIndexes().count()==0)) return;

	QModelIndex mi = tvInstalledPackages->currentIndex();
	QMenu *menu = new QMenu(this);               	

	//Which actions do we have to put? It depends on package status
	menu->addAction(actionPackageContent);

	if ( tvInstalledPackages->selectionModel()->selectedIndexes().count() == 2){
		menu->addAction(actionInstalledPackageInfo);
	}

	bool allSameType = true;
	int lastType=-9999;

	foreach(QModelIndex item, tvInstalledPackages->selectionModel()->selectedIndexes()){
		if ( item.column() == PACKAGE_ICON ){    
			QModelIndex mi = proxyModelInstalledPackages->mapToSource(item);	
			if ((lastType != -9999) && (lastType != modelInstalledPackages->item( mi.row(), mi.column() )->icon().serialNumber())){ 
				allSameType = false; 
				break;
			}
			lastType = modelInstalledPackages->item( mi.row(), mi.column() )->icon().serialNumber();
		}
	}

	if ( allSameType == true ){
		if ( lastType == iconFrozen.serialNumber() ) menu->addAction(actionUnfreezePkg); 
		else {
			menu->addAction(actionFreezePkg);  	
			menu->addAction(actionRemove_package);
		}
	}	        		        		       		        		       		

	QPoint pt2 = tvInstalledPackages->mapToGlobal(point);
	pt2.setY(pt2.y() + tvInstalledPackages->header()->height());
	menu->exec(pt2);        	
}

void MainWindowImpl::transformTGZinLZM(){
	QFile ftemp(TEMP_ACTIONS_FILE);
	ftemp.open(QIODevice::ReadWrite|QIODevice::Text);
	ftemp.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner|
			QFile::ReadUser|QFile::WriteUser|QFile::ExeUser);
	QTextStream out(&ftemp);

	int tgzCount=0;
	QList<SelectedPackage> lsp = getSelectedPackage();	
	QStringList args;
	bool rootUser = (QDir::homePath() == "/root");

	if (!rootUser){
		args << "-d";
		args << "-t";
		args << "--noignorebutton";
		//args << "-c";
	}
	else args << "-c";

	foreach(SelectedPackage ami, lsp){  
		if (ami.getIcon().serialNumber() != iconRPM.serialNumber()) tgzCount++;
	}

	if ( tgzCount == lsp.count() ){
		foreach(SelectedPackage sp, lsp){  
			out << "make-lzm " << sp.getCompleteFileName() << "\n";
		}

		out.flush();
		ftemp.close();
		args << TEMP_ACTIONS_FILE;

		tgz2lzm = new QProcess(this);
		tgz2lzm->setWorkingDirectory( lsp[0].getPath() ); 

		connect(tgz2lzm, SIGNAL( started() ), this, SLOT( TGZ2LZMprocessStarted() ));
		connect(tgz2lzm, SIGNAL( readyReadStandardOutput() ), this, SLOT( TGZ2LZMprocessReadOutput()));
		connect(tgz2lzm, SIGNAL( finished ( int, QProcess::ExitStatus )),
				this, SLOT( TGZ2LZMprocessFinished(int, QProcess::ExitStatus) ));
		connect(tgz2lzm, SIGNAL( readyReadStandardError() ), this, SLOT( TGZ2LZMprocessRaisedError() ));

		if (!rootUser) tgz2lzm->start("kdesu", args);
		else tgz2lzm->start("/bin/sh", args);
	}
}

void MainWindowImpl::transformRPMinTGZ(){
	QFile ftemp(TEMP_ACTIONS_FILE);
	ftemp.open(QIODevice::ReadWrite|QIODevice::Text);
	ftemp.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner|
			QFile::ReadUser|QFile::WriteUser|QFile::ExeUser);
	QTextStream out(&ftemp);

	QList<SelectedPackage> lsp = getSelectedPackage();
	QStringList args;
	args << "-c";

	rpm2tgz = new QProcess(this);
	rpm2tgz->setWorkingDirectory( lsp[0].getPath() ); 

	foreach(SelectedPackage sp, lsp){
		out << "rpm2tgz " << sp.getCompleteFileName() << "\n";
	}

	out.flush();
	ftemp.close();
	args << TEMP_ACTIONS_FILE;

	connect(rpm2tgz, SIGNAL( started() ), this, SLOT( RPM2TGZprocessStarted() ));
	connect(rpm2tgz, SIGNAL( readyReadStandardOutput() ), this, SLOT( RPM2TGZprocessReadOutput() ));
	connect(rpm2tgz, SIGNAL( finished ( int, QProcess::ExitStatus )),
			this, SLOT( RPM2TGZprocessFinished(int, QProcess::ExitStatus) ));
	connect(rpm2tgz, SIGNAL( readyReadStandardError() ), this, SLOT( RPM2TGZprocessRaisedError() ));

	rpm2tgz->start("/bin/sh", args) ;
}

void MainWindowImpl::execContextMenutvTODO(QPoint point){
	if (tvTODO->selectionModel()->selectedRows().count()==0) return;
	QModelIndex mi = tvTODO->currentIndex();
	QMenu menu(this);               	

	//Which actions do we have to put? It depends on package status
	if ( (modelTodo->itemFromIndex(mi)->parent() == 0) && (modelTodo->rowCount(mi) > 0))
		menu.addAction(actionDelete_All_ActionFiles);
	else if ((modelTodo->itemFromIndex(mi)->parent() != 0))
		menu.addAction(actionDelete_ActionFile);

	QPoint pt2 = tvTODO->mapToGlobal(point);
	pt2.setY(pt2.y() + tvTODO->header()->height());
	menu.exec(pt2);        	
}

void MainWindowImpl::execSystemTrayActivated ( QSystemTrayIcon::ActivationReason ar ){
	if ( ar == QSystemTrayIcon::Trigger )  
		if ( this->isHidden() ){
			this->restoreGeometry( savedGeometry );
			if (this->isMinimized()) this->setWindowState(Qt::WindowNoState);
			this->show();
		}
		else {
			savedGeometry = this->saveGeometry();
			this->hide();
		}
}

void MainWindowImpl::keyReleaseEvent(QKeyEvent* ke){
	static int i=0;
	static int k=-9999;
	static int k_count=0;
	static QString cur_dir=modelDir->filePath(tvDir->currentIndex());

	if ((tvPackage->hasFocus()) && (ke->key() >= Qt::Key_A) && (ke->key() <= Qt::Key_Z)){
		QList<QStandardItem*> fi = modelPackage->findItems( ke->text(), Qt::MatchStartsWith, PACKAGE_NAME );
		if (fi.count() > 0){
			if ( (cur_dir != modelDir->filePath(tvDir->currentIndex()) ) || (ke->key() != k) || (fi.count() != k_count) ) i=0;

			foreach (QStandardItem* si, fi){
				QModelIndex mi = si->index();
				mi = proxyModelPackage->mapFromSource(mi);		
				if (!proxyModelPackage->hasIndex(mi.row(), mi.column())) fi.removeAll(si);
			}

			QList<SelectedPackage> sp = getSelectedPackage();
			if (sp.count() == 1) {
				int a=0;
				while (a<=fi.count()-1) {
					QStandardItem* si = fi[a];
					if (si->text() == sp[sp.count()-1].getFileName()) break;
					a++;
					i=a;
				}
				if((a+1)<=fi.count()-1) { a++; i=a; }
				else { a=i=0; }	
			}

			tvPackage->selectionModel()->clear();
			QModelIndex mi = fi[i]->index();
			mi = proxyModelPackage->mapFromSource(mi);		
			tvPackage->scrollTo(mi);		
			QModelIndex maux = proxyModelPackage->index( mi.row(), PACKAGE_ICON );
			tvPackage->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::Select);
			tvPackage->selectionModel()->setCurrentIndex(maux, QItemSelectionModel::Select);
			tvPackage->setCurrentIndex(mi);
			selectInstalledPackage();

			if ((i <= fi.count()-1)) i++; 
			if (i == fi.count()) i = 0;
		}

		k = ke->key();
		k_count = fi.count();
		cur_dir=modelDir->filePath(tvDir->currentIndex());
	}

	else if ((tvInstalledPackages->hasFocus()) && (ke->key() >= Qt::Key_A) && (ke->key() <= Qt::Key_Z)) {
		QList<QStandardItem*> fi = modelInstalledPackages->findItems( ke->text(), Qt::MatchStartsWith, PACKAGE_NAME );
		if (fi.count() > 0){
			if ( (ke->key() != k) || (fi.count() != k_count) ) i=0;

			foreach (QStandardItem* si, fi){
				QModelIndex mi = si->index();
				mi = proxyModelInstalledPackages->mapFromSource(mi);		
				if (!proxyModelInstalledPackages->hasIndex(mi.row(), mi.column())) fi.removeAll(si);
			}

			QList<SelectedPackage> sp = getSelectedInstalledPackage();
			if (sp.count() == 1) {
				int a=0;
				while (a<=fi.count()-1) {
					QStandardItem* si = fi[a];
					if (si->text() == sp[sp.count()-1].getFileName()) break;
					a++; i=a;
				}

				if ((a+1)<=fi.count()-1) { a++; i=a; }
				else a=i=0; 
			}

			tvInstalledPackages->selectionModel()->clear();
			QModelIndex mi = fi[i]->index();
			mi = proxyModelInstalledPackages->mapFromSource(mi);		
			tvInstalledPackages->scrollTo(mi, QAbstractItemView::PositionAtCenter);		
			QModelIndex maux = proxyModelInstalledPackages->index(mi.row(), PACKAGE_ICON);
			tvInstalledPackages->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::Select);
			tvInstalledPackages->selectionModel()->setCurrentIndex(maux, QItemSelectionModel::Select);

			if ((i <= fi.count()-1)) i++; 
			if (i == fi.count()) i = 0;
		}

		k = ke->key();
		k_count = fi.count();
		cur_dir = "";
	}

	else if ((ke->key() != Qt::Key_Shift) && (ke->key() != Qt::Key_Control) && (tvPackage->hasFocus() && (ke->key() == Qt::Key_Down|Qt::Key_Up|Qt::Key_PageDown|Qt::Key_PageUp))) {
		tvPackage->scrollTo(tvPackage->currentIndex());
		selectInstalledPackage();
	}
	else if ((ke->key() == Qt::Key_Down|Qt::Key_Up|Qt::Key_PageDown|Qt::Key_PageUp)) {
		QTreeView *t = twTODO->currentWidget()->findChild<QTreeView*>("tvPkgFileList");
		if ( (t != 0)  && (t->hasFocus())) {
			t->scrollTo( t->currentIndex() );
			showFullPathOfObject( t->currentIndex() );
		}
	}
	else ke->ignore();
}

void MainWindowImpl::keyPressEvent(QKeyEvent* ke){
	if ( ((ke->key() < Qt::Key_A) || (ke->key() > Qt::Key_Z)) && ((ke->key() != Qt::Key_Shift) && (ke->key() != Qt::Key_Control) && (tvPackage->hasFocus()))) {
		tvPackage->scrollTo(tvPackage->currentIndex());
		selectInstalledPackage();
	}
	else {
		QTreeView *t = twTODO->currentWidget()->findChild<QTreeView*>("tvPkgFileList");
		if ( (t != 0)  && (t->hasFocus())) {
			t->scrollTo( t->currentIndex() );
			showFullPathOfObject( t->currentIndex() );
		}
	}

	if (( tvPackage->hasFocus()) && ((ke->key() == Qt::Key_Minus) && (ke->modifiers() == Qt::ControlModifier)) ){
		if (m_PackagesInDirFont > 8){
		  m_PackagesInDirFont--;
			tvPackage->setFont(QFont("Verdana", m_PackagesInDirFont));		
		}
	}

	else if (( tvPackage->hasFocus()) && ((ke->key() == Qt::Key_Equal) && (ke->modifiers() == Qt::ControlModifier)) ){
	  m_PackagesInDirFont++;
		tvPackage->setFont(QFont("Verdana", m_PackagesInDirFont));		
	}

	if (( tvInstalledPackages->hasFocus()) && ((ke->key() == Qt::Key_Minus) && (ke->modifiers() == Qt::ControlModifier)) ){
		if (m_InstalledPackagesFont > 8){
		  m_InstalledPackagesFont--;
			tvInstalledPackages->setFont(QFont("Verdana", m_InstalledPackagesFont));		
		}
	}

	else if (( tvInstalledPackages->hasFocus()) && ((ke->key() == Qt::Key_Equal) && (ke->modifiers() == Qt::ControlModifier)) ){
	  m_InstalledPackagesFont++;
		tvInstalledPackages->setFont(QFont("Verdana", m_InstalledPackagesFont));		
	}

	else if ( (tvPackage->hasFocus()) && ((ke->key() == Qt::Key_L) && (ke->modifiers() == Qt::ControlModifier)) && ( hasTheExecutable("make-lzm") )) { 
		QModelIndexList lmi = tvPackage->selectionModel()->selectedIndexes();
		if (lmi.size() > 0) transformTGZinLZM();
	}	

	else if (ke->key() == Qt::Key_F3) openDirectory();

	else if (ke->key() == Qt::Key_F4) openTerminal();

	else if ((ke->key() == Qt::Key_F8) && (tvPackage->hasFocus())){
		showPackageInfo();
	}

	else if ((ke->key() == Qt::Key_F8) && (tvInstalledPackages->hasFocus())){
		showInstalledPackageInfo();
	}	

	else if ((ke->key() == Qt::Key_Delete) && (tvPackage->hasFocus())){ 
		QModelIndexList lmi = tvPackage->selectionModel()->selectedIndexes();
		if (lmi.size() > 0) deleteFile();
	}  

	else if ((ke->key() == Qt::Key_Delete) && (tvTODO->hasFocus())){
		QModelIndex mi = tvTODO->currentIndex();

		int res=0;
		if ( (modelTodo->itemFromIndex(mi)->parent() == 0) && (modelTodo->rowCount(mi) > 0)){
			res = QMessageBox::question ( this, tr ( "Confirmation" ),
					tr ( "Are you sure you want to delete all these files?" ),
					QMessageBox::Yes | QMessageBox::No,
					QMessageBox::No );

			if (res == QMessageBox::Yes) modelTodo->removeRows (0, modelTodo->rowCount(mi), mi);
		}
		else if ((modelTodo->itemFromIndex(mi)->parent() != 0)){
			res = QMessageBox::question(this, tr("Confirmation"), 
					tr("Are you sure you want to delete this file?"), 
					QMessageBox::Yes | QMessageBox::No,
					QMessageBox::No);

			if (res == QMessageBox::Yes) modelTodo->removeRow(mi.row(), mi.parent());     
		}
	}

	else if ((ke->key() == Qt::Key_W) && (ke->modifiers() == Qt::ControlModifier)){
		closeCurrentTab(); 
	}

	else ke->ignore();
}

void MainWindowImpl::closeClickedTab(){
	if ((m_clickedTab != -1) && (m_clickedTab != 0) && (m_clickedTab != 1)) twTODO->removeTab(m_clickedTab);
	if (twTODO->count() == 2){
		twTODO->setCurrentIndex(0);
		enableCloseTabButton(-1);	
	}
}

void MainWindowImpl::closeCurrentTab() {
	if (twTODO->currentWidget()->isActiveWindow() && (twTODO->currentIndex()!=0 && twTODO->currentIndex()!=1)){ 
		twTODO->removeTab(twTODO->currentIndex()); 
		enableCloseTabButton(-1);	

		if (twTODO->count() == 2)	twTODO->setCurrentIndex(0);
	}	
	if (twTODO->count() == 2){
		enableCloseTabButton(-1);	
	}
}

void MainWindowImpl::closeAllTabs() {
	while ( twTODO->count() > 2 ){  
		twTODO->removeTab( twTODO->count()-1 );    
		QCoreApplication::processEvents();	
	}

	twTODO->setCurrentIndex(0);
}

void MainWindowImpl::hideRightView(){
	static QByteArray stateH = splitter1->saveState();		

	QList<int> l, rl;
	rl = splitter1->sizes();
	if ( rl[2] == 0 ) splitter1->restoreState( stateH );
	else
		splitter1->setSizes( l << dockDirectories->width() << dockPackages->width() << 0 );
}

void MainWindowImpl::normalView(){
	splitter1->restoreState(m_verticalSplit);
	splitter_21->restoreState(m_horizontalSplit);
	if (actionHideRightView->isChecked()) hideRightView();
}

void MainWindowImpl::minimizeLowerView(){
	static QByteArray stateV = splitter_21->saveState();		

	if (actionHideRightView->isChecked()) hideRightView();

	QList<int> l, rl;
	rl = splitter_21->sizes();
	if ( rl[1] == 0 ) splitter_21->restoreState( stateV );
	else
		splitter_21->setSizes( l << twTODO->height() << 0 );

	if (actionHideRightView->isChecked()) hideRightView();
}

void MainWindowImpl::maximizeLowerView(){
	static QByteArray stateV = splitter_21->saveState();		

	QList<int> l, rl;
	rl = splitter_21->sizes();
	if ( rl[0] == 0 ) splitter_21->restoreState( stateV );
	else
		splitter_21->setSizes( l << 0 << twTODO->maximumHeight()); // height() );
}

void MainWindowImpl::initializeActions(){  
	actionFreezePkg = new QAction( this );
	actionUnfreezePkg = new QAction( this );
	actionFreezePkg->setIcon(QIcon((":/resources/images/tgz_frozen.png")));
	actionFreezePkg->setText(tr("Freeze package"));
	actionUnfreezePkg->setIcon(QIcon((":/resources/images/tgz3.png")));
	actionUnfreezePkg->setText(tr("Unfreeze package"));

	actionTransformRPMinTGZ = new QAction( this );
	actionTransformRPMinTGZ->setIcon(QIcon((":/resources/images/tgz3.png")));
	actionTransformRPMinTGZ->setText(tr("Transform in TGZ"));

	actionFindFile->setIcon(QIcon((":/resources/images/find.png"))); 
	actionFindFile->setShortcut( QKeySequence(Qt::CTRL | Qt::Key_F ));

	actionExit->setIcon(QIcon((":/resources/images/exit.png")));    
	actionInstall_package->setIcon(QIcon((":/resources/images/1rightarrow.png")));		
	actionReinstall_package->setIcon(QIcon(":/resources/images/reload2.png"));
	actionUpgrade_package->setIcon(QIcon((":/resources/images/2rightarrow.png")));
	actionDowngrade_package->setIcon(QIcon((":/resources/images/2leftarrow.png")));
	actionRemove_package->setIcon(QIcon((":/resources/images/close.png")));
	actionDelete_file->setIcon(QIcon((":/resources/images/tool_delete.png")));
	actionDelete_All_ActionFiles->setIcon(QIcon((":/resources/images/tool_delete.png")));
	actionDelete_ActionFile->setIcon(QIcon((":/resources/images/tool_delete.png")));
	actionCreate_Directory->setIcon(QIcon((":/resources/images/newFolder.png")));
	actionRemove_Directory->setIcon(QIcon((":/resources/images/trashcan.png")));
	actionAbout_QTGZManager->setIcon(QIcon((":/resources/images/QTGZManager.png")));
	actionAbout_QTGZManager->setShortcut( QKeySequence(Qt::Key_F1) );
	actionAbout_QTGZManager->setToolTip(tr("About %1").arg("QTGZManager"));
	actionSnapshotInstalledPackages->setIcon(QIcon((":/resources/images/camera.png")));

	actionPackageContent->setIcon(QIcon(":/resources/images/content.png"));
	actionPackageInfo->setIcon(QIcon(":/resources/images/info.png"));
	actionInstalledPackageInfo->setIcon(QIcon(":/resources/images/info.png"));
	actionExecuteActions->setIcon(QIcon(":/resources/images/executeActions.png"));
	actionExecuteActions->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_E ));

	actionExpand_All_Items->setIcon(QIcon(":/resources/images/expand.png"));
	actionCollapse_All_Items->setIcon(QIcon(":/resources/images/collapse.png"));
	actionExpandItem = new QAction(QIcon(":/resources/images/expand.png"), tr("Expand this item"), this);	
	actionCollapseItem = new QAction(QIcon(":/resources/images/collapse.png"), tr("Collapse this item"), this);	
	actionDiffAgainstEachOther = new QAction(QIcon(":/resources/images/diff.png"), tr("Diff against each other"), this);	

	actionOpenFile = new QAction(QIcon(":/resources/images/binary.png"), tr("Open file"), this);
	actionOpenDirectory = new QAction(QIcon(":/resources/images/folder.png"), tr("Open directory"), this);
	actionOpenDirectory->setShortcut(QKeySequence(Qt::Key_F3));
	actionOpenTerminal = new QAction(QIcon(":/resources/images/terminal.png"), tr("Open in terminal"), this);
	actionOpenTerminal->setShortcut(QKeySequence(Qt::Key_F4));
	actionHideRightView->setIcon(QIcon(":/resources/images/horizontalView.png"));
	actionHideRightView->setShortcut(QKeySequence(Qt::Key_F9));
	actionNormalView->setIcon(QIcon(":/resources/images/normalView.png"));
	actionNormalView->setShortcut(QKeySequence(Qt::Key_F10));
	actionMinimizeLowerView->setIcon(QIcon(":/resources/images/minimizedLowerView.png"));
	actionMinimizeLowerView->setShortcut(QKeySequence(Qt::Key_F11));
	actionMaximizeLowerView->setIcon(QIcon(":/resources/images/verticalView.png"));
	actionMaximizeLowerView->setShortcut(QKeySequence(Qt::Key_F12));
	actionCloseTab->setIcon(QIcon(":/resources/images/close.png"));	
	actionCloseAllTabs->setIcon(QIcon(":/resources/images/close.png"));
	actionCloseAllTabs->setObjectName("actionCloseAllTabs");
	actionDiffAgainstInstalled->setIcon(QIcon(":/resources/images/diff.png"));
	actionMaximizeLowerView->setToolTip(actionMaximizeLowerView->text());
	actionHideRightView->setToolTip(actionHideRightView->text());
	actionExit->setToolTip(actionExit->text());
	actionExecuteActions->setToolTip(actionExecuteActions->text());

	actionMaximizeLowerView->setCheckable( true );
	actionMaximizeLowerView->setChecked( false );
	actionHideRightView->setCheckable( true );
	actionHideRightView->setChecked( false );
	actionMinimizeLowerView->setCheckable( true );
	actionMinimizeLowerView->setChecked( false );
	actionNormalView->setCheckable( true );
	actionNormalView->setChecked( true );

	//actionRefreshPackageLists->setIcon(QIcon(":/resources/images/refresh.png"));
	//actionRefreshPackageLists->setShortcut( QKeySequence(Qt::Key_F5));
	//actionRefreshPackageLists->setToolTip(actionRefreshPackageLists->text());

	connect(actionTransformRPMinTGZ, SIGNAL(triggered()), this, SLOT(transformRPMinTGZ()));
	connect(actionFreezePkg, SIGNAL(triggered()), this, SLOT(freezePackage()));
	connect(actionUnfreezePkg, SIGNAL(triggered()), this, SLOT(unfreezePackage()));
	connect(actionFindFile, SIGNAL(triggered()), this, SLOT(findFile()));
	connect(actionOpenFile, SIGNAL(triggered()), this, SLOT(openFile()));
	connect(actionOpenDirectory, SIGNAL(triggered()), this, SLOT(openDirectory()));
	connect(actionOpenTerminal, SIGNAL(triggered()), this, SLOT(openTerminal()));
	connect(actionRefreshPackageLists, SIGNAL(triggered()), this, SLOT(refreshTreeViews()));
	connect(actionMaximizeLowerView, SIGNAL(triggered()), this, SLOT(maximizeLowerView()));
	connect(actionMinimizeLowerView, SIGNAL(triggered()), this, SLOT(minimizeLowerView()));
	connect(actionHideRightView, SIGNAL(triggered()), this, SLOT(hideRightView()));
	connect(actionNormalView, SIGNAL(triggered()), this, SLOT(normalView()));
	connect(actionExpand_All_Items, SIGNAL(triggered()), this, SLOT(expandAllContentItems()));
	connect(actionExpandItem,  SIGNAL(triggered()), this, SLOT(expandThisContentItems()));
	connect(actionCollapseItem,  SIGNAL(triggered()), this, SLOT(collapseThisContentItems()));
	connect(actionCollapse_All_Items, SIGNAL(triggered()), this, SLOT(collapseAllContentItems()));
	connect(actionCloseAllTabs, SIGNAL(triggered()), this, SLOT(closeAllTabs()));
	connect(actionCloseTab, SIGNAL(triggered()), this, SLOT(closeCurrentTab()));
	connect(actionExecuteActions, SIGNAL(triggered()), this, SLOT(executePackageActions()));
	connect(actionPackageInfo, SIGNAL(triggered()), this, SLOT(showPackageInfo()));
	connect(actionInstalledPackageInfo, SIGNAL(triggered()), this, SLOT(showInstalledPackageInfo()));
	connect(actionPackageContent, SIGNAL(triggered()), this, SLOT(showPackageContent()));
	connect(actionUpgrade_package, SIGNAL(triggered()), this, SLOT(insertUpgradePackageAction()));
	connect(actionReinstall_package, SIGNAL(triggered()), this, SLOT(insertReinstallPackageAction()));
	connect(actionInstall_package, SIGNAL(triggered()), this, SLOT(insertInstallPackageAction()));
	connect(actionDowngrade_package, SIGNAL(triggered()), this, SLOT(insertDowngradePackageAction()));
	connect(actionRemove_package, SIGNAL(triggered()), this, SLOT(insertRemovePackageAction()));		
	connect(actionDelete_file, SIGNAL(triggered()), this, SLOT(deleteFile()));
	connect(actionDiffAgainstInstalled, SIGNAL(triggered()), this, SLOT(diffAgainstInstalled()));
	connect(actionDiffAgainstEachOther, SIGNAL(triggered()), this, SLOT(diffAgainstEachOther()));
	connect(actionDelete_ActionFile, SIGNAL(triggered()), this, SLOT(deleteActionFile()));
	connect(actionDelete_All_ActionFiles, SIGNAL(triggered()), this, SLOT(deleteAllActionFiles()));
	connect(actionCreate_Directory, SIGNAL(triggered()), this, SLOT(createDirectory()));
	connect(actionRemove_Directory, SIGNAL(triggered()), this, SLOT(removeDirectory()));	    	   
	connect(actionExit, SIGNAL(triggered()), this, SLOT(exitApplication()));
	connect(actionAbout_QTGZManager, SIGNAL(triggered()), this, SLOT(aboutQTGZManager()));
	connect(actionSnapshotInstalledPackages, SIGNAL(triggered()), this, SLOT(takeSnapshotOfInstalledPackages()));

	actionExecuteActions->setEnabled( false );
}

void MainWindowImpl::takeSnapshotOfInstalledPackages(){
	twTODO->setCurrentIndex(1);
	QString msg;
	textEdit->clear();
	msg = tr("<h4>Please, wait while the snapshot of installed packages is being generated...</h4><br>");
	textEdit->insertHtml(msg);

	Package pkg;
	QString fileName = pkg.dumpInstalledPackageList();
	msg = tr("<h4>Finished generating the snapshot of installed packages!</h4><br>"
			"<br>The name of the snapshot is: \"%1\"<br>" 
			"<br>For more information about QTGZManager visit: %2").
			arg(fileName).
			arg("<a href=\"http://jtgzmanager.sf.net\" target=\"_blank\">http://jtgzmanager.sf.net</a>");		
	textEdit->insertHtml(msg);
	textEdit->ensureCursorVisible();
}

void MainWindowImpl::refreshTreeViews(){
	showPackagesInDirectory();
}

void MainWindowImpl::initializeToolBar(){
	QActionGroup *ag = new QActionGroup(this);

	toolBar->setToolButtonStyle ( Qt::ToolButtonIconOnly ); 
	toolBar->addAction(actionHideRightView);
	
	toolBar->addAction(ag->addAction(actionNormalView));
	toolBar->addAction(ag->addAction(actionMinimizeLowerView));
	toolBar->addAction(ag->addAction(actionMaximizeLowerView));
	
	toolBar->addSeparator();
	toolBar->addAction(actionFindFile);
	toolBar->addAction(actionExecuteActions);
	toolBar->addAction(actionSnapshotInstalledPackages);
	toolBar->addSeparator();
	toolBar->addAction(actionAbout_QTGZManager);
	toolBar->addAction(actionExit);
}

void MainWindowImpl::refreshPackageTreeView(){
	delete modelPackage;
	delete proxyModelPackage;
	initializePackageListView();
}

void MainWindowImpl::refreshInstalledPackageTreeView(){
	delete modelInstalledPackages;
	delete proxyModelInstalledPackages;
	initializeInstalledPackagesListView();
	reapplyInstalledPackagesFilter();
}

void MainWindowImpl::freezePackage(){
	int bkSize = frozenPkgList->count();
	foreach(QModelIndex item, tvInstalledPackages->selectionModel()->selectedIndexes()){
		if ( item.column() == PACKAGE_ICON ){    
			QStandardItem *si = new QStandardItem( iconFrozen, "Frozen" ); 
			QModelIndex mi = proxyModelInstalledPackages->mapToSource( item );
			modelInstalledPackages->setItem(mi.row(), mi.column(), si);
		}
		else if ( item.column() == PACKAGE_NAME ){    		
			*frozenPkgList << Package::getBaseName( proxyModelInstalledPackages->data(item).toString());
		}
	}

	refreshInstalledPackageTreeView();

	//Now we must reconstruct the list of frozen packages in order to save it to the QSettings.
	frozenPkgList->save();
	if ( (modelPackage->rowCount()>0) && (bkSize != frozenPkgList->count()) ) showPackagesInDirectory();
}

void MainWindowImpl::unfreezePackage(){
	int bkSize = frozenPkgList->count();
	foreach(QModelIndex item, tvInstalledPackages->selectionModel()->selectedIndexes()){
		if ( item.column() == PACKAGE_ICON ){    
			QStandardItem *si = new QStandardItem( iconUnFrozen, "UnFrozen" ); 
			QModelIndex mi = proxyModelInstalledPackages->mapToSource( item );
			modelInstalledPackages->setItem(mi.row(), mi.column(), si);
		}		
		else if ( item.column() == PACKAGE_NAME ){    		
			frozenPkgList->removeAll( Package::getBaseName(proxyModelInstalledPackages->data(item).toString() ));
		}
	}

	refreshInstalledPackageTreeView();

	//Now we must reconstruct the list of frozen packages in order to save it to the QSettings.
	//m_SYSsettings->setValue( KEY_FROZEN_PACKAGES_LIST, QVariant( m_slFrozenPackages ) );
	frozenPkgList->save();
	if ( (modelPackage->rowCount()>0) && (bkSize != frozenPkgList->count()) ) showPackagesInDirectory();
}

void MainWindowImpl::aboutQTGZManager(){	
	QString about;
	about = "<strong>QTGZManager</strong>  is a GUI for the Slackware <cite>pkgtools</cite>, licensed under the terms of <a href=\"http://www.gnu.org/licenses/gpl-2.0.html\">GPL v2</a><br><br>"
			"Basic usage help:"					
			"<ul><li>Use drag and drop or context menus to generate actions</li>"
			"<li>Select \"Information\" over a package to see it's info</li>"
			"<li>Select \"Content\" over a package to see it's content</li>"
			"<li>Select \"Freeze\" over an installed package to freeze it's version</li>"
			"<li>Select \"Diff\" over an old/new version of a package to see it's changes</li>"
			"<li>Press Ctrl+E or click \"Execute\" to start the execution of actions</li>"
			"<li>Press Ctrl+\"+\" or Ctrl+\"-\" over the package or installed package lists to maximize or minimize their font size</li></ul>"					
			"<br>I'd like to <strong>thank</strong>:"
			"<ul><li>Andrea Sciucca - for feedback and italian translation</li>"
			"<li>Grzegorz Gibas - for feedback and polish translation</li>"
			"<li>Mahdi Fattahi - for feedback and farsi translation</li>"
			"<li>Manfred Mueller - for feedback and german translation</li></ul>"
			"<br>For more information visit <a href=\"http://jtgzmanager.sf.net\">QTGZManager's main site</a>  or the <a href=\"http://jtgzmanager.sf.net/development.html\">development blog</a> <br><br>"
			"<i>Alexandre Albuquerque Arnt - Main Developer</i><br>";

	QString aux("About");
	QString translated_about = QApplication::translate ( "MainWindow", aux.toUtf8(), 0, QApplication::UnicodeUTF8 );
	for (int c=2; c<twTODO->count(); c++)
		if (twTODO->tabText(c) == translated_about){
			twTODO->setCurrentIndex ( c );			
			return;
		} 

	QWidget *tabAbout = new QWidget();
	QGridLayout *gridLayoutX = new QGridLayout ( tabAbout );
	gridLayoutX->setSpacing ( 0 );
	gridLayoutX->setMargin ( 0 );

	QTextBrowser *text = new QTextBrowser(tabAbout);
	text->setReadOnly(true);
	text->setFrameShape(QFrame::NoFrame);
	text->setFrameShadow(QFrame::Plain);
	text->setOpenExternalLinks(true);
	gridLayoutX->addWidget ( text, 0, 0, 1, 1 );
	text->setHtml(about);
	text->show();

	int tindex = twTODO->addTab( tabAbout, QApplication::translate ( "MainWindow", aux.toUtf8(), 0, QApplication::UnicodeUTF8 ) );
	twTODO->setTabText(twTODO->indexOf(tabAbout), QApplication::translate("MainWindow", aux.toUtf8(), 0, QApplication::UnicodeUTF8));

	twTODO->setCurrentIndex ( tindex );
}

void MainWindowImpl::deleteActionFile(){
	QModelIndex mi = tvTODO->currentIndex();

	int res = QMessageBox::question ( this, tr ( "Confirmation" ),
			tr ( "Are you sure you want to delete this file?" ),
			QMessageBox::Yes | QMessageBox::No,
			QMessageBox::No );

	if ( res == QMessageBox::Yes ){
		modelTodo->removeRow ( mi.row(), mi.parent() );
	}
}

void MainWindowImpl::deleteAllActionFiles(){
	QModelIndex mi = tvTODO->currentIndex();

	int res = QMessageBox::question ( this, tr ( "Confirmation" ),
			tr ( "Are you sure you want to delete all these files?" ),
			QMessageBox::Yes | QMessageBox::No,
			QMessageBox::No );

	if ( res == QMessageBox::Yes ){
		modelTodo->removeRows (0, modelTodo->rowCount(mi), mi);
	}
}

void MainWindowImpl::openFileOrDirectory(const QModelIndex& mi){		
	const QStandardItemModel *sim = qobject_cast<const QStandardItemModel*>(mi.model());
	QStandardItem *si = sim->itemFromIndex(mi);
	QDir d;
	QFile f;
	/*if ( ( si->icon().serialNumber() == iconFolder.serialNumber() ) && ( d.exists( lblStatus->text() )) ) {
		openDirectory();
	}*/
	if ((si->icon().serialNumber() == iconBinary.serialNumber()) && ( f.exists( lblStatus->text())) ) {
		openFile();
	}
}

void MainWindowImpl::findFile(){
	if ( findDialog == 0 )	findDialog = new FindDialogImpl( this );
	else findDialog->show();
}

void MainWindowImpl::openFile(){
	QFile f(lblStatus->text());
	QFileInfo fi(f);
	if (fi.size() == 0) return;
	QProcess *p = new QProcess(this);
	QStringList s;

	s << lblStatus->text();
	p->start( "file", s );
	p->waitForFinished();
	QByteArray output = p->readAllStandardOutput();

	if ((output.indexOf( "ASCII", 0 ) == -1) && (output.indexOf( "text", 0 ) == -1)) {
		int res = QMessageBox::question(this, tr("Confirmation"), 
				tr("This file does not appear to be a simple text.\n"
						"Are you sure you want to run it?"), 
						QMessageBox::Yes | QMessageBox::No,
						QMessageBox::No);

		if ( res == QMessageBox::No ) return;
	}

	s.clear();
	s << "exec";
	s << "file:" + lblStatus->text(); 
	p->startDetached( "kfmclient" , s );
}

void MainWindowImpl::openDirectory(){
	QProcess *p = new QProcess(this);
	QStringList s;
	s << "newTab";

	QString targetDir;
	if ((tvPackage->hasFocus()) || (tvDir->hasFocus())) targetDir = modelDir->filePath(tvDir->currentIndex());
	else if (lblStatus->text() != ""){
		//QFileInfo fi(lblStatus->text());
		targetDir = lblStatus->text(); //fi.path(); 
	}
	else{
		delete p;
		return;
	}
	
	QFileInfo f(targetDir);
	if (f.exists()){
		s << targetDir;
		p->startDetached( "kfmclient" , s );
	}
}

void MainWindowImpl::openTerminal(){
	QProcess *p = new QProcess(this);
	QStringList s;
	s << "--workdir";

	QString targetDir;
	QTreeView *t = twTODO->currentWidget()->findChild<QTreeView*>("tvPkgFileList");
	if ((t) && (t->hasFocus()) && (lblStatus->text() != "")){
		QFileInfo fi(lblStatus->text());
		if (fi.isDir()) targetDir = lblStatus->text();
		else targetDir = fi.path(); 
	}
	else if	(leDir->text() != "") targetDir = leDir->text();
	else{
		delete p;
		return;
	}
	QFileInfo f(targetDir);
	if (f.exists()){
		s << targetDir;
		p->startDetached( "konsole" , s );
	}
}

void MainWindowImpl::deleteFile(){
	QDir d(modelDir->filePath(tvDir->currentIndex())); 				
	d.setFilter(QDir::Files);		

	QList<SelectedPackage> lmi = getSelectedPackage();		
	int res;

	if (lmi.size() > 1)
		res = QMessageBox::question(this, tr("Confirmation"), 
				tr("Are you sure you want to delete these files?"), 
				QMessageBox::Yes | QMessageBox::No,
				QMessageBox::No);
	else
		res = QMessageBox::question(this, tr("Confirmation"), 
				tr("Are you sure you want to delete this file?"), 
				QMessageBox::Yes | QMessageBox::No,
				QMessageBox::No);

	if (res == QMessageBox::Yes){
		foreach (SelectedPackage mi, lmi){
			QString fileToDelete = mi.getCompleteFileName(); //d.absolutePath() + QDir::separator() + modelPackage->itemFromIndex(mi)->text();

			QFile::remove(fileToDelete);			
		}			
	}
}

void MainWindowImpl::exitApplication(){
	m_reallyWannaClose = true;
	close();
}

bool MainWindowImpl::close(){
	bool res = QWidget::close();
	if ( res == true ){ 
		qApp->exit();
		return( true );
	}
	else return( false );
}

void MainWindowImpl::closeEvent(QCloseEvent *event){
	savedGeometry = this->saveGeometry();

	if ((m_reallyWannaClose) && ((install->rowCount() != 0) || (remove->rowCount() != 0) || (downgrade->rowCount() != 0) || 		(upgrade->rowCount() != 0))){
		int res = QMessageBox::question(this, tr("Confirmation"), 
				tr("There are actions waiting for execution!\n"
						"Are you sure you want to exit?"), 
						QMessageBox::Yes | QMessageBox::No,
						QMessageBox::No);

		if (res == QMessageBox::Yes) event->accept(); 
		else event->ignore();
	}
	m_reallyWannaClose = false;
}

void MainWindowImpl::initializeDirTreeView(){
	modelDir = new QDnDDirModel(this);
	modelDir->setFilter(QDir::AllDirs|QDir::CaseSensitive|QDir::NoDotAndDotDot);
	QModelIndex index;
	QString initialDir(QDir::homePath());
	if ( QCoreApplication::arguments().count() > 1 ){
		initialDir = QCoreApplication::arguments().at(1); 
		if ( initialDir.indexOf("-initialdir=", 0, Qt::CaseInsensitive) != -1 ){
			initialDir = initialDir.mid(12, initialDir.length()-12);
			if (QFile::exists(initialDir)) index = modelDir->index(initialDir);
		}
	}
	index = modelDir->setRootPath(initialDir);

	QPalette p(dockDirectories->palette());
	QPalette p2(leDir->palette());
	p2.setColor(QPalette::Base, p.color(QPalette::Window));
	leDir->setPalette(p2);

	tvDir->setModel(modelDir);
	tvDir->setColumnHidden(1, true);
	tvDir->setColumnHidden(2, true);
	tvDir->setColumnHidden(3, true);
	tvDir->setFont(QFont("Verdana", m_DirectoryFont));
	tvDir->header()->hide();
	tvDir->setStyleSheet( treeViewStyleSheet());
	tvDir->setAcceptDrops(true);
	tvDir->setDropIndicatorShown(true);

	//tvDir->resizeColumnToContents(0);
	tvDir->setCurrentIndex(index);
	tvDir->expand(index);
	//QMessageBox::information(this, "Debug", QString::number(tvDir->verticalScrollBar()->maximum()));
	update();
	tvDir->scrollTo(tvDir->currentIndex());
	//tvDir->verticalScrollBar()->setValue(tvDir->verticalScrollBar()->maximum());
	changeDir();
}

QString MainWindowImpl::filterPackageFoundStyleSheet(){
	return QString("QLineEdit{ color: black; "
		 "background-color: rgb(255, 255, 200);"
     "border-color: rgb(206, 204, 197);}"
	);	
}

QString MainWindowImpl::filterPackageNotFoundStyleSheet(){
	return QString("QLineEdit{ color: white; "
		 "background-color: rgb(207, 135, 142);"
		 "border-color: rgb(206, 204, 197);}"
	);	
}

QString MainWindowImpl::treeViewStyleSheet(){
	return QString("QTreeView::branch:has-siblings:!adjoins-item {"
			"   border-image: url(:/resources/styles/vline.png) 0;"
			"}"
			"QTreeView::branch:has-siblings:adjoins-item {"
			"    border-image: url(:/resources/styles/branch-more.png) 0;"
			"}"
			"QTreeView::branch:!has-children:!has-siblings:adjoins-item {"
			"   border-image: url(:/resources/styles/branch-end.png) 0;"
			"}"
			"QTreeView::branch:has-children:!has-siblings:closed,"
			"QTreeView::branch:closed:has-children:has-siblings {"
			"       border-image: none;"
			"        image: url(:/resources/styles/branch-closed_BW.png);"
			"}"
			"QTreeView::branch:open:has-children:!has-siblings,"
			"QTreeView::branch:open:has-children:has-siblings  {"
			"       border-image: none;"
			"        image: url(:/resources/styles/branch-open_BW.png);}");
}

void MainWindowImpl::initializePackageListView(){
	proxyModelPackage = new QSortFilterProxyModel(this);
	modelPackage = new QDnDStandardItemModel(this);
	proxyModelPackage->setSourceModel(modelPackage);
	proxyModelPackage->setFilterKeyColumn(1);

	tvPackage->setItemDelegate(new tvPackagesItemDelegate(tvPackage));

	tvPackage->setFont(QFont("Verdana", m_PackagesInDirFont));		
	tvPackage->setEditTriggers(QAbstractItemView::NoEditTriggers);
	tvPackage->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);		
	//tvPackage->setSelectionBehavior(QAbstractItemView::SelectItems);
	tvPackage->setAllColumnsShowFocus( true );

	tvPackage->setModel(proxyModelPackage);
	tvPackage->setSortingEnabled( true );
	tvPackage->sortByColumn( 1, Qt::AscendingOrder);
	tvPackage->setIndentation( 0 );
	tvPackage->header()->setSortIndicatorShown(true);
	tvPackage->header()->setClickable(true);
	tvPackage->header()->setMovable(false);
	tvPackage->header()->setDefaultAlignment( Qt::AlignCenter );
	tvPackage->header()->setResizeMode( QHeaderView::Fixed );

	//Prepare it for drag operations
	tvPackage->setSelectionMode(QAbstractItemView::ExtendedSelection);
	tvPackage->setDragEnabled(true);

	//tvPackage->setAutoScroll(true);
	connect(leFilterPackage, SIGNAL(textChanged (const QString&)), this, SLOT(reapplyPackageFilter()));  
}

void MainWindowImpl::initializeInstalledPackagesListView(){		
	proxyModelInstalledPackages = new QSortFilterProxyModel(this);
	modelInstalledPackages = new QStandardItemModel(this);
	proxyModelInstalledPackages->setSourceModel(modelInstalledPackages);
	proxyModelInstalledPackages->setFilterKeyColumn(1);

	tvInstalledPackages->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	tvInstalledPackages->setItemDelegate(new tvPackagesItemDelegate(tvInstalledPackages));

	QDir d(PACKAGES_DIR); 				
	d.setFilter(QDir::Files);		
	QStringList list = d.entryList();

	QStandardItem *parentItem = modelInstalledPackages->invisibleRootItem();
	QList<QStandardItem*> lIcons, lNames;

	if ( frozenPkgList->isEmpty() ){
		foreach( QString s, list ){
			lIcons << new QStandardItem( iconUnFrozen, "_UnFrozen" ); 
			lNames << new QStandardItem( s );
		}
	}
	else{
		foreach( QString s, list ){
			if ( frozenPkgList->indexOf( QRegExp(Package::getBaseName(s)), 0 ) == -1 ) 
				lIcons << new QStandardItem( iconUnFrozen, "_UnFrozen" ); 
			else
				lIcons << new QStandardItem( iconFrozen, "_Frozen" ); 

			lNames << new QStandardItem( s ); 
		}
	}

	parentItem->insertColumn(0, lIcons );
	parentItem->insertColumn(1, lNames );

	QStringList sl;
	modelInstalledPackages->setHorizontalHeaderLabels(sl << "" << tr("Name"));

	tvInstalledPackages->setFont(QFont("Verdana", m_InstalledPackagesFont));		
	tvInstalledPackages->setEditTriggers(QAbstractItemView::NoEditTriggers);
	tvInstalledPackages->setSelectionMode(QAbstractItemView::ExtendedSelection);

	tvInstalledPackages->setModel(proxyModelInstalledPackages);			
	tvInstalledPackages->setSortingEnabled( true );
	tvInstalledPackages->sortByColumn( 1, Qt::AscendingOrder);
	tvInstalledPackages->setIndentation( 0 );

	tvInstalledPackages->setAllColumnsShowFocus( true );
	tvInstalledPackages->header()->setSortIndicatorShown(true);
	tvInstalledPackages->header()->setClickable(true);
	tvInstalledPackages->header()->setMovable(false);
	dockInstalledPackages->setWindowTitle(tr("%1 Installed Packages").arg(QString::number(list.size())));

	connect(leFilterInstalledPackages, SIGNAL(textChanged (const QString&)), this, SLOT(reapplyInstalledPackagesFilter()));  

	tvInstalledPackages->setColumnWidth(0, 24);	
	tvInstalledPackages->setColumnWidth(1, 50); 

	tvInstalledPackages->header()->setSortIndicator( m_InstalledPackageListOrderedCol, m_InstalledPackageListSortOrder );	

	tvInstalledPackages->sortByColumn( m_InstalledPackageListOrderedCol, m_InstalledPackageListSortOrder );
	tvInstalledPackages->header()->setDefaultAlignment( Qt::AlignCenter );
	tvInstalledPackages->header()->setResizeMode( QHeaderView::Fixed );
}

void MainWindowImpl::initializeTodoTreeView(){
	modelTodo = new QDnDStandardItemModel(this);

	QFont f("Verdana", m_TodoFont);
	tvTODO->setFont(f);		
	tvTODO->setModel(modelTodo);
	tvTODO->setEditTriggers(QAbstractItemView::NoEditTriggers);

	tvTODO->setDropIndicatorShown(true);
	tvTODO->setAcceptDrops(true);

	tvTODO->header()->setSortIndicatorShown(false);
	tvTODO->header()->setClickable(false);
	tvTODO->header()->setMovable(false);
	tvTODO->header()->setDefaultAlignment( Qt::AlignCenter );

	tvTODO->setStyleSheet( treeViewStyleSheet()	);

	textEdit->setFont(QFont("Verdana", 11));
	modelTodo->setSortRole(0);
	modelTodo->setColumnCount(0);

	downgrade = new QStandardItem(iconInferior, TODO_DOWNGRADE);
	install = new QStandardItem(iconNotInstalled, TODO_INSTALL);
	remove = new QStandardItem(iconInternalError, TODO_REMOVE);
	upgrade = new QStandardItem(iconSuperior, TODO_UPGRADE);
	reinstall = new QStandardItem(iconInstalled, TODO_REINSTALL);

	QStandardItem* parentItem = modelTodo->invisibleRootItem();  

	parentItem->appendRow(downgrade);
	parentItem->appendRow(install);
	parentItem->appendRow(reinstall);
	parentItem->appendRow(remove);
	parentItem->appendRow(upgrade);			

	modelTodo->setHorizontalHeaderLabels(QStringList() << tr("Package Actions ( Ctrl+E to execute )"));

	twTODO->setCurrentIndex(0);
}

void MainWindowImpl::createTabPkgDiff(const QString pkg, const QString installedPkg, const QString diff ){
	QWidget *tabPkgFileList = new QWidget();
	QGridLayout *gridLayoutX = new QGridLayout ( tabPkgFileList );
	gridLayoutX->setSpacing ( 0 );
	gridLayoutX->setMargin ( 0 );

	QTextBrowser *text = new QTextBrowser(tabPkgFileList);
	text->setReadOnly(true);
	text->setFrameShape(QFrame::NoFrame);
	text->setFrameShadow(QFrame::Plain);
	gridLayoutX->addWidget ( text, 0, 0, 1, 1 );


	QString html;
	html += tr("<table border=\"1\" bgcolor=\"#FBFFFC\"><tr><th colspan=\"2\"><h2>Diff against %1</h2></th></tr>").arg(installedPkg);
	html += "<tr bgcolor=\"#FBFFFC\"><td><font color=\"#5C311F\"><h2>" + pkg + "</h2></td><td><font color=\"#5C311F\"><h2>" + installedPkg + "</h2></td></tr>";

	//We must first parse this diff content to produce human-readable text
	QStringList ldiff = diff.split("\n");
	foreach (QString s, ldiff){
		if ((s[0] != '<') && (s[0] != '>')) continue;
		if (s[0] == '<'){
			html += "<tr><td><h4><font color=\"darkgreen\">" + s.mid(2) + "</h4></td><td></td></tr>";
		}		
		else if (s[0] == '>') {
			html += "<tr><td></td><td><h4><font color=\"#940305\">" + s.mid(2) + "</h4></td></tr>";
		}
	}
	html += "</table>";
	text->insertHtml(html); 
	QString aux(pkg + " DIFF");
	int tindex = twTODO->addTab( tabPkgFileList, QApplication::translate ( "MainWindow", aux.toUtf8(), 0, QApplication::UnicodeUTF8 ) );
	twTODO->setTabText(twTODO->indexOf(tabPkgFileList), QApplication::translate("MainWindow", aux.toUtf8(), 0, QApplication::UnicodeUTF8));

	twTODO->setCurrentIndex ( tindex ); 
	text->verticalScrollBar()->setValue(0);
}

void MainWindowImpl::createTabPkgFileList(const QString pkgName, const QStringList fileList){
	QWidget *tabPkgFileList = new QWidget();
	QGridLayout *gridLayoutX = new QGridLayout ( tabPkgFileList );
	gridLayoutX->setSpacing ( 0 );
	gridLayoutX->setMargin ( 0 );

	QStandardItemModel *modelPkgFileList = new QStandardItemModel(this);
	QStandardItemModel *fakeModelPkgFileList = new QStandardItemModel(this);
	QTreeView *tvPkgFileList = new QTreeView(tabPkgFileList);
	QFont f("Verdana", m_PkgListFont);
	tvPkgFileList->setFont(f);   

	tvPkgFileList->setEditTriggers(QAbstractItemView::NoEditTriggers);
	tvPkgFileList->setDropIndicatorShown(false);
	tvPkgFileList->setAcceptDrops(false);  
	tvPkgFileList->header()->setSortIndicatorShown(false);
	tvPkgFileList->header()->setClickable(false);
	tvPkgFileList->header()->setMovable(false);
	//tvPkgFileList->header()->setDefaultAlignment( Qt::AlignCenter );
	tvPkgFileList->setFrameShape(QFrame::NoFrame);
	tvPkgFileList->setFrameShadow(QFrame::Plain);
	tvPkgFileList->setObjectName("tvPkgFileList");
	tvPkgFileList->setStyleSheet( treeViewStyleSheet()	);

	modelPkgFileList->setSortRole(0);
	modelPkgFileList->setColumnCount(0);

	gridLayoutX->addWidget ( tvPkgFileList, 0, 0, 1, 1 );

	QStandardItem* fakeRoot = fakeModelPkgFileList->invisibleRootItem();
	QStandardItem* root = modelPkgFileList->invisibleRootItem();

	QStandardItem *bkpDir, *item, *bkpItem=root, *parent;
	bool first=true;
	bkpDir = root;
	foreach ( QString file, fileList )
	{
		QFileInfo fi ( file );
		if ( file.endsWith ( '/' ) )
		{
			if ( first == true )
			{
				item = new QStandardItem ( iconFolder, file );
				fakeRoot->appendRow ( item );
			}
			else
			{
				if ( file.indexOf ( bkpDir->text() ) != -1 )
				{					
					item = new QStandardItem ( iconFolder, file );
					bkpDir->appendRow ( item );
				}
				else
				{
					parent = bkpItem->parent();
					do
					{
						if ( parent == 0 || file.indexOf ( parent->text() ) != -1 ) break;
						parent = parent->parent();
					}
					while ( parent != fakeRoot );

					item = new QStandardItem ( iconFolder, file );
					if ( parent != 0 ) parent->appendRow ( item );
					else fakeRoot->appendRow ( item );
				}
			}
			bkpDir = item;
		}
		else
		{
			item = new QStandardItem ( iconBinary, fi.fileName() );
			parent = bkpDir;
			do
			{
				if ( parent == 0 || file.indexOf ( parent->text() ) != -1 ) break;
				parent = parent->parent();
			}
			while ( parent != fakeRoot );
			parent->appendRow ( item );
		}

		bkpItem = item;
		first = false;
	}

	root = fakeRoot;
	fakeModelPkgFileList->sort(0);
	modelPkgFileList = fakeModelPkgFileList;

	tvPkgFileList->setModel(modelPkgFileList);
	tvPkgFileList->header()->setDefaultAlignment( Qt::AlignCenter );
	modelPkgFileList->setHorizontalHeaderLabels( QStringList() << tr("Content of \"%1\" ( Ctrl+W to close this tab )").arg(pkgName)); 

	QList<QStandardItem*> lit = modelPkgFileList->findItems( "/", Qt::MatchStartsWith | Qt::MatchRecursive );	

	foreach( QStandardItem* it, lit ){
		QFileInfo fi( it->text() );
		if ( fi.isFile() == false ){
			QString s( it->text() );
			s.remove(s.size()-1, 1);
			s = s.right(s.size() - s.lastIndexOf('/') -1);
			it->setText( s );
		}
	}

	QString aux("&"+pkgName);
	int tindex = twTODO->addTab( tabPkgFileList, QApplication::translate ( "MainWindow", aux.toUtf8(), 0, QApplication::UnicodeUTF8 ) );
	twTODO->setTabText(twTODO->indexOf(tabPkgFileList), QApplication::translate("MainWindow", aux.toUtf8(), 0, QApplication::UnicodeUTF8));

	twTODO->setCurrentIndex ( tindex );

	tvPkgFileList->setContextMenuPolicy(Qt::CustomContextMenu);
	connect(tvPkgFileList, SIGNAL(customContextMenuRequested(QPoint)), 
			this, SLOT(execContextMenuPkgFileList(QPoint)));

	connect(tvPkgFileList, SIGNAL(clicked (const QModelIndex&)), 
			this, SLOT(showFullPathOfObject(const QModelIndex&))); 
	connect(tvPkgFileList, SIGNAL(doubleClicked (const QModelIndex&)), 
			this, SLOT(openFileOrDirectory(const QModelIndex&))); 

	connect(tvPkgFileList, SIGNAL(pressed (const QModelIndex&)), 
			tvPkgFileList, SIGNAL(clicked (const QModelIndex&))); 
	connect(tvPkgFileList, SIGNAL(activated(const QModelIndex)), tvPkgFileList, 
			SIGNAL(clicked(const QModelIndex)));
}

void MainWindowImpl::showFullPathOfObject( const QModelIndex & index ){
	if (!index.isValid()) return;

	const QStandardItemModel *sim = qobject_cast<const QStandardItemModel*>( index.model() );	

	QStringList sl;	
	QModelIndex nindex;
	QString str;
	sl << sim->itemFromIndex( index )->text();

	nindex = index;
	while (1){
		nindex = sim->parent( nindex ); 
		if ( nindex != sim->invisibleRootItem()->index() ) sl << sim->itemFromIndex( nindex )->text();
		else break;
	}
	str = QDir::separator() + str;

	for ( int i=sl.count()-1; i>=0; i-- ){
		if ( i < sl.count()-1 ) str += QDir::separator();
		str += sl[i];
	}

	lblStatus->setText( str );
}

void MainWindowImpl::execContextMenuPkgFileList(QPoint point){
	QTreeView *t = twTODO->currentWidget()->findChild<QTreeView*>("tvPkgFileList");
	if (t == 0) return;
	QModelIndex mi = t->currentIndex();
	QMenu menu(this);            

	QStandardItemModel *sim = qobject_cast<QStandardItemModel*>(t->model());
	QStandardItem *si = sim->itemFromIndex(mi);
	if (si == 0) return;
	if (si->hasChildren() && (!t->isExpanded(mi))) menu.addAction( actionExpandItem );
	if (si->hasChildren() && (t->isExpanded(mi))) menu.addAction( actionCollapseItem );

	if (menu.actions().count() > 0) menu.addSeparator(); 

	menu.addAction( actionCollapse_All_Items );
	menu.addAction( actionExpand_All_Items );

	menu.addSeparator();

	QDir d;
	QFile f(lblStatus->text()); QFileInfo fi(f);
	if ( ( si->icon().serialNumber() == iconFolder.serialNumber() ) && ( d.exists( lblStatus->text() )) ) {
		menu.addAction( actionOpenDirectory );
		menu.addAction( actionOpenTerminal );	
	}
	else if ( f.exists( lblStatus->text() ) && (fi.size() > 0) ) {
		menu.addAction ( actionOpenFile );
	}

	menu.addSeparator();

	menu.addAction( actionCloseTab );
	if (twTODO->count() > 3) 
		menu.addAction( actionCloseAllTabs );

	QPoint pt2 = t->mapToGlobal(point);
	pt2.setY(pt2.y() + t->header()->height());
	menu.exec(pt2);        	        	
}

void MainWindowImpl::expandAllContentItems(){
	QTreeView *tv =  twTODO->currentWidget()->findChild<QTreeView *>("tvPkgFileList") ;		
	if ( tv != 0 ){
		tv->repaint(tv->rect());
 		QCoreApplication::processEvents();
		tv->expandAll();
	}
}

void MainWindowImpl::_expandItem(QTreeView* tv, QStandardItemModel* sim, QModelIndex mi){
	for (int i=0; i<sim->rowCount(mi); i++){
		if (sim->hasChildren(mi)){			
	 		QCoreApplication::processEvents();
			tv->expand(mi);
			QModelIndex mi2 = mi.child(i, 0);
			_expandItem(tv, sim, mi2);
		}
	}
}

void MainWindowImpl::_collapseItem(QTreeView* tv, QStandardItemModel* sim, QModelIndex mi){
	for (int i=0; i<sim->rowCount(mi); i++){
		if (sim->hasChildren(mi)){			
	 		QCoreApplication::processEvents();
			tv->collapse(mi);
			QModelIndex mi2 = mi.child(i, 0);
			_collapseItem(tv, sim, mi2);
		}
	}
}

void MainWindowImpl::expandThisContentItems(){
	QTreeView *tv =  twTODO->currentWidget()->findChild<QTreeView *>("tvPkgFileList") ;
	if ( tv != 0 ){
		tv->repaint(tv->rect());
 		QCoreApplication::processEvents();
		QStandardItemModel *sim = qobject_cast<QStandardItemModel*>(tv->model());
		QModelIndex mi = tv->currentIndex();
		if (sim->hasChildren(mi))	_expandItem(tv, sim, mi);
	} 
}

void MainWindowImpl::collapseThisContentItems(){
	QTreeView *tv =  twTODO->currentWidget()->findChild<QTreeView *>("tvPkgFileList") ;
	if ( tv != 0 ){
		tv->repaint(tv->rect());
 		QCoreApplication::processEvents();
		QStandardItemModel *sim = qobject_cast<QStandardItemModel*>(tv->model());
		QModelIndex mi = tv->currentIndex();
		if (sim->hasChildren(mi))	_collapseItem(tv, sim, mi);
	} 
}

void MainWindowImpl::collapseAllContentItems(){
	QTreeView *tv =  twTODO->currentWidget()->findChild<QTreeView *>("tvPkgFileList") ;
	if ( tv != 0 ) tv->collapseAll();
}

void  MainWindowImpl::removeAbsoluteDir( QStandardItemModel *im, QModelIndex index ){
	if (index.isValid() == false) return;
	else if ( im->itemFromIndex(index)->hasChildren() ) {
		QStandardItem* si = im->itemFromIndex(index)->child(0, 0);
		removeAbsoluteDir(im, im->index(0, 0, si->index()));		
	}
	else{
		QStandardItem *item = im->itemFromIndex(index);
		QFileInfo fi( item->text() );
		if (fi.isDir()) item->setText( fi.path() );
	}
}

void MainWindowImpl::createDirectory(){
	QModelIndex index = tvDir->currentIndex();

	if (!index.isValid())
		return;

	QString dirName = QInputDialog::getText(this,
			tr("Create directory"),
			tr("Directory name"));

	if ((dirName != 0) && (dirName.length() > 0)) {
		if (!modelDir->mkdir(index, dirName).isValid())
			QMessageBox::information(this, tr("Create directory"),
					tr("Failed to create the directory"));
	}		
}

void MainWindowImpl::removeDirectory(){
	QModelIndex index = tvDir->currentIndex();

	if (!index.isValid()) return;

	bool ok;
	if (modelDir->fileInfo(index).isDir()) {
		int res;
		res = QMessageBox::question(this, tr("Confirmation"), 
				tr("Are you sure you want to remove this directory?"), 
				QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
		if (res == QMessageBox::Yes){
			ok = modelDir->rmdir(index);

			if (!ok)
				QMessageBox::information(this, tr("Remove"),
						tr("Failed to remove") + " " + (modelDir->fileName(index)));			    		
		}
	}	  
}

QList<QStandardItem*> reverse (const QList<QStandardItem*> &list)
{
	QList<QStandardItem*> tmp;
	if ( list.count() == 0 )
		return tmp;
	for ( QList<QStandardItem*>::ConstIterator it= list.begin();
	        it != list.end();
	        it++ )
		tmp.prepend ( *it );

	return tmp;
}

void MainWindowImpl::showPackagesInDirectory(){
	//if (g_Last_Selected_Directory == modelDir->filePath(tvDir->currentIndex())) return;
	changeDir();	

	QPointer<CPUIntensiveComputing> gRi;	
	if (!fsw.directories().isEmpty()) fsw.removePath( fsw.directories()[0] );
	if (tvDir->currentIndex().isValid()) fsw.addPath( modelDir->filePath(tvDir->currentIndex() ));
	modelPackage->clear();
	QDir d(modelDir->filePath(tvDir->currentIndex())); 				

	QStringList fl;
	QStringList list = d.entryList(fl << "*" + TGZ_PACKAGE_EXTENSION << "*" + RPM_PACKAGE_EXTENSION, 
		QDir::Files, QDir::Name); 
	if ( list.count() > 0 )	gRi = new CPUIntensiveComputing();		

	Package pck;
	pck.setTargetDir(d.absolutePath()); 			

	QList<QStandardItem*> items, icons;

	foreach (QString str, list) {
		Result res = pck.getStatus(str);
		QStandardItem *s;

		switch (res.getClassification()) { 
		case RPM:
			s = new QStandardItem(
					iconRPM, "_RPM");
			icons << s;
			s = new QStandardItem( str );	
			items << s; break;

		case FROZEN :
			s = new QStandardItem(
					iconFrozen, "_Frozen");
			icons << s;
			s = new QStandardItem( str );	
			items << s; break;

		case INTERNAL_ERROR : 
			s = new QStandardItem(
					iconInternalError, "_Error");
			icons << s;
			s = new QStandardItem( str );	
			items << s; break;

		case INFERIOR_VERSION : 
			s = new QStandardItem(
					iconInferior, "_Inferior");    			
			icons << s;
			s = new QStandardItem( str );    			
			items << s; break;

		case SUPERIOR_VERSION: 
			s = new QStandardItem(
					iconSuperior, "_Superior");
			icons << s;
			s = new QStandardItem( str );    						
			items << s; break;

		case OTHER_VERSION:
			s = new QStandardItem(
					iconOtherVersion, "_OtherVersion");
			icons << s;
			s = new QStandardItem( str );    						
			items << s; break;

		case INSTALLED : 
			s = new QStandardItem(
					iconInstalled, "_Installed");
			icons << s;
			s = new QStandardItem( str );    						
			items << s; break;

		case NOT_INSTALLED : 
			s = new QStandardItem(
					iconNotInstalled, "_Not installed");
			icons << s;
			s = new QStandardItem( str );    						
			items << s; break; 

		default: 
			s = new QStandardItem(
					iconInternalError, "_Error");
			icons << s;
			s = new QStandardItem( str );    						
			items << s;	    	
		}    	
	}
	
	modelPackage->appendColumn(icons); 
	modelPackage->appendColumn(items); 
	modelPackage->sort(1);
	modelPackage->setHorizontalHeaderLabels(QStringList() << "" << tr("Name"));

	QString msg;
	if (items.size()>=1){
		if (items.size()>1) dockPackages->setWindowTitle(tr("%1 Packages in Directory").arg(
				QString::number(items.size())));
		else dockPackages->setWindowTitle(tr("%1 Package in Directory").arg(QString::number(items.size())));  	
	}
	else dockPackages->setWindowTitle(LABEL_LISTVIEW_PACKAGES);

	tvPackage->setColumnWidth(0, 24);	
	tvPackage->header()->setSortIndicator( m_PackageListOrderedCol, m_PackageListSortOrder );	
	tvPackage->sortByColumn( m_PackageListOrderedCol, m_PackageListSortOrder );

	tvPackage->header()->setMovable(false);
	//tvPackage->header()->setDefaultAlignment( Qt::AlignCenter );
	tvPackage->header()->setResizeMode( QHeaderView::Fixed );
	reapplyPackageFilter();

	if (modelPackage->rowCount() > 0) {
		QModelIndex mi = proxyModelPackage->index(0, 0);
		//mi = proxyModelInstalledPackages->mapToSource(mi);
		//QModelIndex maux = proxyModelPackage->index( mi.row(), PACKAGE_ICON );		
		//tvPackage->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::Select);
		//tvPackage->selectionModel()->setCurrentIndex(maux, QItemSelectionModel::Select);
		tvPackage->setCurrentIndex(mi);

		tvPackage->scrollTo(mi);
		selectInstalledPackage();    
		tvPackage->setFocus();
	}		
	
	g_Last_Selected_Directory = leDir->text();
	if (gRi) delete gRi;
}

void MainWindowImpl::selectInstalledPackage(){
	if (modelPackage->rowCount() == 0) return;

	QDir d(modelDir->filePath(tvDir->currentIndex())); 				
	d.setFilter(QDir::Files);	
	Package pck;
	pck.setTargetDir(d.absolutePath()); 					
	QModelIndex mi;

	QList<SelectedPackage> lt = getSelectedPackage();
	if (lt.count() == 0){
		QModelIndex mi = proxyModelInstalledPackages->index(0, 0);
		tvInstalledPackages->selectionModel()->clear();
		tvInstalledPackages->scrollTo(mi, QAbstractItemView::PositionAtCenter);
	} 

	else if (lt.count() == 1) tvInstalledPackages->selectionModel()->clear(); 
	
	foreach( SelectedPackage sp, lt ){
		Result res = pck.getStatus(sp.getFileName()); 

		if (res.getInstalledPackage().size() > 0){
			QList<QStandardItem*> l = 
				modelInstalledPackages->findItems( res.getInstalledPackage(), Qt::MatchStartsWith, PACKAGE_NAME );

			if (l.count() > 0){
				QStandardItem* aux = l[0];

				mi = 	aux->index();
				mi = proxyModelInstalledPackages->mapFromSource(mi);
				if (!proxyModelInstalledPackages->hasIndex(mi.row(), mi.column())) return;
			}
			else mi = proxyModelInstalledPackages->index(0, 0);

			tvInstalledPackages->scrollTo(mi, QAbstractItemView::PositionAtCenter);		
			QModelIndex maux = proxyModelInstalledPackages->index(mi.row(), 0);
			tvInstalledPackages->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::Select);
			tvInstalledPackages->selectionModel()->setCurrentIndex(maux, QItemSelectionModel::Select);

		}
		else if (res.getInstalledPackage().size() == 0){
			QModelIndex mi = proxyModelInstalledPackages->index(0, 0);
			tvInstalledPackages->selectionModel()->clear();
			tvInstalledPackages->scrollTo(mi, QAbstractItemView::PositionAtCenter);
		} 
	}
}

void MainWindowImpl::positionInInstalledPkgList( const QString& pkg ){
	tvInstalledPackages->setFocus();
	tvInstalledPackages->selectionModel()->clear();	

	QList<QStandardItem*> l = modelInstalledPackages->findItems( pkg, Qt::MatchStartsWith, PACKAGE_NAME );

	QStandardItem* aux;
	QModelIndex mi;

	if (l.count() > 0){
		aux = l[0];
		mi = 	aux->index();
		mi = proxyModelInstalledPackages->mapFromSource(mi);
		if (!proxyModelInstalledPackages->hasIndex(mi.row(), mi.column())) return;
	}
	else return; //mi = proxyModelInstalledPackages->index(0, 0);

	tvInstalledPackages->scrollTo(mi, QAbstractItemView::PositionAtCenter);		
	QModelIndex maux = proxyModelInstalledPackages->index(mi.row(), 0);
	tvInstalledPackages->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::Select);
	tvInstalledPackages->selectionModel()->setCurrentIndex(maux, QItemSelectionModel::Select);
}

QList<SelectedPackage> MainWindowImpl::getSelectedPackage(){
	QList<SelectedPackage> lsp;
	QDir d(modelDir->filePath(tvDir->currentIndex())); 				
	d.setFilter(QDir::Files);	
	QList<QIcon> licons;
	int c=0;

	foreach(QModelIndex item, tvPackage->selectionModel()->selectedRows(PACKAGE_ICON)){
		QModelIndex mi = proxyModelPackage->mapToSource(item);	
		QStandardItem *si = modelPackage->item( mi.row(), PACKAGE_ICON );
		if (si != 0) 
			licons << si->icon();
	}

	foreach(QModelIndex item, tvPackage->selectionModel()->selectedRows(PACKAGE_NAME)){
		QModelIndex mi = proxyModelPackage->mapToSource(item);	
		QStandardItem *si = modelPackage->item( mi.row(), PACKAGE_NAME );
		if (si != 0){ 
			lsp << SelectedPackage(d.absolutePath(), si->text(), licons[c]);
			c++;
		}
	}

	return lsp;		
}

QList<SelectedPackage> MainWindowImpl::getSelectedInstalledPackage(){
	QList<SelectedPackage> lsp;
	foreach(QModelIndex item, tvInstalledPackages->selectionModel()->selectedIndexes()){
		if ( item.column() == PACKAGE_NAME ){    
			lsp << SelectedPackage(PACKAGES_DIR, proxyModelInstalledPackages->data(item, 0).toString());
		}
	}

	return lsp;	
}

void MainWindowImpl::showPackageInfo(){
	tvPackage->repaint(tvPackage->rect());
	QCoreApplication::processEvents();	

	QList<SelectedPackage> lsp = getSelectedPackage();
	if (lsp.count() > 1) return;
	foreach(SelectedPackage sp, lsp){       	
		if ( sp.getIcon().serialNumber() == iconRPM.serialNumber() ) continue;

		CPUIntensiveComputing *ri = new CPUIntensiveComputing();
		QString sb = Package::getInformation(sp.getCompleteFileName(), false);
		delete ri;
		if ((sb != 0) && (sb.size() > 0)) QMessageBox::information(this, tr("Package %1 info").arg(sp.getFileName()),  sb);
		else QMessageBox::critical(this, tr("Package %1 info").arg(sp.getFileName()), tr("Sorry, no info provided!"));    
	}
}

void MainWindowImpl::showInstalledPackageInfo(){
	tvInstalledPackages->repaint(tvInstalledPackages->rect());
	QCoreApplication::processEvents();	

	QList<SelectedPackage> lsp = getSelectedInstalledPackage();

	foreach(SelectedPackage sp, lsp){
		CPUIntensiveComputing *ri = new CPUIntensiveComputing();
		QString sb = Package::getInformation(sp.getCompleteFileName(), true);
		delete ri;
		if ((sb != 0) && (sb.size() > 0)){
			//sb.replace("\n", " ");
			QMessageBox::information(this, tr("Package %1 info").arg(sp.getFileName()), "<html>" + sb + "</html>");
		}
		else QMessageBox::critical(this, tr("Package %1 info").arg(sp.getFileName()), tr("Sorry, no info provided!"));    
	}
}

void MainWindowImpl::execPackageContent(){
	CPUIntensiveComputing ri;
	QStringList res = m_fw->result();	

	QString package = res[0];
	res.removeAt(0);
	if ( !res.isEmpty() ) 
		createTabPkgFileList(package, res);  
	else{
		ri.restoreDefaultCursor();
		QMessageBox::critical(this, tr("Package %1").arg(package), tr("This package seems corrupted!"));	
	}
}

QStringList _showPackageContent(const QString& fileName, const QString& completeFileName, bool b){
	QStringList sl;
	sl << fileName << Package::getContents(completeFileName, b);
	return sl;
}

void MainWindowImpl::showPackageContent(){
	tvPackage->repaint(tvPackage->rect());
	QCoreApplication::processEvents();	
	QFuture<QStringList> f;
	bool alreadyExists=false;

	if (tvInstalledPackages->hasFocus()){
		foreach( SelectedPackage sp, getSelectedInstalledPackage() ){  			
			alreadyExists = false;

			//First we check if there's not a tab opened with this pkgName contents
			for (int c=2; c<twTODO->count(); c++)
				if (twTODO->tabText(c) == ("&" + sp.getFileName())){
					twTODO->setCurrentIndex ( c );			
					alreadyExists = true;
					break;
				} 
			if (alreadyExists) continue;

			QString pkg(sp.getCompleteFileName());			
			f = run(_showPackageContent, sp.getFileName(), pkg, true);
			m_fw->setFuture(f);
			//connect(m_fw, SIGNAL(finished()), this, SLOT(execPackageContent()));
			m_fw->waitForFinished();
			QCoreApplication::processEvents();	
			execPackageContent();
		}
	}
	else{
		foreach( SelectedPackage sp, getSelectedPackage() ){  			
			alreadyExists = false;

			//First we check if there's not a tab opened with this pkgName contents
			for (int c=2; c<twTODO->count(); c++)
				if (twTODO->tabText(c) == ("&" + sp.getFileName())){
					twTODO->setCurrentIndex ( c );			
					alreadyExists = true;
					break;
				} 
			if (alreadyExists) continue;

			QString pkg(sp.getCompleteFileName());
			f = run(_showPackageContent, sp.getFileName(), pkg, false);
			m_fw->setFuture(f);
			//connect(m_fw, SIGNAL(finished()), this, SLOT(execPackageContent()));
			m_fw->waitForFinished();
			QCoreApplication::processEvents();
			execPackageContent();
		}			
	}
}

void MainWindowImpl::executePackageActions(){ 
	QFile ftemp(TEMP_ACTIONS_FILE);
	ftemp.open(QIODevice::ReadWrite|QIODevice::Text);
	ftemp.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner|
			QFile::ReadUser|QFile::WriteUser|QFile::ExeUser);
	QTextStream out(&ftemp);

	QStringList s;
	bool rootUser = (QDir::homePath() == "/root");

	if (!rootUser){
		s << "-d";
		s << "-t";
		s << "--noignorebutton";
	}
	else s << "-c";

	for (int r=0; r<remove->rowCount(); r++){    
		out << "removepkg " << remove->child(r)->text() << "\n";
	}
	for (int r=0; r<downgrade->rowCount(); r++){    
		out << "upgradepkg " << downgrade->child(r)->text() << "\n";
	}
	for (int r=0; r<upgrade->rowCount(); r++){    
		out << "upgradepkg " << upgrade->child(r)->text() << "\n";
	}
	for (int r=0; r<install->rowCount(); r++){    
		out << "installpkg " << install->child(r)->text() << "\n";
	}
	for (int r=0; r<reinstall->rowCount(); r++){    
		out << "upgradepkg --reinstall " << reinstall->child(r)->text() << "\n";
	}

	out.flush();
	ftemp.close();
	s << TEMP_ACTIONS_FILE;
	textEdit->clear();
	textEdit->setHtml("");

	echo = new QProcess(this);  
	connect(echo, SIGNAL( started() ), this, SLOT( ACTIONSprocessStarted() ));
	connect(echo, SIGNAL( readyReadStandardOutput() ), this, SLOT( ACTIONSprocessReadOutput() ));
	connect(echo, SIGNAL( finished ( int, QProcess::ExitStatus )),
			this, SLOT(ACTIONSprocessFinished(int, QProcess::ExitStatus)));
	connect(echo, SIGNAL( readyReadStandardError() ), this, SLOT(ACTIONSprocessRaisedError()));
	//connect(echo, SIGNAL( error ( QProcess::ProcessError )),
	//  this, SLOT(processRaisedError( QProcess::ProcessError )));
	if (rootUser) echo->start("/bin/sh", s); 
	else echo->start("kdesu", s);
}

void MainWindowImpl::ACTIONSprocessRaisedError(){
	twTODO->setCurrentIndex(1);
	QString msg;
	msg = tr("<br><h4>It seems an error has ocorred...</h4>"
			"For more information about QTGZManager visit: %1").
			arg("<a href=\"http://jtgzmanager.sf.net\">http://jtgzmanager.sf.net</a><br><br>");	

	textEdit->insertHtml("<pre>" + echo->readAllStandardError() + "</pre>");  
	textEdit->insertHtml(msg);
	textEdit->ensureCursorVisible();
}

void MainWindowImpl::ACTIONSprocessStarted(){
	twTODO->setCurrentIndex(1);
	QString msg;
	textEdit->clear();
	actionExecuteActions->setEnabled( false );
	msg = tr("<h4>Please, wait while the actions are being executed...</h4><br>");
	textEdit->insertHtml(msg);
}

void MainWindowImpl::ACTIONSprocessFinished(int, QProcess::ExitStatus){
	twTODO->setCurrentIndex(1);
	QString msg;
	lblStatus->setText("");	

	if (textEdit->toHtml().indexOf("<pre style") != -1){
		install->removeRows(0, install->rowCount());
		remove->removeRows(0, remove->rowCount());
		downgrade->removeRows(0, downgrade->rowCount());
		upgrade->removeRows(0, upgrade->rowCount());
		reinstall->removeRows(0, reinstall->rowCount());
		delete modelInstalledPackages;
		delete proxyModelInstalledPackages;
		initializeInstalledPackagesListView();  

		msg = tr("<br><h4>Finished executing package actions!</h4>"
				"For more information about QTGZManager visit: %1").
				arg("<a href=\"http://jtgzmanager.sf.net\" target=\"_blank\">http://jtgzmanager.sf.net</a>");		
	}
	else{
		msg = tr("<br><h4>Package actions's execution were cancelled!</h4>"
				"For more information about QTGZManager visit: %1").
				arg("<a href=\"http://jtgzmanager.sf.net\" target=\"_blank\">http://jtgzmanager.sf.net</a>");	
		actionExecuteActions->setEnabled( true );
	}
	
	reapplyInstalledPackagesFilter();	
	textEdit->insertHtml(msg);
	textEdit->ensureCursorVisible();
	delete echo;
	QFile::remove(TEMP_ACTIONS_FILE);
}

void MainWindowImpl::ACTIONSprocessReadOutput(){
	twTODO->setCurrentIndex(1);
	textEdit->insertHtml("<pre>" + echo->readAllStandardOutput() + "</pre>");  
	textEdit->ensureCursorVisible();
}

void MainWindowImpl::TGZ2LZMprocessReadOutput(){
	twTODO->setCurrentIndex(1);
	textEdit->insertHtml("<pre>" + tgz2lzm->readAllStandardOutput() + "</pre>");  
	textEdit->ensureCursorVisible();
}

void MainWindowImpl::RPM2TGZprocessReadOutput(){
	twTODO->setCurrentIndex(1);
	textEdit->insertHtml("<pre>" + rpm2tgz->readAllStandardOutput() + "</pre>");  
	textEdit->ensureCursorVisible();
}

void MainWindowImpl::TGZ2LZMprocessStarted(){
	twTODO->setCurrentIndex(1);
	QString msg;
	textEdit->clear();
	actionExecuteActions->setEnabled( false );
	msg = tr("<h4>Please, wait while the TGZ to LZM convertion is being executed...</h4><br>");
	textEdit->insertHtml(msg);
}

void MainWindowImpl::RPM2TGZprocessStarted(){
	twTODO->setCurrentIndex(1);
	QString msg;
	textEdit->clear();
	actionExecuteActions->setEnabled( false );
	msg = tr("<h4>Please, wait while the RPM to TGZ convertion is being executed...</h4><br>");
	textEdit->insertHtml(msg);
}

void MainWindowImpl::TGZ2LZMprocessFinished(int, QProcess::ExitStatus){
	twTODO->setCurrentIndex(1);
	QString msg;		
	lblStatus->setText("");	

	if (textEdit->toHtml().indexOf("<pre style") != -1){
		msg = tr("<br><h4>Finished executing TGZ to LZM convertion!</h4>"
				"For more information about QTGZManager visit: %1").
				arg("<a href=\"http://jtgzmanager.sf.net\" target=\"_blank\">http://jtgzmanager.sf.net</a>");
	}
	else{
		msg = tr("<br><h4>TGZ to LZM convertion was cancelled!</h4>"
				"For more information about QTGZManager visit: %1").
				arg("<a href=\"http://jtgzmanager.sf.net\" target=\"_blank\">http://jtgzmanager.sf.net</a>");		
	}

	textEdit->insertHtml(msg);
	textEdit->ensureCursorVisible();
	delete tgz2lzm;
	QFile::remove(TEMP_ACTIONS_FILE);
}

void MainWindowImpl::RPM2TGZprocessFinished(int, QProcess::ExitStatus){
	twTODO->setCurrentIndex(1);
	QString msg;		
	lblStatus->setText("");	
	msg = tr("<br><h4>Finished executing RPM to TGZ convertion!</h4>"
			"For more information about QTGZManager visit: %1").
			arg("<a href=\"http://jtgzmanager.sf.net\" target=\"_blank\">http://jtgzmanager.sf.net</a>");		
	textEdit->insertHtml(msg);
	textEdit->ensureCursorVisible();
	delete rpm2tgz;
	QFile::remove(TEMP_ACTIONS_FILE);
}

void MainWindowImpl::TGZ2LZMprocessRaisedError(){
	twTODO->setCurrentIndex(1);
	textEdit->insertHtml("<pre>" + tgz2lzm->readAllStandardError() + "</pre><br><br>");  
	textEdit->ensureCursorVisible();
}

void MainWindowImpl::RPM2TGZprocessRaisedError(){
	twTODO->setCurrentIndex(1);
	QString msg;
	msg = tr("<br><h4>It seems an error has ocorred...</h4>"
			"For more information about QTGZManager visit: %1").
			arg("<a href=\"http://jtgzmanager.sf.net\">http://jtgzmanager.sf.net</a><br><br>");	
	textEdit->insertHtml("<pre>" + rpm2tgz->readAllStandardError() + "</pre>");  
	textEdit->insertHtml(msg);
	textEdit->ensureCursorVisible();
}

void MainWindowImpl::reapplyPackageFilter(){
	QRegExp regExp(leFilterPackage->text(), Qt::CaseInsensitive, QRegExp::FixedString);
	proxyModelPackage->setFilterRegExp(regExp);  
	int numPkgs = proxyModelPackage->rowCount();

	if (leFilterPackage->text() != ""){
		if (numPkgs > 0) leFilterPackage->setStyleSheet(filterPackageFoundStyleSheet());
		else leFilterPackage->setStyleSheet(filterPackageNotFoundStyleSheet());
	}
	else{
		leFilterPackage->setStyleSheet("");
	}

	if (numPkgs > 1)
		dockPackages->setWindowTitle(tr("%1 Packages in Directory").arg(QString::number(numPkgs)));
	else if (numPkgs == 1)
		dockPackages->setWindowTitle(tr("1 Package in Directory"));
	else
		dockPackages->setWindowTitle(tr("0 Packages in Directory"));

	tvPackage->selectionModel()->clear();
	QModelIndex mi = proxyModelPackage->index(0, 0);
	tvPackage->setCurrentIndex(mi);
	tvPackage->scrollTo(mi);
	selectInstalledPackage();
}

void MainWindowImpl::reapplyInstalledPackagesFilter(){
	QRegExp regExp(leFilterInstalledPackages->text(), Qt::CaseInsensitive, QRegExp::FixedString);
	proxyModelInstalledPackages->setFilterRegExp(regExp);  
	int numInstPkgs = proxyModelInstalledPackages->rowCount();

	if (leFilterInstalledPackages->text() != ""){
		if (numInstPkgs > 0) leFilterInstalledPackages->setStyleSheet(filterPackageFoundStyleSheet());
		else leFilterInstalledPackages->setStyleSheet(filterPackageNotFoundStyleSheet());
	}
	else{
		leFilterInstalledPackages->setStyleSheet("");
	}

	if (numInstPkgs > 1)
		dockInstalledPackages->setWindowTitle(tr("%1 Installed Packages").arg(QString::number(numInstPkgs)));
	else if (numInstPkgs == 1)
		dockInstalledPackages->setWindowTitle(tr("1 Installed Package"));
	else
		dockInstalledPackages->setWindowTitle(tr("No Installed Package found!"));

	tvInstalledPackages->selectionModel()->clear();
	QModelIndex mi = proxyModelInstalledPackages->index(0, 1);			
	tvInstalledPackages->scrollTo(mi, QAbstractItemView::PositionAtCenter);		
	QModelIndex maux = proxyModelInstalledPackages->index(0, 0);
	tvInstalledPackages->selectionModel()->setCurrentIndex(maux, QItemSelectionModel::Select);
	tvInstalledPackages->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::Select);	
}
