You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1588 lines
52 KiB
1588 lines
52 KiB
//
|
|
//
|
|
// 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, TQ_SIGNAL(updateGUI()), this, TQ_SLOT(updateGUI()));
|
|
|
|
// File
|
|
(void)new TDEAction(i18n("Customize Search/Replace Session..."), "projectopen", TDEShortcut(CTRL + Key_F), this, TQ_SLOT(slotSetNewParameters()), actionCollection(), "new_project");
|
|
(void)new TDEAction(i18n("&Search"), "filesearch", 0, this, TQ_SLOT(slotSearchingOperation()), actionCollection(), "search");
|
|
(void)new TDEAction(i18n("S&imulate"), "filesimulate", 0, this, TQ_SLOT(slotSimulatingOperation()), actionCollection(), "file_simulate");
|
|
(void)new TDEAction(i18n("&Replace"), "filereplace", 0, this, TQ_SLOT(slotReplacingOperation()), actionCollection(), "replace");
|
|
(void)new TDEAction(i18n("Sto&p"), "process-stop", 0, this, TQ_SLOT(slotStop()), actionCollection(), "stop");
|
|
(void)new TDEAction(i18n("Cre&ate Report File..."), "document-save-as", 0, this, TQ_SLOT(slotCreateReport()), actionCollection(), "results_create_report");
|
|
(void)new TDEAction(i18n("&Save Results List to File..."), "document-save-as", 0, m_view, TQ_SLOT(slotResultSave()), actionCollection(), "results_save");
|
|
(void)new TDEAction(i18n("&Load Results List From File..."), "unsortedList", 0, m_view, TQ_SLOT(slotResultLoad()), actionCollection(), "results_load");
|
|
|
|
// Strings
|
|
(void)new TDEAction(i18n("&Add String..."), "editadd", 0, m_view, TQ_SLOT(slotStringsAdd()), actionCollection(), "strings_add");
|
|
(void)new TDEAction(i18n("&Delete String"), "editremove", 0, m_view, TQ_SLOT(slotStringsDeleteItem()), actionCollection(), "strings_del");
|
|
(void)new TDEAction(i18n("&Empty Strings List"), "edit-delete", 0, m_view, TQ_SLOT(slotStringsEmpty()), actionCollection(), "strings_empty");
|
|
(void)new TDEAction(i18n("&Save Strings List to File..."), "document-save-as", 0, m_view, TQ_SLOT(slotStringsSave()), actionCollection(), "strings_save");
|
|
(void)new TDEAction(i18n("&Load Strings List From File..."), "unsortedList", 0, m_view, TQ_SLOT(slotStringsLoad()), actionCollection(), "strings_load");
|
|
(void)new TDEAction(i18n("&Invert Current String (search <--> replace)"), "invert", 0, m_view, TQ_SLOT(slotStringsInvertCur()), actionCollection(), "strings_invert");
|
|
(void)new TDEAction(i18n("&Invert All Strings (search <--> replace)"), "invert", 0, m_view, TQ_SLOT(slotStringsInvertAll()), actionCollection(), "strings_invert_all");
|
|
|
|
// Options
|
|
(void)new TDEToggleAction(i18n("&Include Sub-Folders"), "recursive_option", 0, this, TQ_SLOT(slotOptionRecursive()), actionCollection(), "options_recursive");
|
|
(void)new TDEToggleAction(i18n("Create &Backup Files"), "backup_option", 0, this, TQ_SLOT(slotOptionBackup()), actionCollection(), "options_backup");
|
|
(void)new TDEToggleAction(i18n("Case &Sensitive"), "casesensitive_option", 0, this, TQ_SLOT(slotOptionCaseSensitive()), actionCollection(), "options_case");
|
|
(void)new TDEToggleAction(i18n("Enable Commands &in Replace String: [$command:option$]"), "command_option", 0, this, TQ_SLOT(slotOptionVariables()), actionCollection(), "options_var");
|
|
(void)new TDEToggleAction(i18n("Enable &Regular Expressions"), "regularexpression_option", 0, this, TQ_SLOT(slotOptionRegularExpressions()), actionCollection(), "options_regularexpressions");
|
|
(void)new TDEAction(i18n("Configure &TDEFileReplace..."), "configure", 0, this, TQ_SLOT(slotOptionPreferences()), actionCollection(), "configure_tdefilereplace");
|
|
|
|
// Results
|
|
(void)new TDEAction(i18n("&Properties"), "informations", 0, m_view, TQ_SLOT(slotResultProperties()), actionCollection(), "results_infos");
|
|
(void)new TDEAction(i18n("&Open"), "document-open", 0, m_view, TQ_SLOT(slotResultOpen()), actionCollection(), "results_openfile");
|
|
(void)new TDEAction(i18n("Open &With..."), "document-open", 0, m_view, TQ_SLOT(slotResultOpenWith()), actionCollection(), "results_openfilewith");
|
|
if(quantaFound)
|
|
{
|
|
(void)new TDEAction(i18n("&Edit in Quanta"), "quanta", 0, m_view, TQ_SLOT(slotResultEdit()), actionCollection(), "results_editfile");
|
|
}
|
|
(void)new TDEAction(i18n("Open Parent &Folder"), "go-up", 0, m_view, TQ_SLOT(slotResultDirOpen()), actionCollection(), "results_opendir");
|
|
(void)new TDEAction(i18n("Remove &Entry"), "edit-clear", 0, m_view, TQ_SLOT(slotResultRemoveEntry()), actionCollection(), "results_removeentry");
|
|
(void)new TDEAction(i18n("&Delete"), "edit-delete", 0, m_view, TQ_SLOT(slotResultDelete()), actionCollection(), "results_delete");
|
|
(void)new TDEAction(i18n("E&xpand Tree"), 0, m_view, TQ_SLOT(slotResultTreeExpand()), actionCollection(), "results_treeexpand");
|
|
(void)new TDEAction(i18n("&Reduce Tree"), 0, m_view, TQ_SLOT(slotResultTreeReduce()), actionCollection(), "results_treereduce");
|
|
|
|
// Help
|
|
(void)new TDEAction(i18n("&About TDEFileReplace"), "tdefilereplace", 0, this, TQ_SLOT(showAboutApplication()), actionCollection(), "help_about_tdefilereplace");
|
|
(void)new TDEAction(i18n("TDEFileReplace &Handbook"), "help", 0, this, TQ_SLOT(appHelpActivated()), actionCollection(), "help_tdefilereplace");
|
|
(void)new TDEAction(i18n("&Report Bug"), 0, 0, this, TQ_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(¤tFile);
|
|
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"
|