//
//
// C++ Implementation: tdefilereplacepart
//
// Description:
//
//
// Author: Andras Mantia <amantia@kde.org>, (C) 2003
// Maintainer: Emiliano Gulmini <emi_barbarossa@yahoo.it>, (C) 2004
//
// Copyright: GPL v2. See COPYING file that comes with this distribution
//
//

// QT
#include <tqdir.h>
#include <tqdatastream.h>
#include <tqregexp.h>
#include <tqimage.h>
#include <tqtextcodec.h>

// KDE
#include <dcopclient.h>
#include <dcopref.h>
#include <tdeaboutapplication.h>
#include <tdeapplication.h>
#include <tdeaction.h>
#include <kbugreport.h>
#include <tdeconfig.h>
#include <tdefiledialog.h>
#include <kinstance.h>
#include <tdeio/netaccess.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tdeparts/genericfactory.h>
#include <kstandarddirs.h>
#include <kiconloader.h>
#include <tdeglobal.h>
#include <kiconeffect.h>
#include <tdelistview.h>
#include <kuser.h>
#include <kcombobox.h>
#include <kguiitem.h>

// local
#include "tdefilereplacelib.h"
#include "tdefilereplacepart.h"
#include "tdefilereplaceview.h"
#include "koptionsdlg.h"
#include "knewprojectdlg.h"
#include "report.h"
#include "commandengine.h"
#include "whatthis.h"

// Change this as well if increasing the max value allowed for the m_spbMaxDepth spinbox
static const int CIRCULAR_LINK_DETECTION_LEVEL = 256;

using namespace whatthisNameSpace;

//PUBLIC CONSTRUCTORS
// Factory code for KDE 3
typedef KParts::GenericFactory<TDEFileReplacePart> FileReplaceFactory;

K_EXPORT_COMPONENT_FACTORY( libtdefilereplacepart, FileReplaceFactory )

TDEFileReplacePart::TDEFileReplacePart(TQWidget* parentWidget, const char* , TQObject* parent, const char* name, const TQStringList & ) : KParts::ReadOnlyPart(parent,name)
{
  setInstance(FileReplaceFactory::instance());
  TDEGlobal::locale()->insertCatalogue("tdefilereplace");	
  m_parentWidget = parentWidget;
  m_config = new TDEConfig("tdefilereplacerc");
  m_aboutDlg = 0;
  m_stop = false;
  m_optionMask = TQDir::Files;
  m_w = widget();
  m_option = 0;
  m_circ_ref_warning_shown = false;

  loadOptionsFromRC();
  initView();
  initGUI();

  whatsThis();
}

TDEFileReplacePart::~TDEFileReplacePart()
{
  m_view = 0; //it's already deleted, so set it to NULL

  saveOptionsToRC();

  delete m_aboutDlg;
  m_aboutDlg = 0;
  delete m_config;
  m_config = 0;
  delete m_w;
  m_w = 0;
  delete m_option;
}

//PRIVATE SLOTS
void TDEFileReplacePart::slotSetNewParameters()
{
  launchNewProjectDialog(KURL());
  m_view->changeViews(m_option->m_searchingOnlyMode);
  emit setStatusBarText(i18n("Ready."));
}

void TDEFileReplacePart::slotSearchingOperation()
{
  if(!checkBeforeOperation())
    return;

  TDEListView* rv = m_view->getResultsView();

  rv->clear();

  rv->setSorting(-1);

  // show wait cursor
  TQApplication::setOverrideCursor( TQt::waitCursor );

  freezeActions();

  setOptionMask();

  TQString currentDirectory = m_option->m_directories[0],
          currentFilter = m_option->m_filters[0];

  //m_currentDir = currentDirectory;

  m_view->showSemaphore("red");

  if(m_option->m_recursive)
    {
    int foldersNumber = 0;
    int filesNumber = 0;
    m_circ_ref_warning_shown = false;
    recursiveFileSearch(currentDirectory, currentFilter, foldersNumber, filesNumber, 0);
    }
  else
    fileSearch(currentDirectory, currentFilter);

  m_view->showSemaphore("yellow");

  kapp->processEvents();

  //disabling and enabling sorting... don't ask me why, but it works!
  rv->setSorting(0);
  rv->sort();
  rv->setSorting(-1);

  // restore false status for stop button
  m_stop = false;

  TQApplication::restoreOverrideCursor();

  emit setStatusBarText(i18n("Search completed."));

  m_option->m_searchingOnlyMode = true;

  updateGUI();

  m_searchingOperation = true;

  m_view->showSemaphore("green");
}

void TDEFileReplacePart::slotReplacingOperation()
{
  if (KMessageBox::warningContinueCancel(m_w, i18n("<qt>You have selected <b>%1</b> as the encoding of the files.<br>Selecting the correct encoding is very important as if you have files that have some other encoding than the selected one, after a replace you may damage those files.<br><br>In case you do not know the encoding of your files, select <i>utf8</i> and <b>enable</b> the creation of backup files. This setting will autodetect <i>utf8</i> and <i>utf16</i> files, but the changed files will be converted to <i>utf8</i>.</qt>").arg(m_option->m_encoding), i18n("File Encoding Warning"), KStdGuiItem::cont(), "ShowEncodingWarning") == KMessageBox::Cancel)
    return;
  if(!checkBeforeOperation())
    return;

  TDEListView* rv = m_view->getResultsView();

  if(m_option->m_simulation)
    {
      emit setStatusBarText(i18n("Replacing files (simulation)..."));
      rv->setColumnText(4,i18n("Replaced strings (simulation)"));
    }
  else
    {
      emit setStatusBarText(i18n("Replacing files..."));
      rv->setColumnText(4,i18n("Replaced strings"));
    }
  // show wait cursor
  TQApplication::setOverrideCursor( TQt::waitCursor );

  freezeActions();

  setOptionMask();

  rv->setSorting(-1);

  m_view->showSemaphore("green");

  TQString currentDirectory = m_option->m_directories[0];

  m_view->showSemaphore("red");

  if(m_option->m_recursive)
    {
      int foldersNumber = 0;
      int filesNumber = 0;
      m_circ_ref_warning_shown = false;
      recursiveFileReplace(currentDirectory, foldersNumber, filesNumber, 0);
    }
  else
    {
      fileReplace();
    }

  rv->setSorting(0);
  rv->sort();
  rv->setSorting(-1);

  // restore false status for stop button
  m_stop = false;

  TQApplication::restoreOverrideCursor();

  m_option->m_searchingOnlyMode = false;

  updateGUI();

  m_searchingOperation = false;

  m_view->showSemaphore("green");
}

void TDEFileReplacePart::slotSimulatingOperation()
{
  m_option->m_simulation = true;
  slotReplacingOperation();
  m_option->m_simulation = false;
}

void TDEFileReplacePart::slotStop()
{
  emit setStatusBarText(i18n("Stopping..."));
  m_stop = true;
  TQApplication::restoreOverrideCursor();
  updateGUI();
}

void TDEFileReplacePart::slotCreateReport()
{
  // Check there are results
  TDEListView* rv = m_view->getResultsView(),
           * sv = m_view->getStringsView();

  if(rv->firstChild() == 0)
    {
      KMessageBox::error(m_w, i18n("There are no results to save: the result list is empty."));
      return ;
    }
  // Select the file where results will be saved
  TQString documentName = KFileDialog::getSaveFileName(TQString(), "*.xml|XML " + i18n("Files") + " (*.xml)", m_w, i18n("Save Report"));
  if (documentName.isEmpty())
    return ;

  // delete a spourious extension
  documentName.truncate(documentName.length()-4);

  TQFileInfo fileInfo(documentName);
  if(fileInfo.exists())
    {
      KMessageBox::error(m_w, i18n("<qt>A folder or a file named <b>%1</b> already exists.</qt>").arg(documentName));
      return ;
    }

  TQDir directoryName;

  if(!directoryName.mkdir(documentName, true))
    {
      KMessageBox::error(m_w, i18n("<qt>Cannot create the <b>%1</b> folder.</qt>").arg(documentName));
      return ;
    }

  directoryName.cd(documentName);

  TQString documentPath = documentName+"/"+directoryName.dirName();

  Report report(m_option, rv, sv);
         report.createDocument(documentPath);

  //updateGUI();
}

void TDEFileReplacePart::slotQuickStringsAdd()
{
  //this slot handles a pair of strings that come from project dialog,
  //if the control character 'N' is found at the position 0 of the two strings,
  //then we start the search now.
  TQString qs = m_option->m_quickSearchString;
  TQStringList map;

  map.append(qs.left(1));
  map.append(qs.right(qs.length()-1));
  //in this case there is no string to search for, so return
  if(map[1].isEmpty())
    return;

  //in this one instead, we must search for a string
  qs = m_option->m_quickReplaceString;
  map.append(qs.left(1));
  map.append(qs.right(qs.length()-1));

  m_view->updateOptions(m_option);

  m_view->slotQuickStringsAdd(map[1],map[3]);

  //if search-only mode == true and search-now mode == true then search string
  if (map[0] == "N")
  {
    if (m_option->m_searchingOnlyMode)
      slotSearchingOperation();
    else
      slotReplacingOperation();
  }
}

void TDEFileReplacePart::slotOptionRecursive()
{
  m_option->m_recursive = !m_option->m_recursive;
  updateGUI();
}

void TDEFileReplacePart::slotOptionBackup()
{
  m_option->m_backup = !m_option->m_backup;
  updateGUI();
}

void TDEFileReplacePart::slotOptionCaseSensitive()
{
  m_option->m_caseSensitive = !m_option->m_caseSensitive;
  updateGUI();
}

void TDEFileReplacePart::slotOptionVariables()
{
  m_option->m_variables = !m_option->m_variables;
  updateGUI();
}

void TDEFileReplacePart::slotOptionRegularExpressions()
{
  m_option->m_regularExpressions = !m_option->m_regularExpressions;
  updateGUI();
}

void TDEFileReplacePart::slotOptionPreferences()
{
  KOptionsDlg dlg(m_option, m_w, 0);
  if (!dlg.exec())
  {
    return;
  }
  m_view->updateOptions(m_option);
  updateGUI();
}

void TDEFileReplacePart::showAboutApplication()
{
  m_aboutDlg = new TDEAboutApplication(createAboutData(), (TQWidget *)0, (const char *)0, false);
  if(m_aboutDlg == 0)
    return;

  if(!m_aboutDlg->isVisible())
    m_aboutDlg->show();
  else
    m_aboutDlg->raise();
}

void TDEFileReplacePart::appHelpActivated()
{
  kapp->invokeHelp(TQString(), "tdefilereplace");
}

void TDEFileReplacePart::reportBug()
{
  KBugReport dlg(m_w, true, createAboutData());
  dlg.exec();
}

void TDEFileReplacePart::updateGUI()
{
  TDEListView *rv = m_view->getResultsView();
  TDEListView *sv = m_view->getStringsView();

  bool hasResults = (rv->firstChild() != 0);
  bool hasStrings = (sv->firstChild() != 0);
  bool searchOnlyMode = m_option->m_searchingOnlyMode;

  // File
  actionCollection()->action("new_project")->setEnabled(true);
  actionCollection()->action("search")->setEnabled(hasStrings && searchOnlyMode);
  actionCollection()->action("file_simulate")->setEnabled(hasStrings && !searchOnlyMode);
  actionCollection()->action("replace")->setEnabled(hasStrings && !searchOnlyMode);
  actionCollection()->action("stop")->setEnabled(false);

  // Strings
  actionCollection()->action("strings_add")->setEnabled(true);
  actionCollection()->action("strings_del")->setEnabled(hasStrings);
  actionCollection()->action("strings_empty")->setEnabled(hasStrings);
  actionCollection()->action("strings_save")->setEnabled(hasStrings);
  actionCollection()->action("strings_load")->setEnabled(true);
  actionCollection()->action("strings_invert")->setEnabled(hasStrings && !searchOnlyMode);
  actionCollection()->action("strings_invert_all")->setEnabled(hasStrings && !searchOnlyMode);

  // Options
  actionCollection()->action("options_recursive")->setEnabled(true);
  actionCollection()->action("options_backup")->setEnabled(!searchOnlyMode);
  actionCollection()->action("options_case")->setEnabled(true);
  actionCollection()->action("options_var")->setEnabled(!searchOnlyMode);
  actionCollection()->action("options_regularexpressions")->setEnabled(true);
  actionCollection()->action("configure_tdefilereplace")->setEnabled(true);

  // Results
  actionCollection()->action("results_infos")->setEnabled(hasResults);
  actionCollection()->action("results_openfile")->setEnabled(hasResults);
  actionCollection()->action("results_openfilewith")->setEnabled(hasResults);
  if (actionCollection()->action("results_editfile"))
  {
      actionCollection()->action("results_editfile")->setEnabled(hasResults);
  }
  actionCollection()->action("results_opendir")->setEnabled(hasResults);
  actionCollection()->action("results_removeentry")->setEnabled(hasResults);
  actionCollection()->action("results_delete")->setEnabled(hasResults);
  actionCollection()->action("results_treeexpand")->setEnabled(hasResults);
  actionCollection()->action("results_treereduce")->setEnabled(hasResults);
  actionCollection()->action("results_create_report")->setEnabled(hasResults);
  actionCollection()->action("results_save")->setEnabled(hasResults);
  actionCollection()->action("results_load")->setEnabled(true);

  // Updates menus and toolbar
  ((TDEToggleAction*) actionCollection()->action("options_recursive"))->setChecked(m_option->m_recursive);
  ((TDEToggleAction*) actionCollection()->action("options_backup"))->setChecked(m_option->m_backup && !searchOnlyMode);
  ((TDEToggleAction*) actionCollection()->action("options_case"))->setChecked(m_option->m_caseSensitive);
  ((TDEToggleAction*) actionCollection()->action("options_var"))->setChecked(m_option->m_variables && !searchOnlyMode);
  ((TDEToggleAction*) actionCollection()->action("options_regularexpressions"))->setChecked(m_option->m_regularExpressions);
}

//PUBLIC METHODS
TDEAboutData* TDEFileReplacePart::createAboutData()
{
  TDEAboutData *aboutData = new TDEAboutData("tdefilereplacepart",
                                          I18N_NOOP("TDEFileReplacePart"),
                                          KFR_VERSION,
                                          I18N_NOOP( "Batch search and replace tool."),
                                          TDEAboutData::License_GPL_V2,
                                          "(C) 1999-2002 François Dupoux\n(C) 2003-2004 Andras Mantia\n(C) 2004 Emiliano Gulmini", I18N_NOOP("Part of the TDEUtils module."), "http://www.kdewebdev.org");
  aboutData->addAuthor("François Dupoux",
                       I18N_NOOP("Original author of the TDEFileReplace tool"),
                       "dupoux@dupoux.com");
  aboutData->addAuthor("Emiliano Gulmini",
                       I18N_NOOP("Current maintainer, code cleaner and rewriter"),
                       "emi_barbarossa@yahoo.it");
  aboutData->addAuthor("Andras Mantia",
                       I18N_NOOP("Co-maintainer, KPart creator"),
                       "amantia@kde.org");
  aboutData->addCredit("Heiko Goller",
                       I18N_NOOP("Original german translator"),
                       "heiko.goller@tuebingen.mpg.de");
  return aboutData;
}

//PROTECTED METHODS
bool TDEFileReplacePart::openURL(const KURL &url)
{
  if(!url.isEmpty() && (url.protocol() != "file"))
    {
      KMessageBox::sorry(m_w, i18n("Sorry, currently the TDEFileReplace part works only for local files."), i18n("Non Local File"));
      emit canceled("");
      return false;
    }
  if(!url.isEmpty())
    return launchNewProjectDialog(url);
  else
    {
      updateGUI();
      return true;
    }
}

//PRIVATE METHODS
void TDEFileReplacePart::initGUI()
{
  setXMLFile("tdefilereplacepartui.rc");

  actionCollection()->setHighlightingEnabled(true);

  DCOPClient *client = kapp->dcopClient();
  QCStringList appList = client->registeredApplications();
  bool quantaFound = false;
  for(QCStringList::Iterator it = appList.begin(); it != appList.end(); ++it)
    {
      if((*it).left(6) == "quanta")
        {
          quantaFound = true;
          break;
        }
    }

  // GUI
  connect(m_view, TQT_SIGNAL(updateGUI()), this, TQT_SLOT(updateGUI()));

  // File
  (void)new TDEAction(i18n("Customize Search/Replace Session..."), "projectopen", TDEShortcut(CTRL + Key_F), TQT_TQOBJECT(this), TQT_SLOT(slotSetNewParameters()), actionCollection(), "new_project");
  (void)new TDEAction(i18n("&Search"), "filesearch", 0, TQT_TQOBJECT(this), TQT_SLOT(slotSearchingOperation()), actionCollection(), "search");
  (void)new TDEAction(i18n("S&imulate"), "filesimulate", 0, TQT_TQOBJECT(this), TQT_SLOT(slotSimulatingOperation()), actionCollection(), "file_simulate");
  (void)new TDEAction(i18n("&Replace"),  "filereplace", 0, TQT_TQOBJECT(this), TQT_SLOT(slotReplacingOperation()), actionCollection(), "replace");
  (void)new TDEAction(i18n("Sto&p"), "process-stop", 0, TQT_TQOBJECT(this), TQT_SLOT(slotStop()), actionCollection(), "stop");
  (void)new TDEAction(i18n("Cre&ate Report File..."), "document-save-as", 0, TQT_TQOBJECT(this), TQT_SLOT(slotCreateReport()), actionCollection(), "results_create_report");
  (void)new TDEAction(i18n("&Save Results List to File..."), "document-save-as", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultSave()), actionCollection(), "results_save");
  (void)new TDEAction(i18n("&Load Results List From File..."), "unsortedList", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultLoad()), actionCollection(), "results_load");

  // Strings
  (void)new TDEAction(i18n("&Add String..."), "editadd", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotStringsAdd()), actionCollection(), "strings_add");
  (void)new TDEAction(i18n("&Delete String"), "editremove", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotStringsDeleteItem()), actionCollection(), "strings_del");
  (void)new TDEAction(i18n("&Empty Strings List"), "edit-delete", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotStringsEmpty()), actionCollection(), "strings_empty");
  (void)new TDEAction(i18n("&Save Strings List to File..."), "document-save-as", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotStringsSave()), actionCollection(), "strings_save");
  (void)new TDEAction(i18n("&Load Strings List From File..."), "unsortedList", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotStringsLoad()), actionCollection(), "strings_load");
  (void)new TDEAction(i18n("&Invert Current String (search <--> replace)"), "invert", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotStringsInvertCur()), actionCollection(), "strings_invert");
  (void)new TDEAction(i18n("&Invert All Strings (search <--> replace)"), "invert", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotStringsInvertAll()), actionCollection(), "strings_invert_all");

  // Options
  (void)new TDEToggleAction(i18n("&Include Sub-Folders"), "recursive_option", 0, TQT_TQOBJECT(this), TQT_SLOT(slotOptionRecursive()), actionCollection(), "options_recursive");
  (void)new TDEToggleAction(i18n("Create &Backup Files"), "backup_option", 0, TQT_TQOBJECT(this), TQT_SLOT(slotOptionBackup()), actionCollection(), "options_backup");
  (void)new TDEToggleAction(i18n("Case &Sensitive"), "casesensitive_option", 0, TQT_TQOBJECT(this), TQT_SLOT(slotOptionCaseSensitive()), actionCollection(), "options_case");
  (void)new TDEToggleAction(i18n("Enable Commands &in Replace String: [$command:option$]"), "command_option", 0, TQT_TQOBJECT(this), TQT_SLOT(slotOptionVariables()), actionCollection(), "options_var");
  (void)new TDEToggleAction(i18n("Enable &Regular Expressions"), "regularexpression_option", 0, TQT_TQOBJECT(this), TQT_SLOT(slotOptionRegularExpressions()), actionCollection(), "options_regularexpressions");
  (void)new TDEAction(i18n("Configure &TDEFileReplace..."), "configure", 0, TQT_TQOBJECT(this), TQT_SLOT(slotOptionPreferences()), actionCollection(), "configure_tdefilereplace");

  // Results
  (void)new TDEAction(i18n("&Properties"), "informations", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultProperties()), actionCollection(), "results_infos");
  (void)new TDEAction(i18n("&Open"), "document-open", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultOpen()), actionCollection(), "results_openfile");
  (void)new TDEAction(i18n("Open &With..."), "document-open", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultOpenWith()), actionCollection(), "results_openfilewith");
  if(quantaFound)
  {
    (void)new TDEAction(i18n("&Edit in Quanta"), "quanta", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultEdit()), actionCollection(), "results_editfile");
  }
  (void)new TDEAction(i18n("Open Parent &Folder"), "go-up", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultDirOpen()), actionCollection(), "results_opendir");
  (void)new TDEAction(i18n("Remove &Entry"), "edit-clear", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultRemoveEntry()), actionCollection(), "results_removeentry");
  (void)new TDEAction(i18n("&Delete"), "edit-delete", 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultDelete()), actionCollection(), "results_delete");
  (void)new TDEAction(i18n("E&xpand Tree"), 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultTreeExpand()), actionCollection(), "results_treeexpand");
  (void)new TDEAction(i18n("&Reduce Tree"), 0, TQT_TQOBJECT(m_view), TQT_SLOT(slotResultTreeReduce()), actionCollection(), "results_treereduce");

  // Help
  (void)new TDEAction(i18n("&About TDEFileReplace"), "tdefilereplace", 0, TQT_TQOBJECT(this), TQT_SLOT(showAboutApplication()), actionCollection(), "help_about_tdefilereplace");
  (void)new TDEAction(i18n("TDEFileReplace &Handbook"), "help", 0, TQT_TQOBJECT(this), TQT_SLOT(appHelpActivated()), actionCollection(), "help_tdefilereplace");
  (void)new TDEAction(i18n("&Report Bug"), 0, 0, TQT_TQOBJECT(this), TQT_SLOT(reportBug()), actionCollection(), "report_bug");
}

void TDEFileReplacePart::initView()
{
  m_view = new TDEFileReplaceView(m_option, m_parentWidget, "view");

  setWidget(m_view);

  m_view->setAcceptDrops(false);

  m_view->showSemaphore("green");
}

void TDEFileReplacePart::freezeActions()
{
  //Disables actions during search/replace operation
  actionCollection()->action("new_project")->setEnabled(false);
  actionCollection()->action("stop")->setEnabled(true);

  actionCollection()->action("file_simulate")->setEnabled(false);
  actionCollection()->action("replace")->setEnabled(false);
  actionCollection()->action("search")->setEnabled(false);
  actionCollection()->action("strings_add")->setEnabled(false);
  actionCollection()->action("strings_del")->setEnabled(false);
  actionCollection()->action("strings_empty")->setEnabled(false);
  actionCollection()->action("strings_save")->setEnabled(false);
  actionCollection()->action("strings_load")->setEnabled(false);
  actionCollection()->action("strings_invert")->setEnabled(false);
  actionCollection()->action("strings_invert_all")->setEnabled(false);
  actionCollection()->action("options_recursive")->setEnabled(false);
  actionCollection()->action("options_backup")->setEnabled(false);
  actionCollection()->action("options_case")->setEnabled(false);
  actionCollection()->action("options_var")->setEnabled(false);
  actionCollection()->action("options_regularexpressions")->setEnabled(false);
  actionCollection()->action("configure_tdefilereplace")->setEnabled(false);
  actionCollection()->action("results_infos")->setEnabled(false);
  actionCollection()->action("results_openfile")->setEnabled(false);
  if (actionCollection()->action("results_editfile"))
  {
      actionCollection()->action("results_editfile")->setEnabled(false);
  }
  actionCollection()->action("results_opendir")->setEnabled(false);
  actionCollection()->action("results_removeentry")->setEnabled(false);
  actionCollection()->action("results_delete")->setEnabled(false);
  actionCollection()->action("results_treeexpand")->setEnabled(false);
  actionCollection()->action("results_treereduce")->setEnabled(false);
  ((TDEToggleAction* ) actionCollection()->action("options_recursive"))->setChecked(false);
  ((TDEToggleAction* ) actionCollection()->action("options_backup"))->setChecked(false);
  ((TDEToggleAction* ) actionCollection()->action("options_case"))->setChecked(false);
  ((TDEToggleAction* ) actionCollection()->action("options_var"))->setChecked(false);
  ((TDEToggleAction* ) actionCollection()->action("options_regularexpressions"))->setChecked(false);
}

void TDEFileReplacePart::loadOptionsFromRC()
{
  m_option = new RCOptions();

  loadOptions();
  loadFileSizeOptions();
  loadDateAccessOptions();
  loadOwnerOptions();
  loadCBLists();
  loadFiltersList();
  loadBackupExtensionOptions();
}

void TDEFileReplacePart::loadOptions()
{
  m_config->setGroup("General Options");

  m_option->m_searchingOnlyMode = m_config->readBoolEntry(rcSearchMode,SearchModeOption);

  m_config->setGroup("Options");

  m_option->m_encoding = m_config->readEntry(rcEncoding, EncodingOption);
  m_option->m_recursive = m_config->readBoolEntry(rcRecursive, RecursiveOption);
  m_option->m_limitDepth = m_config->readBoolEntry(rcLimitDepth, LimitDepthOption);
  m_option->m_maxDepth = m_config->readNumEntry(rcMaxDepth, MaxDepthOption);

  m_option->m_caseSensitive = m_config->readBoolEntry(rcCaseSensitive, CaseSensitiveOption);
  m_option->m_variables = m_config->readBoolEntry(rcVariables, VariablesOption);
  m_option->m_regularExpressions = m_config->readBoolEntry(rcRegularExpressions, RegularExpressionsOption);
  m_option->m_followSymLinks = m_config->readBoolEntry(rcFollowSymLinks, FollowSymbolicLinksOption);

  m_option->m_haltOnFirstOccur = m_config->readBoolEntry(rcHaltOnFirstOccur, StopWhenFirstOccurenceOption);

  m_option->m_ignoreHidden = m_config->readBoolEntry(rcIgnoreHidden, IgnoreHiddenOption);
  m_option->m_ignoreFiles = m_config->readBoolEntry(rcIgnoreFiles, IgnoreFilesOption);

  m_config->setGroup("Notification Messages");

  m_option->m_notifyOnErrors  = m_config->readBoolEntry(rcNotifyOnErrors, true);

  m_option->m_askConfirmReplace = m_config->readBoolEntry(rcAskConfirmReplace, AskConfirmReplaceOption);

  TQString dontAskAgain = m_config->readEntry(rcDontAskAgain, "no");

  if(dontAskAgain == "yes")
    m_option->m_askConfirmReplace = false;
}

void TDEFileReplacePart::loadFileSizeOptions()
{
  m_config->setGroup("Size options");

  m_option->m_minSize = m_config->readNumEntry(rcMinFileSize, FileSizeOption);
  m_option->m_maxSize = m_config->readNumEntry(rcMaxFileSize, FileSizeOption);
}

void TDEFileReplacePart::loadDateAccessOptions()
{
  m_config->setGroup("Access options");

  m_option->m_dateAccess = m_config->readEntry(rcValidAccessDate, ValidAccessDateOption);
  m_option->m_minDate = m_config->readEntry(rcMinDate, AccessDateOption);
  m_option->m_maxDate = m_config->readEntry(rcMaxDate, AccessDateOption);
}

void TDEFileReplacePart::loadOwnerOptions()
{
  m_config->setGroup("Owner options");

  TQStringList ownerList = TQStringList::split(',',m_config->readEntry(rcOwnerUser, OwnerOption),true);
  if(ownerList[0] == "true")
    m_option->m_ownerUserIsChecked = true;
  else
    m_option->m_ownerUserIsChecked = false;

  m_option->m_ownerUserType = ownerList[1];
  m_option->m_ownerUserBool = ownerList[2];
  m_option->m_ownerUserValue = ownerList[3];

  ownerList = TQStringList::split(',',m_config->readEntry(rcOwnerGroup, OwnerOption),true);

  if(ownerList[0] == "true")
    m_option->m_ownerGroupIsChecked = true;
  else
    m_option->m_ownerGroupIsChecked = false;

  m_option->m_ownerGroupType = ownerList[1];
  m_option->m_ownerGroupBool = ownerList[2];
  m_option->m_ownerGroupValue = ownerList[3];
}

void TDEFileReplacePart::loadCBLists()
{
  // Search list
  m_config->setGroup("Search strings");
  m_option->m_searchStrings = m_config->readPathListEntry(rcSearchStringsList);
  
  // Replace list
  m_config->setGroup("Replace strings");
  m_option->m_replaceStrings = m_config->readPathListEntry(rcReplaceStringsList);
  
  // Location list
  m_config->setGroup("Directories");
  m_option->m_directories = m_config->readPathListEntry(rcDirectoriesList);
  if (m_option->m_directories.isEmpty())
    m_option->m_directories.append(TQDir::current().path());
}

void TDEFileReplacePart::loadFiltersList()
{
  TQStringList filtersEntryList;

  m_config->setGroup("Filters");
  #if KDE_IS_VERSION(3,1,3)
  filtersEntryList = m_config->readPathListEntry(rcFiltersList);
  #else
  filtersEntryList = m_config->readListEntry(rcFiltersList);
  #endif

  if(filtersEntryList.isEmpty())
    filtersEntryList.append("*.htm;*.html;*.xml;*.xhtml;*.css;*.js;*.php");

  m_option->m_filters = filtersEntryList;
}

void TDEFileReplacePart::loadBackupExtensionOptions()
{
  m_config->setGroup("Options");
  TQStringList bkList = TQStringList::split(',',
                                          m_config->readEntry(rcBackupExtension, BackupExtensionOption),
                                          true);
  if(bkList[0] == "true")
    m_option->m_backup = true;
  else
    m_option->m_backup = false;

  m_option->m_backupExtension = bkList[1];
}

void TDEFileReplacePart::saveOptionsToRC()
{
  saveOptions();
  saveFileSizeOptions();
  saveDateAccessOptions();
  saveOwnerOptions();
  saveCBLists();
  saveFiltersList();
  saveBackupExtensionOptions();
}

void TDEFileReplacePart::saveOptions()
{
  m_config->setGroup("General Options");

  m_config->writeEntry(rcSearchMode,m_option->m_searchingOnlyMode);

  m_config->setGroup("Options");

  m_config->writeEntry(rcEncoding, m_option->m_encoding);
  m_config->writeEntry(rcRecursive, m_option->m_recursive);
  m_config->writeEntry(rcLimitDepth, m_option->m_limitDepth);
  m_config->writeEntry(rcMaxDepth, m_option->m_maxDepth);
  m_config->writeEntry(rcCaseSensitive, m_option->m_caseSensitive);
  m_config->writeEntry(rcVariables, m_option->m_variables);
  m_config->writeEntry(rcRegularExpressions, m_option->m_regularExpressions);

  m_config->writeEntry(rcFollowSymLinks, m_option->m_followSymLinks);
  m_config->writeEntry(rcHaltOnFirstOccur, m_option->m_haltOnFirstOccur);

  m_config->writeEntry(rcIgnoreHidden, m_option->m_ignoreHidden);
  m_config->writeEntry(rcIgnoreFiles, m_option->m_ignoreFiles);

  m_config->setGroup("Notification Messages");
  m_config->writeEntry(rcNotifyOnErrors, m_option->m_notifyOnErrors);
  if(m_config->readEntry(rcDontAskAgain,"no") == "yes")
    m_config->writeEntry(rcAskConfirmReplace, false);
  else
    m_config->writeEntry(rcAskConfirmReplace, m_option->m_askConfirmReplace);

  m_config->sync();
}

void TDEFileReplacePart::saveFileSizeOptions()
{
  m_config->setGroup("Size options");

  m_config->writeEntry(rcMaxFileSize, m_option->m_maxSize);
  m_config->writeEntry(rcMinFileSize, m_option->m_minSize);

  m_config->sync();
}

void TDEFileReplacePart::saveDateAccessOptions()
{
  m_config->setGroup("Access options");

  m_config->writeEntry(rcValidAccessDate, m_option->m_dateAccess);
  m_config->writeEntry(rcMinDate, m_option->m_minDate);
  m_config->writeEntry(rcMaxDate, m_option->m_maxDate);

  m_config->sync();
}

void TDEFileReplacePart::saveOwnerOptions()
{
  m_config->setGroup("Owner options");

  TQString list;
  if(m_option->m_ownerUserIsChecked)
    list = "true,";
  else
    list = "false,";

  list += m_option->m_ownerUserType +
          "," +
          m_option->m_ownerUserBool;
  if(!m_option->m_ownerUserValue.isEmpty())
    list += "," + m_option->m_ownerUserValue;

  m_config->writeEntry(rcOwnerUser,list);

  if(m_option->m_ownerGroupIsChecked)
    list = "true,";
  else
    list = "false,";

  list += m_option->m_ownerGroupType +
          "," +
          m_option->m_ownerGroupBool;
  if(!m_option->m_ownerGroupValue.isEmpty())
    list += "," + m_option->m_ownerGroupValue;

  m_config->writeEntry(rcOwnerGroup,list);
  m_config->sync();
}

void TDEFileReplacePart::saveCBLists()
{
  // Search list
  m_config->setGroup("Search strings");
  m_config->writePathEntry(rcSearchStringsList, m_option->m_searchStrings);
  
  // Replace list
  m_config->setGroup("Replace strings");
  m_config->writePathEntry(rcReplaceStringsList, m_option->m_replaceStrings);
  
  // Location list
  m_config->setGroup("Directories");
  m_config->writePathEntry(rcDirectoriesList, m_option->m_directories);
  
  m_config->sync();
}

void TDEFileReplacePart::saveFiltersList()
{
  m_config->setGroup("Filters");
  m_config->writeEntry(rcFiltersList, m_option->m_filters);
  m_config->sync();
}

void TDEFileReplacePart::saveBackupExtensionOptions()
{
  m_config->setGroup("Options");
  TQString bkOptions;
  if(m_option->m_backup)
    bkOptions = "true," + m_option->m_backupExtension;
  else
    bkOptions = "false," + m_option->m_backupExtension;

  m_config->writeEntry(rcBackupExtension, bkOptions);
  m_config->sync();
}

void TDEFileReplacePart::fileReplace()
{
  TQString directoryName = m_option->m_directories[0];
  TQDir d(directoryName);
  d.setMatchAllDirs(true);
  d.setFilter(m_optionMask);

  TQString currentFilter = m_option->m_filters[0];
  TQStringList filesList = d.entryList(currentFilter);
  TQStringList::iterator filesIt;
  int filesNumber = 0;

  m_view->displayScannedFiles(0, filesNumber);

  for (filesIt = filesList.begin(); filesIt != filesList.end() ; ++filesIt)
    {
      TQString fileName = (*filesIt);

      // m_stop == true means that we pushed the stop button
      if(m_stop)
        break;

      // Avoids files that not match requirements
      if(!TDEFileReplaceLib::isAnAccessibleFile(d.canonicalPath(), fileName, m_option))
        continue;
      kapp->processEvents();
      if(m_option->m_backup)
        replaceAndBackup(d.canonicalPath(), fileName);
      else
        replaceAndOverwrite(d.canonicalPath(), fileName);

      filesNumber++;
      m_view->displayScannedFiles(0, filesNumber);
    }
    m_view->displayScannedFiles(1, filesNumber);
}

void TDEFileReplacePart::recursiveFileReplace(const TQString &directoryName, int &foldersNumber, int &filesNumber,
                                              int depth)
{
  // if m_stop == true or the max depth level is reached, then interrupt recursion
  if (m_stop || (m_option->m_limitDepth && depth > m_option->m_maxDepth))
    return;
  else if (!m_option->m_limitDepth && depth > CIRCULAR_LINK_DETECTION_LEVEL)
    {
      if (!m_circ_ref_warning_shown)
        {
          KMessageBox::information(m_w,
              i18n("It seems you have a circular reference in your file system."
                  "The search has been limited to this sublevel to prevent"
                  "TDEFileReplace from crashing."),
              i18n("Circular reference detected"));
          m_circ_ref_warning_shown = true;
        }
      return;
    }  
    
  TQDir d(directoryName);

  d.setMatchAllDirs(true);
  d.setFilter(m_optionMask);

  TQString currentFilter = m_option->m_filters[0];
  TQStringList filesList = d.entryList(currentFilter);
  TQStringList::iterator filesIt;

  for (filesIt = filesList.begin(); filesIt != filesList.end(); ++filesIt)
    {
      if (m_stop)
        break;

      TQString fileName = (*filesIt);
      // Avoids files that not match requirements
      if(!TDEFileReplaceLib::isAnAccessibleFile(d.canonicalPath(), fileName, m_option))
        continue;

      TQString filePath = d.canonicalPath()+"/"+fileName;

      TQFileInfo qi(filePath);

      m_view->displayScannedFiles(foldersNumber, filesNumber);
      kapp->processEvents();
      
      // Replace recursively if "filePath" is a directory and we have not reached the max depth level
      if (qi.isDir())
        { 
          if (!m_option->m_limitDepth || depth < m_option->m_maxDepth)
            {
            recursiveFileReplace(filePath, foldersNumber, filesNumber, depth+1);
            }
        }  
      else
        {
          if(m_option->m_backup)
            replaceAndBackup(d.canonicalPath(), fileName);
          else
            replaceAndOverwrite(d.canonicalPath(), fileName);

          filesNumber++;
          m_view->displayScannedFiles(foldersNumber, filesNumber);
        }
    }
    
  foldersNumber++;
  m_view->displayScannedFiles(foldersNumber, filesNumber);
}

void TDEFileReplacePart::replaceAndBackup(const TQString& currentDir, const TQString& oldFileName)
{
   //Creates a path string
  TQString oldPathString = currentDir+"/"+oldFileName;

  TQFile currentFile(oldPathString);
  if(!currentFile.open(IO_ReadOnly))
    {
      KMessageBox::information(m_w, i18n("<qt>Cannot open file <b>%1</b> for reading.</qt>").arg(oldFileName),TQString(), rcNotifyOnErrors);
      return ;
    }
  TQTextStream currentStream(&currentFile);
  if (m_option->m_encoding == "utf8")
    currentStream.setEncoding(TQTextStream::UnicodeUTF8);
  else
    currentStream.setCodec(TQTextCodec::codecForName(m_option->m_encoding.ascii()));
  TQString line = currentStream.read(),
          backupLine = line;

  TQString backupSize = TDEFileReplaceLib::formatFileSize(currentFile.size());

  currentFile.close();

  TQString backupExtension = m_option->m_backupExtension;

  bool atLeastOneStringFound = false;
  TDEListViewItem *item = 0;
  int occurrence = 0;

  replacingLoop(line, &item, atLeastOneStringFound, occurrence, m_option->m_regularExpressions, m_option->m_askConfirmReplace);

  //If we are not performing a simulation creates a backup file
  if(!m_option->m_simulation)
    {
      if(atLeastOneStringFound)
        {
          TDEIO::NetAccess::file_copy(KURL::fromPathOrURL(oldPathString), KURL::fromPathOrURL(oldPathString + backupExtension), -1, true);
      	}
    }

  if(!m_option->m_simulation)
    {
      if(atLeastOneStringFound)
        {
          TQFile newFile(oldPathString);
          if(!newFile.open(IO_WriteOnly))
            {
              KMessageBox::information(m_w, i18n("<qt>Cannot open file <b>%1</b> for writing.</qt>").arg(oldFileName),TQString(), rcNotifyOnErrors);
              return ;
            }
          TQTextStream newStream(&newFile);
          if (m_option->m_encoding == "utf8")
            newStream.setEncoding(TQTextStream::UnicodeUTF8);
          else
            newStream.setCodec(TQTextCodec::codecForName(m_option->m_encoding.ascii()));
          newStream << line;
          newFile.close();
        }
     }

   if(!m_option->m_ignoreFiles)
     atLeastOneStringFound = true;

  TQFileInfo oldFileInfo(oldPathString);

   if(atLeastOneStringFound && item/* && atLeastOneStringConfirmed*/)
     {
       TDEFileReplaceLib::setIconForFileEntry(item,currentDir+"/"+oldFileName);
       item->setText(0,oldFileName);
       item->setText(1,currentDir);
       TQString newSize = TDEFileReplaceLib::formatFileSize(oldFileInfo.size());
       if(!m_option->m_simulation)
         {
           item->setText(2, backupSize);
           item->setText(3, newSize);
         }
       else
         {
           item->setText(2, backupSize);
           item->setText(3, "-");
         }

       item->setText(4,TQString::number(occurrence,10));
       item->setText(5,TQString("%1[%2]").arg(oldFileInfo.owner()).arg(oldFileInfo.ownerId()));
       item->setText(6,TQString("%1[%2]").arg(oldFileInfo.group()).arg(oldFileInfo.groupId()));
     }
}

void TDEFileReplacePart::replaceAndOverwrite(const TQString& currentDir, const TQString& oldFileName)
{
  TQString oldPathString = currentDir+"/"+oldFileName;
  TQFile oldFile(oldPathString);
  TQFileInfo oldFileInfo(oldPathString);

  if (!oldFile.open(IO_ReadOnly))
    {
      KMessageBox::information(m_w, i18n("<qt>Cannot open file <b>%1</b> for reading.</qt>").arg(oldFile.name()),TQString(), rcNotifyOnErrors);
      return ;
    }

  TQString fileSizeBeforeReplacing =  TDEFileReplaceLib::formatFileSize(oldFileInfo.size());
  TDEListViewItem *item = 0;

  TQTextStream oldStream( &oldFile );
  if (m_option->m_encoding == "utf8")
    oldStream.setEncoding(TQTextStream::UnicodeUTF8);
  else
    oldStream.setCodec(TQTextCodec::codecForName(m_option->m_encoding.ascii()));
  TQString line = oldStream.read();

  oldFile.close();

  bool atLeastOneStringFound = false;
  int occurrence = 0;

  replacingLoop(line, &item, atLeastOneStringFound, occurrence, m_option->m_regularExpressions, m_option->m_askConfirmReplace);


  if(!m_option->m_simulation)
    {
      if(atLeastOneStringFound)
        {
	  TQFile newFile(oldPathString);
          if(!newFile.open(IO_WriteOnly))
            {
              KMessageBox::information(m_w, i18n("<qt>Cannot open file <b>%1</b> for writing.</qt>").arg(newFile.name()),TQString(), rcNotifyOnErrors);
              return ;
            }
          TQTextStream newStream( &newFile );
          if (m_option->m_encoding == "utf8")
            newStream.setEncoding(TQTextStream::UnicodeUTF8);
          else
            newStream.setCodec(TQTextCodec::codecForName(m_option->m_encoding.ascii()));
          newStream << line;
          newFile.close();
	}
     }

  TQFileInfo nf(oldPathString);
  TQString fileSizeAfterReplacing = TDEFileReplaceLib::formatFileSize(nf.size());

  //if ignoreFiles == false then every files must be show
  if(!m_option->m_ignoreFiles)
    atLeastOneStringFound = true;

  if(atLeastOneStringFound  && item/*&& atLeastOneStringConfirmed*/)
    {
      TDEFileReplaceLib::setIconForFileEntry(item,currentDir+"/"+oldFileName);
      item->setText(0,oldFileName);
      item->setText(1,currentDir);
      item->setText(2,fileSizeBeforeReplacing);
      if(!m_option->m_simulation)
        item->setText(3,fileSizeAfterReplacing);
      else
        item->setText(3,"-");

      item->setText(4,TQString::number(occurrence,10));
      item->setText(5,TQString("%1[%2]").arg(oldFileInfo.owner()).arg(oldFileInfo.ownerId()));
      item->setText(6,TQString("%1[%2]").arg(oldFileInfo.group()).arg(oldFileInfo.groupId()));
    }
}

void TDEFileReplacePart::replacingLoop(TQString& line, TDEListViewItem** item, bool& atLeastOneStringFound, int& occur, bool regularExpression, bool& askConfirmReplace)
{
  KeyValueMap tempMap = m_replacementMap;
  KeyValueMap::Iterator it;
  TDEListView* rv = m_view->getResultsView();

  for(it = tempMap.begin(); it != tempMap.end(); ++it)
    {
      if(m_stop)
        break;

      ResultViewEntry entry(it.key(), it.data(), regularExpression, m_option->m_caseSensitive);
      while(entry.pos(line) != -1)
        {
          if(m_stop)
           break;
	  
	  if(askConfirmReplace)
	    {
	      int answer = KMessageBox::questionYesNo(0,
		                                      i18n("<qt>Do you want to replace the string <b>%1</b> with the string <b>%2</b>?</qt>").arg(it.key()).arg(it.data()),
                                                      i18n("Confirm Replace"),
						      i18n("Replace"),
						      i18n("Do Not Replace"),
						      rcDontAskAgain);
	      if(answer == KMessageBox::Yes)
	        {
		  atLeastOneStringFound = true;
		  TQString msg = entry.message(entry.capturedText(line),
					      entry.lineNumber(line),
					      entry.columnNumber(line));

		  if(!*item)
		    *item =  new TDEListViewItem(rv);
		  TDEListViewItem* tempItem = new TDEListViewItem(*item);
		  tempItem->setMultiLinesEnabled(true);
		  tempItem->setText(0,msg);
		  occur ++;
		  entry.updateLine(line);
		  entry.incPos();
		}
              else
	        {
		  entry.incPos();
		}
              if(dontAskAgain()) askConfirmReplace = false;
	     }
	   else
	     {
	       atLeastOneStringFound = true;
	       TQString msg = entry.message(entry.capturedText(line),
					   entry.lineNumber(line),
					   entry.columnNumber(line));

	       if(!*item)
		 *item =  new TDEListViewItem(rv);
	       TDEListViewItem* tempItem = new TDEListViewItem(*item);
	       tempItem->setMultiLinesEnabled(true);
	       tempItem->setText(0,msg);
	       occur ++;
	       entry.updateLine(line);
	       entry.incPos();
	     }

        }
    }
}

void TDEFileReplacePart::fileSearch(const TQString& directoryName, const TQString& filters)
{
  TQDir d(directoryName);

  d.setMatchAllDirs(true);
  d.setFilter(m_optionMask);

  TQStringList filesList = d.entryList(filters);
  TQString filePath = d.canonicalPath();
  TQStringList::iterator filesIt;
  uint filesNumber = 0;

  m_view->displayScannedFiles(0, filesNumber);

  for (filesIt = filesList.begin(); filesIt != filesList.end() ; ++filesIt)
    {
      // We pushed stop button
      if(m_stop)
        break;

      TQString fileName = (*filesIt);

      // Avoids files that not match
      if(!TDEFileReplaceLib::isAnAccessibleFile(filePath, fileName, m_option))
        continue;

      TQFileInfo fileInfo(filePath+"/"+fileName);
      if(fileInfo.isDir())
        continue;
      kapp->processEvents();
      search(filePath, fileName);
      filesNumber++;
      m_view->displayScannedFiles(0, filesNumber);
    }
    m_view->displayScannedFiles(1, filesNumber);
}

void TDEFileReplacePart::recursiveFileSearch(const TQString &directoryName, const TQString &filters,
                                             int &foldersNumber, int &filesNumber, int depth)
{
  // if m_stop == true or the max depth level is reached, then interrupt recursion
  if (m_stop || (m_option->m_limitDepth && depth > m_option->m_maxDepth))
    return;
  else if (!m_option->m_limitDepth && depth > CIRCULAR_LINK_DETECTION_LEVEL)
    {
      if (!m_circ_ref_warning_shown)
        {
          KMessageBox::information(m_w,
              i18n("It seems you have a circular reference in your file system. "
                  "The search has been limited to this sublevel to prevent "
                  "TDEFileReplace from crashing."),
              i18n("Circular reference detected"));
          m_circ_ref_warning_shown = true;
        }
      return;
    }  
  
  TQDir d(directoryName);

  d.setMatchAllDirs(true);
  d.setFilter(m_optionMask);

  TQStringList filesList = d.entryList(filters);
  TQString filePath = d.canonicalPath();
  TQStringList::iterator filesIt;

  for (filesIt = filesList.begin(); filesIt != filesList.end(); ++filesIt)
    {
      if (m_stop)
        break;

      TQString fileName = (*filesIt);
      // Avoids files that not match
      if (!TDEFileReplaceLib::isAnAccessibleFile(filePath, fileName, m_option))
        continue;

      // Composes file path string
      TQFileInfo fileInfo(filePath+"/"+fileName);

      m_view->displayScannedFiles(foldersNumber, filesNumber);

      kapp->processEvents();
      // Searchs recursively if "filePath" is a directory and we have not reached the max depth level
      if (fileInfo.isDir())
        { 
          if (!m_option->m_limitDepth || depth < m_option->m_maxDepth)
            {
            recursiveFileSearch(filePath+"/"+fileName, filters, foldersNumber, filesNumber, depth+1);
            }
        }  
      else
        {
          search(filePath, fileName);
          filesNumber++;
          m_view->displayScannedFiles(foldersNumber, filesNumber);
        }
    }
    
  foldersNumber++;
  m_view->displayScannedFiles(foldersNumber, filesNumber);
}

void TDEFileReplacePart::search(const TQString& currentDir, const TQString& fileName)
{
  TQFile file(currentDir+"/"+fileName);

  if(!file.open(IO_ReadOnly))
    {
      KMessageBox::information(m_w, i18n("<qt>Cannot open file <b>%1</b> for reading.</qt>").arg(fileName), TQString(), rcNotifyOnErrors);
      return ;
    }
  // Creates a stream with the file
  TQTextStream stream( &file );
  if (m_option->m_encoding == "utf8")
    stream.setEncoding(TQTextStream::UnicodeUTF8);
  else
    stream.setCodec(TQTextCodec::codecForName(m_option->m_encoding.ascii()));
  TQString line = stream.read();
  file.close();

  TQFileInfo fileInfo(currentDir+"/"+fileName);

  TDEListViewItem *item = 0;
 
  //Counts occurrences
  int occurrence = 0;

  //This map contains strings to search
  KeyValueMap tempMap = m_replacementMap;
  //If no strings has been found, then no lines will be added to the result view
  bool atLeastOneStringFound = false;

  KeyValueMap::Iterator it = tempMap.begin();

  TDEListView* rv = m_view->getResultsView();

  while(it != tempMap.end())
    {
      //stop polling
      if(m_stop)
        break;

      TQString key = it.key();
      TQString strKey;
      TQRegExp rxKey;

      if(m_option->m_regularExpressions)
        rxKey = TQRegExp("("+key+")", m_option->m_caseSensitive, false);
      else
        strKey = key;
      /* If this option is true then for any string in
      *  the map we search for the first match*/
      if(m_option->m_haltOnFirstOccur)
        {
          int pos;

          if(m_option->m_regularExpressions)
            pos = line.find(rxKey);
          else
            pos = line.find(strKey, 0 ,m_option->m_caseSensitive);

          if(pos != -1)
            {
              atLeastOneStringFound = true;
              int lineNumber = line.mid(0,pos).contains('\n')+1;
              int columnNumber = pos - line.findRev('\n',pos);

              if (!item)
                item = new TDEListViewItem(rv);

              TDEListViewItem* tempItem= new TDEListViewItem(item);
              TQString msg,
                      capturedText;

              if(m_option->m_regularExpressions)
                capturedText = rxKey.cap(1);
              else
                capturedText = line.mid(pos,strKey.length());

	      msg = i18n("Line:%2, Col:%3 - \"%1\"").arg(capturedText).arg(TQString::number(lineNumber,10)).arg(TQString::number(columnNumber,10));
              tempItem->setMultiLinesEnabled(true);
              tempItem->setText(0,msg);
              occurrence = 1;
            }
        }// ends m_option->m_haltOnFirstOccur if-block
      else
        {
          /* This point of the code is reached when we must search for all
	  *  occurrences of all the strings*/

          int pos = 0;
          if(m_option->m_regularExpressions)
            pos = rxKey.search(line,pos);
          else
            pos = line.find(strKey, pos ,m_option->m_caseSensitive);

          while(pos != -1)
            {
              //stop polling
              if(m_stop)
                break;

              atLeastOneStringFound = true;
              TQString msg,
                      capturedText;
              int lineNumber = line.mid(0,pos).contains('\n')+1;
              int columnNumber = pos - line.findRev('\n',pos);

              if(m_option->m_regularExpressions)
                {
                  capturedText = rxKey.cap(1);
                  pos = rxKey.search(line, pos+rxKey.matchedLength());
                }
              else
                {
                  capturedText = line.mid(pos,strKey.length());
                  pos = line.find(strKey,pos+strKey.length());
                }

              msg = i18n("Line:%2, Col:%3 - \"%1\"").arg(capturedText).arg(TQString::number(lineNumber,10)).arg(TQString::number(columnNumber,10));

              if(!item)
                 item = new TDEListViewItem(rv);
              TDEListViewItem* tempItem = new TDEListViewItem(item);
              tempItem->setMultiLinesEnabled(true);
              tempItem->setText(0,msg);
              occurrence++;
              //we push stop button
              if(m_stop)
                break;
            }
        }
      //Advances of one position in the strings map
      ++it;

      //we push stop button
      if(m_stop)
        break;
    }

   //if ignoreFiles == false then every files must be show
   if(!m_option->m_ignoreFiles)
     atLeastOneStringFound = true;

   if(atLeastOneStringFound && item)
     {
       TDEFileReplaceLib::setIconForFileEntry(item,currentDir+"/"+fileName);
       item->setText(0,fileName);
       item->setText(1,currentDir);
       item->setText(2,TDEFileReplaceLib::formatFileSize(fileInfo.size()));
       item->setText(3,TQString::number(occurrence,10));
       item->setText(4,TQString("%1[%2]").arg(fileInfo.owner()).arg(fileInfo.ownerId()));
       item->setText(5,TQString("%1[%2]").arg(fileInfo.group()).arg(fileInfo.groupId()));
     }
}

void TDEFileReplacePart::loadViewContent()
{
  /* Maps the content of the strings view to a TQMap */
  KeyValueMap tempMap;
  CommandEngine command;

  TQListViewItemIterator itlv(m_view->getStringsView());
  while(itlv.current())
    {
      TQListViewItem *item = itlv.current();
      if(m_option->m_variables)
        tempMap[item->text(0)] = command.variableValue(item->text(1));
      else
        tempMap[item->text(0)] = item->text(1);
      ++itlv;
    }
  m_replacementMap = tempMap;
}

bool TDEFileReplacePart::launchNewProjectDialog(const KURL & startURL)
{
  if(!startURL.isEmpty())
    m_option->m_directories.prepend(startURL.path());
  
  /* This dlg reads options from m_option, then execs, finally returns options.*/
  KNewProjectDlg dlg(m_option);

  if(!dlg.exec())
    return false;
  
  dlg.saveRCOptions();

  m_config->sync();

  slotQuickStringsAdd();

  m_view->updateOptions(m_option);

  updateGUI();

  return true;
}

void TDEFileReplacePart::setOptionMask()
{
  m_optionMask |= TQDir::Dirs;

  if(!m_option->m_ignoreHidden)
    m_optionMask |= TQDir::Hidden;

  if(!m_option->m_followSymLinks)
    m_optionMask |= TQDir::NoSymLinks;
}

bool TDEFileReplacePart::checkBeforeOperation()
{
  loadViewContent();
  TDEListView* sv = m_view->getStringsView();

  // Checks if there are strings to replace (not need in search operation)
  if (sv->childCount() == 0)
    {
      KMessageBox::error(m_w, i18n("There are no strings to search and replace."));
      return false;
    }

  // Checks if the main directory can be accessed
  TQString currentDirectory = m_option->m_directories[0];
  TQDir dir;

  dir.setPath(currentDirectory);
  TQString directory = dir.absPath();

  if(!dir.exists())
    {
      KMessageBox::error(m_w, i18n("<qt>The main folder of the project <b>%1</b> does not exist.</qt>").arg(directory));
      return false;
    }

  TQFileInfo dirInfo(directory);
  if(!(dirInfo.isReadable() && dirInfo.isExecutable())
       || (!m_option->m_searchingOnlyMode && !m_option->m_simulation && !(dirInfo.isWritable())))
    {
      KMessageBox::error(m_w, i18n("<qt>Access denied in the main folder of the project:<br><b>%1</b></qt>").arg(directory));
      return false;
    }

  // Clears the list view
  m_view->getResultsView()->clear();

  return true;
}

bool TDEFileReplacePart::dontAskAgain()
{
  m_config->setGroup("Notification Messages");
  TQString dontAskAgain = m_config->readEntry(rcDontAskAgain, "no");
  if(dontAskAgain == "yes")
    return true;
  else
    return false;
}

void TDEFileReplacePart::whatsThis()
{
  actionCollection()->action("options_backup")->setWhatsThis(optionsBackupWhatthis);
  actionCollection()->action("options_case")->setWhatsThis(optionsCaseWhatthis);
  actionCollection()->action("options_var")->setWhatsThis(optionsVarWhatthis);
  actionCollection()->action("options_recursive")->setWhatsThis(optionsRecursiveWhatthis);
  actionCollection()->action("options_regularexpressions")->setWhatsThis(optionsRegularExpressionsWhatthis);
}

#include "tdefilereplacepart.moc"
