/*
* 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 <QtGui>
#include <QDebug>

#include "mainwindowimpl.h"
#include "package.h"

MainWindowImpl::MainWindowImpl( QWidget * parent, Qt::WFlags f) 
	:	QMainWindow(parent, f), 
		APPLICATION_NAME("QTGZManager - Beta3"),
		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")),
		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_reallyWannaClose = false;
	m_settings = new QSettings("QTGZManager", "QTGZManager");

	QVariant v = m_settings->value( KEY_FROZEN_PACKAGES_LIST, QVariant(QStringList()) );
	m_slFrozenPackages = v.toStringList();

	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 ???
  
  //Connect all signals with their slots
  connect(tvDir, SIGNAL(activated(const QModelIndex)), tvDir, SIGNAL(clicked(const QModelIndex)));
  connect(tvDir, SIGNAL(clicked(const QModelIndex)), this, SLOT(showPackagesInDirectory()));
  //connect(tvDir, SIGNAL(pressed(const QModelIndex)), tvDir, SIGNAL(clicked(const QModelIndex)));
   
	connect( lvPackage->header(), 
		SIGNAL( sectionClicked ( int )), 
		this, SLOT( headerViewPackageList_click( int ) ) );
	connect( lvInstalledPackages->header(), 
		SIGNAL( sectionClicked ( int )), 
		this, SLOT( headerViewInstalledPackageList_click( int ) ) );
 
  //connect(lvPackage, SIGNAL(activated(const QModelIndex)), lvPackage, SIGNAL(clicked(const QModelIndex)));
  connect(lvPackage, SIGNAL(clicked(const QModelIndex)), this, SLOT(selectInstalledPackage()));
  //connect(lvPackage, SIGNAL(pressed(const QModelIndex)), lvPackage, SIGNAL(clicked(const QModelIndex)));
  
  connect(tvDir, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(execContextMenuDirectories(QPoint)));
  connect(tvTODO, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(execContextMenutvTODO(QPoint)));
	connect(lvPackage, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(execContextMenuPackages(QPoint)));
  connect(lvInstalledPackages, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(execContextMenuInstalledPackages(QPoint)));

  QIcon icon(":/resources/images/QTGZManager.png");
  setWindowIcon(icon);    

	fsw.addPath( QDir::homePath() );
	connect ( &fsw, SIGNAL(directoryChanged ( const QString &)), this, 
		SLOT(fileSystemWatcher_directoryChanged ( const QString &) ));
  
  initializeActions();
  initializeToolBar();
	initializeDirTreeView();
  initializePackageListView();
  initializeInstalledPackagesListView();
  initializeTodoTreeView();
  
  showPackagesInDirectory();
	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 )));

	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 );
	connect( btnCloseTab, SIGNAL(clicked()), this, SLOT(closeCurrentTab()) );
	connect( twTODO, SIGNAL(currentChanged(int)), this, SLOT(enableCloseTabButton(int)) );
	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")));
	connect(actionAbout, SIGNAL(triggered()), this, SLOT(aboutQTGZManager()));
	actionAbout->setText( tr("About..."));

	systemTrayIconMenu->addAction( actionAbout );
	systemTrayIconMenu->addAction( actionExit );
	systemTrayIcon->setContextMenu( systemTrayIconMenu );

	connect ( systemTrayIcon , SIGNAL( activated( QSystemTrayIcon::ActivationReason ) ), 
		this, SLOT( execSystemTrayActivated ( QSystemTrayIcon::ActivationReason ) ) );
}

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

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());
			delete menu;
			m_clickedTab = -1;
		}
	}

	return false;	
}

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

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

void MainWindowImpl::headerViewInstalledPackageList_click( int  col ){
	m_InstalledPackageListOrderedCol = col;
	m_InstalledPackageListSortOrder = lvInstalledPackages->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) 
  		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) 
  		downgrade->appendRow(new QStandardItem(sp.getCompleteFileName()));				
	}

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

void MainWindowImpl::insertRemovePackageAction(){		
  if (lvPackage->hasFocus()){
    foreach(SelectedPackage sp, getSelectedPackage()){  
    	if ((modelTodo->findItems(sp.getCompleteFileName(), Qt::MatchRecursive).size()==0)) 
    		remove->appendRow(new QStandardItem(sp.getCompleteFileName()));
  	}
	}
  else if (lvInstalledPackages->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) 
	  	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) 
  		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(actionCreate_Directory);
 	menu.addAction(actionRemove_Directory);        		        		       		        		

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

void MainWindowImpl::diffAgainstEachOther(){
	CPUIntensiveComputing ri;
	SelectedPackage pkg1 = getSelectedPackage()[0];
	SelectedPackage pkg2 = getSelectedPackage()[1];

	QStringList sl = Package::getPackageContents(pkg1.getCompleteFileName());
	QStringList sl2 = Package::getPackageContents(pkg2.getCompleteFileName());

	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;

	//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(pkg1.getFileName(), pkg2.getFileName(), out);

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

void MainWindowImpl::diffAgainstInstalled(){
	SelectedPackage pkg = getSelectedPackage()[0];
	Package p;
	QDir d(modelDir->filePath(tvDir->currentIndex())); 				
	d.setFilter(QDir::Files);
	p.setTargetDir(d.absolutePath());
	Result res = p.verifyPackageInstallation(pkg.getFileName(), m_slFrozenPackages);	
	QStringList sl = Package::getPackageContents(PACKAGES_DIR + QDir::separator() + res.getInstalledPackage(), true);
	QStringList sl2 = Package::getPackageContents(pkg.getCompleteFileName());

	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 << "-y";
	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) || (lvPackage->selectionModel()->selectedRows().count()==0)) return;

  //QModelIndex mi = lvPackage->currentIndex();
 	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; 
			break;
		}
		lastType = ami.getIcon().serialNumber(); 
	}
	
	foreach(SelectedPackage ami, lsp){  
		if (ami.getIcon().serialNumber() == iconRPM.serialNumber()) 
		  rpmCount++;
		else tgzCount++;
	}

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

	if (allTGZ){
		menu->addAction(actionPackageContent);
		menu->addAction(actionPackageInfo); 	
	}
	else if (allRPM){
		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())){				
			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::getPackageBaseName(lsp[0].getFileName());
			QString s2 = Package::getPackageBaseName(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() == 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 = lvPackage->mapToGlobal(point);
	pt2.setY(pt2.y() + lvPackage->header()->height());
  menu->exec(pt2);        	
	delete menu;
}

void MainWindowImpl::transformTGZinLZM(){
	int tgzCount=0;
	QList<SelectedPackage> lsp = getSelectedPackage();	
	QProcess tgz2lzm;
	QStringList args;
 	
	bool rootUser = (QDir::homePath() == "/root");

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

	QString s;

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

	if ( tgzCount == lsp.count() ){
		CPUIntensiveComputing ri;

		foreach(SelectedPackage sp, lsp){  
			 s += " /bin/sh 2>&1 -c 'make-lzm " + sp.getCompleteFileName() + "';";
		}

		tgz2lzm.setWorkingDirectory( lsp[0].getPath() ); 
		args << s;
		if (!rootUser) tgz2lzm.start("kdesu", args);
		else tgz2lzm.start("/bin/sh", args);
		qApp->processEvents();
		tgz2lzm.waitForFinished();
	}
}

void MainWindowImpl::transformRPMinTGZ(){
	QList<SelectedPackage> lsp = getSelectedPackage();
	QProcess rpm2tgz;
	QStringList args;

	CPUIntensiveComputing ri;
	rpm2tgz.setWorkingDirectory( lsp[0].getPath() ); 

	foreach(SelectedPackage sp, lsp){
		args << sp.getCompleteFileName();
		rpm2tgz.start("rpm2tgz", args) ;
		qApp->processEvents();
		rpm2tgz.waitForFinished();
		args.clear();
	}
}

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

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

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

	bool allSameType = true;
	int lastType=-9999;

	foreach(QModelIndex item, lvInstalledPackages->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 = lvInstalledPackages->mapToGlobal(point);
  pt2.setY(pt2.y() + lvInstalledPackages->header()->height());
  menu->exec(pt2);        	
	delete menu;
}

void MainWindowImpl::execContextMenutvTODO(QPoint point){
	QModelIndex mi = tvTODO->currentIndex();
 	QMenu menu(this);               	

 	//Which actions do we have to put? It depends on package status
	if ( (( modelTodo->itemFromIndex ( mi ) == install )   ||
       ( modelTodo->itemFromIndex ( mi ) == remove )     ||
       ( modelTodo->itemFromIndex ( mi ) == downgrade )  ||
       ( modelTodo->itemFromIndex ( mi ) == upgrade ) ||
			 ( modelTodo->itemFromIndex ( mi ) == reinstall )) && (modelTodo->rowCount(mi) > 0)) {

	 	menu.addAction(actionDelete_All_ActionFiles);        		        		       		        		       		 
	}
	else if 
			(( modelTodo->itemFromIndex ( mi ) != install )    &&
       ( modelTodo->itemFromIndex ( mi ) != remove )     &&
       ( modelTodo->itemFromIndex ( mi ) != downgrade )  &&
       ( modelTodo->itemFromIndex ( mi ) != upgrade ) &&
			 ( modelTodo->itemFromIndex ( mi ) != reinstall )
			)
		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->show();
		 	this->restoreGeometry( savedGeometry );
		}
		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 ((lvPackage->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;

			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;
					//std::cout << "si has value: " << si->text().toAscii().data() << " and current is: " << 
					//	sp[sp.count()-1].getFileName().toAscii().data() << std::endl;	
				}
				if((a+1)<=fi.count()-1) { a++; i=a; }
				else { a=i=0; }	
			}
	
			lvPackage->selectionModel()->clear();
			lvPackage->scrollTo(fi[i]->index());
			QModelIndex maux = modelPackage->index( fi[i]->index().row(), PACKAGE_ICON );
			lvPackage->selectionModel()->setCurrentIndex(maux, QItemSelectionModel::Select);
			lvPackage->selectionModel()->setCurrentIndex(fi[i]->index(), QItemSelectionModel::Select);
			lvPackage->setCurrentIndex(fi[i]->index());
			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 ((lvInstalledPackages->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; 
			}

			lvInstalledPackages->selectionModel()->clear();
			QModelIndex mi = fi[i]->index();
			mi = proxyModelInstalledPackages->mapFromSource(mi);		
 			lvInstalledPackages->scrollTo(mi);		
			QModelIndex maux = proxyModelInstalledPackages->index(mi.row(), 0);
			lvInstalledPackages->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::Select);
			lvInstalledPackages->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) && (lvPackage->hasFocus() && (ke->key() == Qt::Key_Down|Qt::Key_Up|Qt::Key_PageDown|Qt::Key_PageUp))) {
		lvPackage->scrollTo(lvPackage->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) && (lvPackage->hasFocus()))) {
		lvPackage->scrollTo(lvPackage->currentIndex());
		selectInstalledPackage();
	}
	else {
		QTreeView *t = twTODO->currentWidget()->findChild<QTreeView*>("tvPkgFileList");
		if ( (t != 0)  && (t->hasFocus())) {
			t->scrollTo( t->currentIndex() );
			showFullPathOfObject( t->currentIndex() );
		}
	}

	if ( ((ke->key() == Qt::Key_L) && (ke->modifiers() == Qt::ControlModifier)) ){ 
		transformTGZinLZM();
	}	

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

	else if ((ke->key() == Qt::Key_Delete) && (tvTODO->hasFocus())){
    QModelIndex mi = tvTODO->currentIndex();
    if ((modelTodo->itemFromIndex(mi) == install)    ||
        (modelTodo->itemFromIndex(mi) == remove)     ||
        (modelTodo->itemFromIndex(mi) == downgrade)  ||
        (modelTodo->itemFromIndex(mi) == upgrade)) return;          

		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());     
  }

  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){
		//twTODO->setCurrentIndex(0);
		enableCloseTabButton(-1);	
	}
}

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

	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::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->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"));
	connect(actionTransformRPMinTGZ, SIGNAL(triggered()), this, SLOT(transformRPMinTGZ()));

	connect(actionFreezePkg, SIGNAL(triggered()), this, SLOT(freezePackage()));
	connect(actionUnfreezePkg, SIGNAL(triggered()), this, SLOT(unfreezePackage()));

	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"));
	
	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 externally"), this);
	actionOpenDirectory = new QAction(QIcon(":/resources/images/folder.png"), tr("Open directory externally"), this);

	actionMaximizeLowerView->setIcon(QIcon(":/resources/images/verticalView.png"));
	actionHideRightView->setIcon(QIcon(":/resources/images/horizontalView.png"));
	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 );
	actionHideRightView->setCheckable( true );
	actionMaximizeLowerView->setChecked( false );
	actionHideRightView->setChecked( false );

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

	connect(actionFindFile, SIGNAL(triggered()), this, SLOT(findFile()));

	connect(actionOpenFile, SIGNAL(triggered()), this, SLOT(openFile()));
	connect(actionOpenDirectory, SIGNAL(triggered()), this, SLOT(openDirectory()));

	connect(actionRefreshPackageLists, SIGNAL(triggered()), this, SLOT(refreshTreeViews()));
	connect(actionMaximizeLowerView, SIGNAL(triggered()), this, SLOT(maximizeLowerView()));
	connect(actionHideRightView, SIGNAL(triggered()), this, SLOT(hideRightView()));
	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()));

	actionExecuteActions->setEnabled( false );
}

void MainWindowImpl::refreshTreeViews(){
	modelDir->refresh();
	showPackagesInDirectory();
}

void MainWindowImpl::initializeToolBar(){
 	toolBar->setToolButtonStyle ( Qt::ToolButtonIconOnly ) ;
	toolBar->addAction(actionHideRightView);
 	toolBar->addAction(actionMaximizeLowerView);
  toolBar->addSeparator();
	toolBar->addAction(actionRefreshPackageLists);
	toolBar->addAction(actionFindFile);
	toolBar->addAction(actionExecuteActions);
  toolBar->addSeparator();
  toolBar->addAction(actionAbout_QTGZManager);
	toolBar->addAction(actionExit);
}

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

void MainWindowImpl::freezePackage(){
	int bkSize = m_slFrozenPackages.count();
	foreach(QModelIndex item, lvInstalledPackages->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 ){    		
			m_slFrozenPackages << Package::getPackageBaseName( proxyModelInstalledPackages->data(item).toString());
		}
	}
	
	//Now we must reconstruct the list of frozen packages in order to save it to the QSettings.
	m_settings->setValue( KEY_FROZEN_PACKAGES_LIST, QVariant( m_slFrozenPackages ) );
	if ( (modelPackage->rowCount()>0) && (bkSize != m_slFrozenPackages.count()) ) showPackagesInDirectory();

	refreshInstalledPackageListView();
}

void MainWindowImpl::unfreezePackage(){
	int bkSize = m_slFrozenPackages.count();
	foreach(QModelIndex item, lvInstalledPackages->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 ){    		
			m_slFrozenPackages.removeAll( Package::getPackageBaseName(proxyModelInstalledPackages->data(item).toString() ));
		}
	}

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

	refreshInstalledPackageListView();
}

void MainWindowImpl::aboutQTGZManager(){	
	QString about;
	about = tr("<strong>QTGZManager</strong> is a GUI for the Slackware <cite>pkgtools</cite>, licensed under the terms of %1<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></ul>"					
					"<br><br>I'd like to <strong>thank</strong>:"
					"<ul><li>Andrea Sciucca - for feedback and italian translation.</li>"
					"<li>Manfred Mueller - for feedback and german translation.</li></ul>"
					"<br><br>For more information visit %2 <br><br>"
					"Alexandre Albuquerque Arnt - Main Developer<br>")
					.arg("<a href=\"http://www.gnu.org/licenses/gpl-2.0.html\">GPL v2</a>")
					.arg("<a href=\"http://jtgzmanager.sf.net\">http://jtgzmanager.sf.net</a>");
	
	QMessageBox::about( this, tr("About %1").arg(APPLICATION_NAME), about);
}

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();
	}
	else if ( f.exists( lblStatus->text() ) ) {
		openFile();
	}
}

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

void MainWindowImpl::openFile(){
	QProcess *p = new QProcess(this);
  QStringList s;

	s << lblStatus->text();
	p->start( "file", s );
	p->waitForFinished();
	int a = p->readAllStandardOutput().indexOf( "ASCII", 0 );

	if (a == -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::Yes ) goto lExec;
	}
	else{
		lExec:
		s.clear();
		s << "exec";
		s << "file:" + lblStatus->text(); 
	
		p->start( "kfmclient" , s );
		p->waitForFinished();
	}

	delete p;
}

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

	s << "newTab";
	
	if ((lvPackage->hasFocus()) || (tvDir->hasFocus())) s << modelDir->filePath(tvDir->currentIndex());
	else if (lblStatus->text() != "") s << lblStatus->text(); 

	p->start( "kfmclient" , s );
	p->waitForFinished();
	delete p;
}

void MainWindowImpl::deleteFile(){
	QDir d(modelDir->filePath(tvDir->currentIndex())); 				
	d.setFilter(QDir::Files);		
	
	QModelIndexList lmi = lvPackage->selectionModel()->selectedIndexes();		
	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 (QModelIndex mi, lmi){
			QString fileToDelete = d.absolutePath() + QDir::separator() + 
				modelPackage->itemFromIndex(mi)->text();
			
			//QMessageBox.information(this, "texto", fileToDelete);
			QFile::remove(fileToDelete);			
		}			
	
		showPackagesInDirectory();				
	}
}

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 wainting 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();

	tvDir->setModel(modelDir);
  tvDir->setColumnHidden(1, true);
  tvDir->setColumnHidden(2, true);
  tvDir->setColumnHidden(3, true);
  tvDir->setFont(QFont("Verdana", 12));
	tvDir->header()->hide();

	tvDir->setStyleSheet( treeViewStyleSheet()	);

  tvDir->setAcceptDrops(true);
  tvDir->setDropIndicatorShown(true);
  
  QModelIndex index = modelDir->index(QDir::homePath());
  tvDir->expand(index);
  tvDir->scrollTo(index);

  tvDir->resizeColumnToContents(0);
  tvDir->setCurrentIndex(index);
}

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(){
 	modelPackage = new QDnDStandardItemModel();

	lvPackage->setModel(modelPackage);
	lvPackage->setFont(QFont("Verdana", 12));		
	lvPackage->setEditTriggers(QAbstractItemView::NoEditTriggers);
	lvPackage->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);		
	//lvPackage->setSelectionBehavior(QAbstractItemView::SelectItems);
	lvPackage->setAllColumnsShowFocus( true );

	lvPackage->setSortingEnabled( true );
	lvPackage->setIndentation( 0 );
	lvPackage->header()->setSortIndicatorShown(true);
	lvPackage->header()->setClickable(true);
	lvPackage->header()->setMovable(false);
	lvPackage->header()->setDefaultAlignment( Qt::AlignCenter );
	lvPackage->header()->setResizeMode( QHeaderView::Fixed );

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

	lvPackage->sortByColumn( 1, Qt::AscendingOrder);
}

void MainWindowImpl::initializeInstalledPackagesListView(){		
	proxyModelInstalledPackages = new QSortFilterProxyModel();
	modelInstalledPackages = new QStandardItemModel();
  proxyModelInstalledPackages->setSourceModel(modelInstalledPackages);
  proxyModelInstalledPackages->setFilterKeyColumn(1);
	
	QDir d(PACKAGES_DIR); 				
	d.setFilter(QDir::Files);		
	QStringList list = d.entryList();

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

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

			//QStandardItem* si = new QStandardItem( s );
			//SelectedPackage sp( PACKAGES_DIR, s );
			//si->setToolTip( Package::getInfoPackage( sp, true ) );
			lNames << new QStandardItem( s ); //si;
		}
	}

	parentItem->appendColumn( lIcons );
	parentItem->appendColumn( lNames );

	QStringList sl;
	modelInstalledPackages->setHorizontalHeaderLabels(sl << "" << tr("Name"));
	
	lvInstalledPackages->setFont(QFont("Verdana", 12));		
	lvInstalledPackages->setEditTriggers(QAbstractItemView::NoEditTriggers);
	lvInstalledPackages->setSelectionMode(QAbstractItemView::ExtendedSelection);
	lvInstalledPackages->setModel(proxyModelInstalledPackages);			
	lvInstalledPackages->setIndentation( 0 );

	lvInstalledPackages->setSortingEnabled( true );
	lvInstalledPackages->setAllColumnsShowFocus( true );
	lvInstalledPackages->header()->setSortIndicatorShown(true);
	lvInstalledPackages->header()->setClickable(true);
	lvInstalledPackages->header()->setMovable(false);
	lvInstalledPackages->header()->setDefaultAlignment( Qt::AlignCenter );
	lvInstalledPackages->header()->setResizeMode( QHeaderView::Fixed );
	lvInstalledPackages->sortByColumn( 1, Qt::AscendingOrder);
	lvInstalledPackages->header()->setDefaultAlignment( Qt::AlignCenter );

  dockInstalledPackages->setWindowTitle(tr("%1 Installed Packages").arg(QString::number(list.size())));
	//modelInstalledPackages->setHeaderData( 0, Qt::Horizontal, tr("Name" ));	
  
  connect(leFilter, SIGNAL(textChanged (const QString&)), this, SLOT(reapplyFilter()));  
	lvInstalledPackages->setColumnWidth(0, 24);	
	lvInstalledPackages->header()->setSortIndicator( m_InstalledPackageListOrderedCol, m_InstalledPackageListSortOrder );	
	lvInstalledPackages->sortByColumn( m_InstalledPackageListOrderedCol, m_InstalledPackageListSortOrder );
}

void MainWindowImpl::initializeTodoTreeView(){
	modelTodo = new QDnDStandardItemModel();
	
	//modelTodo->sort(0);
	QFont f("Verdana", 11);
	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);			

  QStringList a;
	modelTodo->setHorizontalHeaderLabels(a << 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=\"linen\"><tr><th colspan=\"2\"><h2>Diff against %1</h2></th></tr>").arg(installedPkg);
	html += "<tr bgcolor=\"moccasin\"><td><font color=\"maroon\"><h3>" + pkg + "</h3></td><td><font color=\"maroon\"><h3>" + installedPkg + "</h3></td></tr>";

	//We must first parse this diff content to produce human-redable 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=\"red\">" + 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 );
}

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();
	QStandardItemModel *fakeModelPkgFileList = new QStandardItemModel();
  QTreeView *tvPkgFileList = new QTreeView(tabPkgFileList);
  QFont f("Verdana", 11);
  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 );
  QStringList a;
	modelPkgFileList->setHorizontalHeaderLabels( a << 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);
			//std::cout << "diretorio: " << s.toAscii().data() <<std::endl;
			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)));

	//tvPkgFileList->expandAll();
}

void MainWindowImpl::showFullPathOfObject( const QModelIndex & index ){
	if (!index.isValid()) return;
	
	const QStandardItemModel *sim = static_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;
	if ( ( si->icon().serialNumber() == iconFolder.serialNumber() ) && ( d.exists( lblStatus->text() )) ) {
		menu.addAction( actionOpenDirectory );	
	}
	else if ( f.exists( lblStatus->text() ) ) {
		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->expandAll();
}

void MainWindowImpl::_expandItem(QTreeView* tv, QStandardItemModel* sim, QModelIndex mi){
	for (int i=0; i<sim->rowCount(mi); i++){
		if (sim->hasChildren(mi)){			
				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)){			
				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 ){
		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 ){
		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)));			    		
    }
  }	  
}

void MainWindowImpl::showPackagesInDirectory(){
	QPointer<CPUIntensiveComputing> gRi;
	
	reapplyFilter();

	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())); 				
	d.setFilter(QDir::Files);

  QStringList fl;
  QStringList list = d.entryList(fl << "*" + TGZ_PACKAGE_EXTENSION << "*" + RPM_PACKAGE_EXTENSION);
	if ( list.count() > 0 )	gRi = new CPUIntensiveComputing();		
  
	Package pck;
	pck.setTargetDir(d.absolutePath()); 			
	
	QList<QStandardItem*> itens, icons;

  foreach (QString str, list) {
  	
  	Result res = pck.verifyPackageInstallation(str, m_slFrozenPackages);
  	QStandardItem *s;
  	
  	switch (res.getClassification()) { 
			case RPM:
  			s = new QStandardItem(
   				iconRPM, "_RPM");
				icons << s;
				s = new QStandardItem( str );	
				itens << s; break;

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

  		case INTERNAL_ERROR : 
  			s = new QStandardItem(
   				iconInternalError, "_Error");
				icons << s;
				s = new QStandardItem( str );	
				itens << s; break;
  		
  		case INFERIOR_VERSION : 
  			s = new QStandardItem(
    			iconInferior, "_Inferior");    			
				icons << s;
  			s = new QStandardItem( str );    			
  			itens << s; break;
  		
  		case SUPERIOR_VERSION: 
  			s = new QStandardItem(
    			iconSuperior, "_Superior");
				icons << s;
  			s = new QStandardItem( str );    						
				itens << s; break;

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

  		case NOT_INSTALLED : 
  			s = new QStandardItem(
    			iconNotInstalled, "_Not installed");
				icons << s;
  			s = new QStandardItem( str );    						
  			itens << s; break; 
   			
   	default: 
   		s = new QStandardItem(
    			iconInternalError, "_Error");
			icons << s;
 			s = new QStandardItem( str );    						
   		itens << s;	    	
   	}    	
  }

	modelPackage->insertColumn(0, icons);	 		
	modelPackage->insertColumn(1, itens);	 		

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

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

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

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

	if (modelPackage->rowCount() > 0) {
		QModelIndex mi = modelPackage->index(0, 0);
		lvPackage->scrollTo(mi);
		lvPackage->setCurrentIndex(mi);
    selectInstalledPackage();    
	}		

	lvPackage->setFocus();
	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() == 1) lvInstalledPackages->selectionModel()->clear(); 
	foreach( SelectedPackage sp, lt ){
		Result res = pck.verifyPackageInstallation(sp.getFileName(), m_slFrozenPackages); 
		
		if (res.getInstalledPackage().size() > 0){
			QList<QStandardItem*> l = 
				modelInstalledPackages->findItems( res.getInstalledPackage(), Qt::MatchStartsWith, PACKAGE_NAME );

			if (l.count() > 0){
				QStandardItem* aux = l[0];
				//modelInstalledPackages->findItems( res.getInstalledPackage(), Qt::MatchStartsWith, PACKAGE_NAME )[0];
				
				mi = 	aux->index();
				mi = proxyModelInstalledPackages->mapFromSource(mi);
				if (!proxyModelInstalledPackages->hasIndex(mi.row(), mi.column())) return;
				//mi = proxyModelInstalledPackages->index(0, 0);
			}
			else mi = proxyModelInstalledPackages->index(0, 0);
			
			lvInstalledPackages->scrollTo(mi);		
			QModelIndex maux = proxyModelInstalledPackages->index(mi.row(), 0);
			lvInstalledPackages->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::Select);
			lvInstalledPackages->selectionModel()->setCurrentIndex(maux, QItemSelectionModel::Select);
			
		}
		else if (res.getInstalledPackage().size() == 0){
			QModelIndex mi = proxyModelInstalledPackages->index(0, 0);
			lvInstalledPackages->selectionModel()->clear();
			lvInstalledPackages->scrollTo(mi);
		} 
	}
}

void MainWindowImpl::positionInInstalledPkgList( const QString& pkg ){
	lvInstalledPackages->setFocus();
	lvInstalledPackages->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);

	lvInstalledPackages->scrollTo(mi);		
	QModelIndex maux = proxyModelInstalledPackages->index(mi.row(), 0);

	lvInstalledPackages->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::Select);
	lvInstalledPackages->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, lvPackage->selectionModel()->selectedRows(PACKAGE_ICON)){
		QStandardItem *si = modelPackage->item( item.row(), PACKAGE_ICON );
		if (si != 0) 
			licons << si->icon();
	}

	foreach(QModelIndex item, lvPackage->selectionModel()->selectedRows(PACKAGE_NAME)){
		QStandardItem *si = modelPackage->item( item.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, lvInstalledPackages->selectionModel()->selectedIndexes()){
		if ( item.column() == PACKAGE_NAME ){    
			lsp << SelectedPackage(PACKAGES_DIR, proxyModelInstalledPackages->data(item, 0).toString());
		}
  }
	
  return lsp;	
}

void MainWindowImpl::showPackageInfo(){
 	QList<SelectedPackage> lsp = getSelectedPackage();

  foreach(SelectedPackage sp, lsp){       	
		if ( sp.getIcon().serialNumber() == iconRPM.serialNumber() ) continue;

		CPUIntensiveComputing *ri = new CPUIntensiveComputing();
		QString sb = Package::getInfoPackage(sp, NOT_INSTALLED);
    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(){
  QList<SelectedPackage> lsp = getSelectedInstalledPackage();

  foreach(SelectedPackage sp, lsp){
		CPUIntensiveComputing *ri = new CPUIntensiveComputing();
  	QString sb = Package::getInfoPackage(sp, INSTALLED);
  	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::showPackageContent(){
	CPUIntensiveComputing ri;
	if (lvInstalledPackages->hasFocus()){
		foreach( SelectedPackage sp, getSelectedInstalledPackage() ){  			
			QString pkg(sp.getCompleteFileName());
			QStringList sl = Package::getPackageContents(pkg, true);
			createTabPkgFileList(sp.getFileName(), sl);  
		}
	}
	else{
		foreach( SelectedPackage sp, getSelectedPackage() ){  			
			QString pkg(sp.getCompleteFileName());
			QStringList sl = Package::getPackageContents(pkg);
			if ( !sl.isEmpty() ) createTabPkgFileList(sp.getFileName(), sl);  
			else{
				ri.restoreDefaultCursor();
				QMessageBox::critical(this, tr("Package %1").arg(sp.getFileName()), tr("This package seems corrupted!"));		
			}
		}			
	}
}

void MainWindowImpl::executePackageActions(){ 
  QStringList s;
	bool rootUser = (QDir::homePath() == "/root");

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

  QString s1;
 
  for (int r=0; r<remove->rowCount(); r++){    
    s1 += " /bin/sh 2>&1 -c 'removepkg " + remove->child(r)->text() + "';";
  }

  for (int r=0; r<downgrade->rowCount(); r++){    
    s1 += " /bin/sh 2>&1 -c 'upgradepkg " + downgrade->child(r)->text() + "';";
  }

  for (int r=0; r<upgrade->rowCount(); r++){    
    s1 += " /bin/sh 2>&1 -c 'upgradepkg " + upgrade->child(r)->text() + "';"; 
  }

  for (int r=0; r<install->rowCount(); r++){    
    s1 += " /bin/sh 2>&1 -c 'installpkg " + install->child(r)->text() + "';"; 
  }

  for (int r=0; r<reinstall->rowCount(); r++){    
    s1 += " /bin/sh 2>&1 -c 'upgradepkg --reinstall " + reinstall->child(r)->text() + "';"; 
  }

	if (s1.isEmpty() == true) return;

  textEdit->clear();
	textEdit->setHtml("");
  
	//std::cout << "Command is: " << s1.toAscii().data() << std::endl;
  s << s1;
  echo = new QProcess(this);  

  connect(echo, SIGNAL( started() ), this, SLOT( processStarted() ));
	connect(echo, SIGNAL( readyReadStandardOutput() ), this, SLOT(readActionsOutput()));
  connect(echo, SIGNAL( finished ( int, QProcess::ExitStatus )),
    this, SLOT(processFinished(int, QProcess::ExitStatus)));
  connect(echo, SIGNAL( error ( QProcess::ProcessError )),
    this, SLOT(processRaisedError( QProcess::ProcessError )));

	if (rootUser) echo->start("/bin/sh", s); 
  else echo->start("kdesu", s);
	//echo->waitForStarted();
  //echo.waitForFinished();  
}

void MainWindowImpl::processRaisedError(QProcess::ProcessError){
  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>");	

	textEdit->insertHtml(msg);
	textEdit->ensureCursorVisible();
}

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

void MainWindowImpl::processFinished(int, QProcess::ExitStatus){
	QString msg;

	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();  

		showPackagesInDirectory();
		
		lblStatus->setText("");	
		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>");	

	textEdit->insertHtml(msg);
	textEdit->ensureCursorVisible();
	delete echo;
}

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

void MainWindowImpl::reapplyFilter(){
  QRegExp regExp(leFilter->text(), Qt::CaseInsensitive, QRegExp::FixedString);
  proxyModelInstalledPackages->setFilterRegExp(regExp);  
  
	int numInstPkgs = proxyModelInstalledPackages->rowCount();
	
	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!"));

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