1
/***************************************************************
2
* Name: ThreadSearchThread
4
* Purpose: This class implements the search worker thread.
5
* It sends events to the view when one or more
6
* search pattern is (are) found in a file.
7
* It derives from wxDirTraverser to test thread
8
* cancel when searching in directory.
9
* One event/file is sent.
11
* Author: Jerome ANTOINE
13
* Copyright: Jerome ANTOINE
15
**************************************************************/
20
#include "configmanager.h"
21
#include "projectbuildtarget.h"
24
#include "cbauibook.h"
26
#include "ThreadSearchThread.h"
27
#include "ThreadSearchEvent.h"
28
#include "TextFileSearcher.h"
30
ThreadSearchThread::ThreadSearchThread(ThreadSearchView* pThreadSearchView,
31
const ThreadSearchFindData& findData)
33
m_pThreadSearchView = pThreadSearchView;
34
m_FindData = findData;
36
// If wxDIR_IGNORE is used, we don't recurse in sub directories during directory search
37
m_DefaultDirResult = (findData.GetRecursiveSearch() == true) ? wxDIR_CONTINUE : wxDIR_IGNORE;
39
// File patterns separator is ';'
40
m_Masks = GetArrayFromString(m_FindData.GetSearchMask());
41
if ( m_Masks.GetCount() == 0 )
45
m_pTextFileSearcher = TextFileSearcher::BuildTextFileSearcher(findData.GetFindText(),
46
findData.GetMatchCase(),
47
findData.GetStartWord(),
48
findData.GetMatchWord(),
50
if (!m_pTextFileSearcher)
52
ThreadSearchEvent event(wxEVT_THREAD_SEARCH_ERROR, -1);
53
event.SetString(_("TextFileSearcher could not be instantiated."));
55
// Using wxPostEvent, we avoid multi-threaded memory violation.
56
wxPostEvent( m_pThreadSearchView,event);
58
ConfigManager* pCfg = Manager::Get()->GetConfigManager(_T("ThreadSearch"));
59
m_ShowFileMissingError=pCfg->ReadBool(wxT("/ShowFileMissingError"),true);
60
m_ShowCantOpenFileError=pCfg->ReadBool(wxT("/ShowCantOpenFileError"),true);
65
ThreadSearchThread::~ThreadSearchThread()
68
if ( m_pTextFileSearcher != NULL )
70
delete m_pTextFileSearcher;
75
void *ThreadSearchThread::Entry()
77
// Tests if we have a working searcher object.
78
// Cancel search if it is not the case
79
if ( m_pTextFileSearcher == NULL )
84
// For now, we look for all paths for the different search scopes
85
// and store them in a sorted array to avoid pasing several times
87
// This will be changed to avoid consuming a lot of memory (parsing
88
// form C:\ and storing all paths...). Aim is to avoid the use of the
89
// array for storing items.
91
// Search in directory files ?
92
if ( m_FindData.MustSearchInDirectory() == true )
94
int flags = wxDIR_FILES | wxDIR_DIRS | wxDIR_DOTDOT;
95
flags |= m_FindData.GetHiddenSearch() ? wxDIR_HIDDEN : 0;
97
const wxString &path = m_FindData.GetSearchPath(true);
98
if (!wxDir::Exists(path))
100
ThreadSearchEvent event(wxEVT_THREAD_SEARCH_ERROR, -1);
101
event.SetString(_("Cannot open folder ") + path);
103
// Using wxPostEvent, we avoid multi-threaded memory violation.
104
wxPostEvent(m_pThreadSearchView,event);
110
Dir.Traverse(*(static_cast<wxDirTraverser*>(this)), wxEmptyString, flags);
113
// Tests thread stop (cancel search, app shutdown)
114
if ( TestDestroy() == true ) return 0;
117
// Search in workspace files ?
118
if ( m_FindData.MustSearchInWorkspace() == true )
120
ProjectsArray* pProjectsArray = Manager::Get()->GetProjectManager()->GetProjects();
121
for ( size_t j=0; j < pProjectsArray->GetCount(); ++j )
123
AddProjectFiles(m_FilePaths, *pProjectsArray->Item(j));
124
if ( TestDestroy() == true ) return 0;
127
else if ( m_FindData.MustSearchInProject() == true )
129
// Search in project files ?
130
// Necessary only if not already parsed in worspace part
131
cbProject* pProject = Manager::Get()->GetProjectManager()->GetActiveProject();
132
if ( pProject != NULL )
134
AddProjectFiles(m_FilePaths, *pProject);
135
if ( TestDestroy() == true ) return 0;
138
else if ( m_FindData.MustSearchInTarget() == true )
140
// Search in target files ?
141
// Necessary only if not already parsed in project part
142
cbProject* pProject = Manager::Get()->GetProjectManager()->GetActiveProject();
143
if ( pProject != NULL )
145
ProjectBuildTarget *pTarget = pProject->GetBuildTarget(pProject->GetActiveBuildTarget());
148
AddTargetFiles(m_FilePaths, *pTarget);
149
if ( TestDestroy() == true ) return 0;
154
// Tests thread stop (cancel search, app shutdown)
155
if ( TestDestroy() == true ) return 0;
158
if ( m_FindData.MustSearchInOpenFiles() == true )
160
EditorManager* pEdManager = Manager::Get()->GetEditorManager();
161
for (i = 0; i < (size_t)pEdManager->GetNotebook()->GetPageCount(); ++i)
163
cbEditor* pEditor = pEdManager->GetBuiltinEditor(i);
164
if ( pEditor != NULL )
166
AddNewItem(m_FilePaths, pEditor->GetFilename());
171
// Tests thread stop (cancel search, app shutdown)
172
if ( TestDestroy() == true ) return 0;
174
// if the list is empty, leave
175
if (m_FilePaths.GetCount() == 0)
177
//-cbMessageBox(wxT("No files to search in!"), wxT("Error"), wxICON_WARNING);
178
////(pecan 2008/4/26)
179
// DO NOT issue graphics calls from this thread !!!!!!
180
ThreadSearchEvent event(wxEVT_THREAD_SEARCH_ERROR, -1);
181
event.SetString(_("No files to search.\nCheck options "));
182
// Using wxPostEvent, we avoid multi-threaded memory violation.
183
wxPostEvent(m_pThreadSearchView,event);
187
for ( i = 0; i < m_FilePaths.GetCount(); ++i )
189
FindInFile(m_FilePaths[i]);
191
// Tests thread stop (cancel search, app shutdown)
192
if ( TestDestroy() == true ) return 0;
199
void ThreadSearchThread::OnExit()
201
// Method is called automatically by wxWidgets framework
202
// We inform thread caller about its termination.
203
m_pThreadSearchView->OnThreadExit();
207
wxDirTraverseResult ThreadSearchThread::OnDir(const wxString& WXUNUSED(dirName))
209
// Method is just used to test thread termination (user cancelled) and
210
// stop recursive dir traversing if it is not required.
211
if ( TestDestroy() == true )
215
return m_DefaultDirResult;
219
wxDirTraverseResult ThreadSearchThread::OnFile(const wxString& fileName)
221
// Tests thread termination (user cancelled)
222
if ( TestDestroy() == true )
227
// Looks if current file matches one of the file patterns
228
for (size_t i = 0; i < m_Masks.GetCount(); ++i)
230
if ( fileName.Matches(m_Masks[i].c_str() ) )
232
// Adds it to list of files to parse
233
m_FilePaths.Add(fileName);
238
return wxDIR_CONTINUE;
242
void ThreadSearchThread::FindInFile(const wxString& path)
244
m_LineTextArray.Empty();
246
switch ( m_pTextFileSearcher->FindInFile(path, m_LineTextArray) )
248
case TextFileSearcher::idStringFound:
250
ThreadSearchEvent event(wxEVT_THREAD_SEARCH, -1);
251
event.SetString(path);
252
event.SetLineTextArray(m_LineTextArray);
254
// Using wxPostEvent, we avoid multi-threaded memory violation.
255
m_pThreadSearchView->PostThreadSearchEvent(event);
258
case TextFileSearcher::idStringNotFound:
262
case TextFileSearcher::idFileNotFound:
264
if(m_ShowFileMissingError)
266
ThreadSearchEvent event(wxEVT_THREAD_SEARCH_ERROR, -1);
267
event.SetString(path + _(" does not exist."));
269
// Using wxPostEvent, we avoid multi-threaded memory violation.
270
wxPostEvent( m_pThreadSearchView,event);
274
case TextFileSearcher::idFileOpenError:
276
if(m_ShowCantOpenFileError)
278
ThreadSearchEvent event(wxEVT_THREAD_SEARCH_ERROR, -1);
279
event.SetString(_("Failed to open ") + path);
281
// Using wxPostEvent, we avoid multi-threaded memory violation.
282
wxPostEvent( m_pThreadSearchView,event);
293
bool ThreadSearchThread::AddNewItem(wxSortedArrayString& sortedArrayString, const wxString& newItem)
295
// Adds item to array only if it does not exist
297
if ( sortedArrayString.Index(newItem.c_str()) == wxNOT_FOUND )
299
sortedArrayString.Add(newItem);
306
void ThreadSearchThread::AddProjectFiles(wxSortedArrayString& sortedArrayString, cbProject& project)
308
// Adds project file paths to array only if they do not already exist.
309
// Same path may exist if we parse both open files and project files
311
for (FilesList::iterator it = project.GetFilesList().begin(); it != project.GetFilesList().end(); ++it)
313
AddNewItem(sortedArrayString, (*it)->file.GetFullPath());
314
if ( TestDestroy() == true ) return;
319
void ThreadSearchThread::AddTargetFiles(wxSortedArrayString& sortedArrayString, ProjectBuildTarget& target)
321
// Adds target file paths to array only if they do not already exist.
322
// Same path may exist if we parse both open files and target files
324
for (FilesList::iterator it = target.GetFilesList().begin(); it != target.GetFilesList().end(); it++)
326
ProjectFile* pf = *it;
327
AddNewItem(sortedArrayString, pf->file.GetFullPath());
328
if ( TestDestroy() == true ) return;