예제 #1
0
void FindResultsTab::OnRepeatOutput(wxCommandEvent& e)
{
    wxUnusedVar(e);
    SearchData* searchData = GetSearchData();
    searchData->UseNewTab(false);
    SearchThreadST::Get()->PerformSearch(*searchData);
}
예제 #2
0
void FindInFilesDialog::DoSearchReplace()
{
    SearchData data = DoGetSearchData();
    data.SetOwner(clMainFrame::Get()->GetOutputPane()->GetReplaceResultsTab());
    DoSaveOpenFiles();
    SearchThreadST::Get()->PerformSearch(data);
    Close();
}
예제 #3
0
void FindResultsTab::OnSearchMatch(wxCommandEvent& e)
{
    SearchResultList* res = (SearchResultList*)e.GetClientData();
    if(!res) return;

    int m = m_book ? m_book->GetPageIndex(m_recv) : 0;
    if(m == wxNOT_FOUND) {
        wxDELETE(res);
        return;
    }

    MatchInfo& matchInfo = GetMatchInfo(m);
    for(SearchResultList::iterator iter = res->begin(); iter != res->end(); iter++) {
        if(matchInfo.empty() || matchInfo.rbegin()->second.GetFileName() != iter->GetFileName()) {
            if(!matchInfo.empty()) {
                AppendText("\n");
            }
            wxFileName fn(iter->GetFileName());
            fn.MakeRelativeTo();
            AppendText(fn.GetFullPath() + wxT("\n"));
        }

        int lineno = m_recv->GetLineCount() - 1;
        matchInfo.insert(std::make_pair(lineno, *iter));
        wxString text = iter->GetPattern();
        int delta = -text.Length();
        text.Trim(false);
        delta += text.Length();
        text.Trim();

        wxString linenum;
        if(iter->GetMatchState() == CppWordScanner::STATE_CPP_COMMENT ||
           iter->GetMatchState() == CppWordScanner::STATE_C_COMMENT)
            linenum = wxString::Format(wxT(" %5u //"), iter->GetLineNumber());
        else
            linenum = wxString::Format(wxT(" %5u "), iter->GetLineNumber());

        SearchData* d = GetSearchData(m_recv);
        // Print the scope name
        if(d->GetDisplayScope()) {
            TagEntryPtr tag = TagsManagerST::Get()->FunctionFromFileLine(iter->GetFileName(), iter->GetLineNumber());
            wxString scopeName(wxT("global"));
            if(tag) {
                scopeName = tag->GetPath();
            }

            linenum << wxT("[ ") << scopeName << wxT(" ] ");
            iter->SetScope(scopeName);
        }

        delta += linenum.Length();
        AppendText(linenum + text + wxT("\n"));
        m_recv->IndicatorFillRange(m_sci->PositionFromLine(lineno) + iter->GetColumn() + delta, iter->GetLen());
    }
    wxDELETE(res);
}
예제 #4
0
void FindInFilesDialog::DoSearch()
{
    SearchData data = DoGetSearchData();
    data.SetOwner(clMainFrame::Get()->GetOutputPane()->GetFindResultsTab());

    // check to see if we require to save the files
    DoSaveOpenFiles();
    SearchThreadST::Get()->PerformSearch(data);
    Close();
}
void ReplaceInFilesPanel::OnSearchStart(wxCommandEvent& e)
{
    e.Skip();
    // set the "Replace With" field with the user value
    SearchData* data = (SearchData*)e.GetClientData();
    m_replaceWith->ChangeValue(data->GetReplaceWith());

    //
    FindResultsTab::OnSearchStart(e);
}
예제 #6
0
void SearchThread::ProcessRequest(ThreadRequest *req)
{
    wxStopWatch sw;
    m_summary = SearchSummary();
    DoSearchFiles(req);
    m_summary.SetElapsedTime(sw.Time());

    SearchData *sd = (SearchData*)req;
    // Send search end event
    SendEvent(wxEVT_SEARCH_THREAD_SEARCHEND, sd->GetOwner());
}
예제 #7
0
void SearchOperation::doSearch( SearchData& searchData, qint64 initialLine )
{
    const qint64 nbSourceLines = sourceLogData_->getNbLine();
    int maxLength = 0;
    int nbMatches = searchData.getNbMatches();
    SearchResultArray currentList = SearchResultArray();

    // Ensure no re-alloc will be done
    currentList.reserve( nbLinesInChunk );

    LOG(logDEBUG) << "Searching from line " << initialLine << " to " << nbSourceLines;

    if (initialLine < startLine_) {
        initialLine = startLine_;
    }

    const qint64 endLine = qMin(nbSourceLines, endLine_);

    for ( qint64 i = initialLine; i < endLine; i += nbLinesInChunk ) {
        if ( *interruptRequested_ )
            break;

        const int percentage = ( i - initialLine ) * 100 / ( endLine - initialLine );
        emit searchProgressed( nbMatches, percentage );

        const QStringList lines = sourceLogData_->getLines( i,
                qMin( nbLinesInChunk, (int) ( endLine - i ) ) );
        LOG(logDEBUG) << "Chunk starting at " << i <<
            ", " << lines.size() << " lines read.";

        int j = 0;
        for ( ; j < lines.size(); j++ ) {
            if ( regexp_.match( lines[j] ).hasMatch() ) {
                // FIXME: increase perf by removing temporary
                const int length = sourceLogData_->getExpandedLineString(i+j).length();
                if ( length > maxLength )
                    maxLength = length;
                currentList.push_back( MatchingLine( i+j ) );
                nbMatches++;
            }
        }

        // After each block, copy the data to shared data
        // and update the client
        searchData.addAll( maxLength, currentList, i+j );
        currentList.clear();
    }

    emit searchProgressed( nbMatches, 100 );
}
// Called in the worker thread's context
void FullSearchOperation::start( SearchData& searchData )
{
    // Clear the shared data
    searchData.clear();

    doSearch( searchData, 0 );
}
예제 #9
0
void FindResultsTab::OnSearchMatch(wxCommandEvent& e)
{
    SearchResultList* res = (SearchResultList*)e.GetClientData();
    if(!res) return;

    SearchResultList::iterator iter = res->begin();
    for(; iter != res->end(); ++iter) {
        if(m_matchInfo.empty() || m_matchInfo.rbegin()->second.GetFileName() != iter->GetFileName()) {
            if(!m_matchInfo.empty()) {
                AppendText("\n");
            }
            wxFileName fn(iter->GetFileName());
            fn.MakeRelativeTo();
            AppendText(fn.GetFullPath() + wxT("\n"));
        }

        int lineno = m_sci->GetLineCount() - 1;
        m_matchInfo.insert(std::make_pair(lineno, *iter));
        wxString text = iter->GetPattern();
        // int delta = -text.Length();
        // text.Trim(false);
        // delta += text.Length();
        // text.Trim();

        wxString linenum = wxString::Format(wxT(" %5u: "), iter->GetLineNumber());
        SearchData* d = GetSearchData();
        // Print the scope name
        if(d->GetDisplayScope()) {
            TagEntryPtr tag = TagsManagerST::Get()->FunctionFromFileLine(iter->GetFileName(), iter->GetLineNumber());
            wxString scopeName(wxT("global"));
            if(tag) {
                scopeName = tag->GetPath();
            }

            linenum << wxT("[ ") << scopeName << wxT(" ] ");
            iter->SetScope(scopeName);
        }

        AppendText(linenum + text + wxT("\n"));
        int indicatorStartPos = m_sci->PositionFromLine(lineno) + iter->GetColumn() + linenum.Length();
        int indicatorLen = iter->GetLen();
        m_indicators.push_back(indicatorStartPos);
        m_sci->IndicatorFillRange(indicatorStartPos, indicatorLen);
    }
    wxDELETE(res);
}
예제 #10
0
void FindResultsTab::OnRepeatOutput(wxCommandEvent& e)
{
    wxUnusedVar(e);

    if(m_book) {
        int sel = m_book->GetSelection();
        if(sel != wxNOT_FOUND) {
            // get the search data used to generate the output on the selected tab
            wxWindow* tab = m_book->GetPage(sel);
            if(tab) {
                SearchData* searchData = (SearchData*)tab->GetClientData();
                searchData->UseNewTab(false);
                SearchThreadST::Get()->PerformSearch(*searchData);
            }
        }
    }
}
예제 #11
0
void FindResultsTab::OnSearchStart(wxCommandEvent& e)
{
    m_searchInProgress = true;
    Clear();
    SetStyles(m_sci);
    SearchData* data = (SearchData*)e.GetClientData();
    if(data) {
        m_searchData = *data;

        wxString message;
        message << _("====== Searching for: '") << data->GetFindString() << _("'; Match case: ")
                << (data->IsMatchCase() ? _("true") : _("false")) << _(" ; Match whole word: ")
                << (data->IsMatchWholeWord() ? _("true") : _("false")) << _(" ; Regular expression: ")
                << (data->IsRegularExpression() ? _("true") : _("false")) << wxT(" ======\n");
        AppendText(message);
    }
    wxDELETE(data);
}
예제 #12
0
void FindResultsTab::OnSearchStart(wxCommandEvent& e)
{
    m_searchInProgress = true;
    SearchData* data = (SearchData*)e.GetClientData();
    wxString label = data ? data->GetFindString() : wxT("");

    if(e.GetInt() != 0 || m_sci == NULL) {
        if(m_book) {
            clWindowUpdateLocker locker(this);
            MySTC* sci = new MySTC(m_book);
            SetStyles(sci);
            sci->Connect(wxEVT_STC_STYLENEEDED, wxStyledTextEventHandler(FindResultsTab::OnStyleNeeded), NULL, this);
            m_book->AddPage(sci, label, true);
#ifdef __WXMAC__
            m_book->GetSizer()->Layout();
#endif
            size_t where = m_book->GetPageCount() - 1;

            // keep the search data used for this tab
            wxWindow* tab = m_book->GetPage(where);
            if(tab) {
                tab->SetClientData(data);
            }

            m_matchInfo.push_back(MatchInfo());
            m_sci = sci;
        }
    } else if(m_book) {
        // using current tab, update the tab title and the search data
        int where = m_book->GetPageIndex(m_sci);
        if(where != wxNOT_FOUND) {
            m_book->SetPageText(where, label);
            // delete the old search data
            wxWindow* tab = m_book->GetPage(where);
            SearchData* oldData = (SearchData*)tab->GetClientData();
            if(oldData) {
                delete oldData;
            }
            // set the new search data
            tab->SetClientData(data);
        }
    }

    // This is needed in >=wxGTK-2.9, otherwise the 'Search' pane doesn't fully expand
    SendSizeEvent(wxSEND_EVENT_POST);

    m_recv = m_sci;
    Clear();

    if(data) {
        m_searchData = *data;

        wxString message;
        message << _("====== Searching for: '") << data->GetFindString() << _("'; Match case: ")
                << (data->IsMatchCase() ? _("true") : _("false")) << _(" ; Match whole word: ")
                << (data->IsMatchWholeWord() ? _("true") : _("false")) << _(" ; Regular expression: ")
                << (data->IsRegularExpression() ? _("true") : _("false")) << wxT(" ======\n");
        AppendText(message);
    }
}
예제 #13
0
SearchData TaskPanel::DoGetSearchData()
{
    SearchData data;
    data.SetDisplayScope(true);
    data.SetRegularExpression(true);
    data.SetMatchCase(false);
    data.SetMatchWholeWord(false);
    data.SetEncoding(m_choiceEncoding->GetStringSelection());
    data.SetOwner(this);

    wxString sfind;

    // Load all info from disk
    TasksPanelData d;
    EditorConfigST::Get()->ReadObject(wxT("TasksPanelData"), &d);

    wxStringMap_t::const_iterator iter = d.GetTasks().begin();
    for(; iter != d.GetTasks().end(); iter++) {
        wxString name = iter->first;
        wxString regex = iter->second;
        bool enabled = (d.GetEnabledItems().Index(iter->first) != wxNOT_FOUND);

        regex.Trim().Trim(false);
        wxRegEx re(regex);
        if(enabled && !regex.IsEmpty() && re.IsValid()) sfind << wxT("(") << regex << wxT(")|");
    }

    if(sfind.empty() == false) sfind.RemoveLast();

    data.SetFindString(sfind);

    wxString rootDir = clWorkspaceManager::Get().GetWorkspace()->GetFileName().GetPath();
    wxArrayString rootDirs;
    rootDirs.push_back(rootDir);
    data.SetRootDirs(rootDirs);
    data.SetExtensions(wxT("*.*"));
    return data;
}
예제 #14
0
// Called in the worker thread's context
void UpdateSearchOperation::start( SearchData& searchData )
{
    qint64 initial_line = initialPosition_;

    if ( initial_line >= 1 ) {
        // We need to re-search the last line because it might have
        // been updated (if it was not LF-terminated)
        --initial_line;
        // In case the last line matched, we don't want it to match twice.
        searchData.deleteMatch( initial_line );
    }

    doSearch( searchData, initial_line );
}
예제 #15
0
void SearchThread::DoSearchFiles(ThreadRequest *req)
{
    SearchData *data = static_cast<SearchData*>(req);

    // Get all files
    if ( data->GetRootDirs().IsEmpty() )
        return;

    if ( data->GetFindString().IsEmpty() )
        return;

    StopSearch(false);
    wxArrayString fileList;
    GetFiles(data, fileList);

    wxStopWatch sw;

    // Send startup message to main thread
    if ( m_notifiedWindow || data->GetOwner() ) {
        wxCommandEvent event(wxEVT_SEARCH_THREAD_SEARCHSTARTED, GetId());
        event.SetClientData(new SearchData(*data));
        //set the rquested output tab
        event.SetInt(data->UseNewTab() ? 1 : 0);
        if (data->GetOwner()) {
            ::wxPostEvent(data->GetOwner(), event);
        } else {
            // since we are in if ( m_notifiedWindow || data->GetOwner() ) block...
            ::wxPostEvent(m_notifiedWindow, event);
        }
    }

    for (size_t i=0; i<fileList.Count(); i++) {
        m_summary.SetNumFileScanned((int)i+1);

        // give user chance to cancel the search ...
        if ( TestStopSearch() ) {
            // Send cancel event
            SendEvent(wxEVT_SEARCH_THREAD_SEARCHCANCELED, data->GetOwner());
            StopSearch(false);
            break;
        }
        DoSearchFile(fileList.Item(i), data);
    }
}
예제 #16
0
/*code implements Greedy search*/
bool Design::greedy(int dest){
  #if DEBUG==3
    fprintf(debugfile_,"GREEDY");
    fprintf(debugfile_,"dest: %d\n",dest);
    fflush(debugfile_);
  #endif
  MinHeap<SearchData> openlist;
  CloseStructure* closelist=new CloseStructure[map_.numvert()];
  bool rc=false;
  Node<EdgeInfo>* currconnect;
  int nn;
  SearchData curr;
  SearchData tmp;
  curr.set(whichbox_,-1,0);  //start at current node, parent is -1.
                             //uniform cost so cost incurred so far is 0
  bool done=false;
  bool found=false;
  float biggestcost=0;
  int numclosed=0;
  do{
    #if DEBUG==3
    fprintf(debugfile_,"curr.nodenum: %d\n",curr.nodenum());
    fflush(debugfile_);
    #endif
    LList<EdgeInfo>& edgelist=map_.edges(curr.nodenum());  //get the conections to curr

    while(currconnect=edgelist.curr()){              //for each node connected to curr
      nn=currconnect->data().to();
      if(!closelist[nn].closed_){                     //if its not in the closed list
        #if DEBUG==3
        fprintf(debugfile_,"add to openlist: %d\n",nn);
        fflush(debugfile_);
        #endif
        tmp.set(nn,curr.nodenum(),timeleft(currconnect,dest));
        openlist.insert(tmp);
      }
      edgelist.gonext();
    }//while
    closelist[curr.nodenum()].closed_=true;  //add it to the close list
    closelist[curr.nodenum()].nodeinf_=curr;
    numclosed++;
    if(!openlist.isempty()){    //if there are still nodes to consider
      curr=openlist.remove();//remove lowest cost item from list
      #if DEBUG == 3
      fprintf(debugfile_,"removed from openlist: %d\n",curr.nodenum());
      fflush(debugfile_);
      #endif
      while(!openlist.isempty() && closelist[curr.nodenum()].closed_){            //if already encountered
        curr=openlist.remove();//remove lowest cost item from list  //consider the next node
      }
      if(closelist[curr.nodenum()].closed_){
        //only way to reach this part of code is if the open list is empty and 
        //we have not found the next node to examine
        done=true;
      }
      else{  
        if(curr.nodenum()==dest){
          found=true;       //found a node to the destination... question is, is it the best.
          biggestcost=curr.cost();
        }
        if(found && curr.cost() > biggestcost){
          done=true;
        }
      }//else still have node
    }//if list is not empty
    else{
      done=true;
    }//open list is empty
  }while(!done);
  if(found){ 
    rc=true;
    setPath(closelist,dest);
    delete [] closelist;
  }
    return rc;
}
예제 #17
0
bool operator<(const SearchData& left, const SearchData& right){
  bool rc=false;
  if(left.cost() < right.cost())
    rc=true;
  return rc;
}
SearchData FindInFilesDialog::DoGetSearchData()
{
    SearchData data;
    wxString findStr(m_data.GetFindString());
    if(!m_findString->GetValue().IsEmpty()) {
        findStr = m_findString->GetValue();
    }

    data.SetFindString(findStr);
    data.SetReplaceWith(m_replaceString->GetValue());

    m_data.SetFlags(GetSearchFlags());
    size_t flags = m_data.GetFlags();

    // If the 'Skip comments' is ON, remove the
    // 'colour comments' flag
    if(flags & wxFRD_SKIP_COMMENTS) {
        flags &= ~wxFRD_COLOUR_COMMENTS;
    }

    data.SetMatchCase((flags & wxFRD_MATCHCASE) != 0);
    data.SetMatchWholeWord((flags & wxFRD_MATCHWHOLEWORD) != 0);
    data.SetRegularExpression((flags & wxFRD_REGULAREXPRESSION) != 0);
    data.SetDisplayScope((flags & wxFRD_DISPLAYSCOPE) != 0);
    data.SetEncoding(m_choiceEncoding->GetStringSelection());
    data.SetSkipComments(flags & wxFRD_SKIP_COMMENTS);
    data.SetSkipStrings(flags & wxFRD_SKIP_STRINGS);
    data.SetColourComments(flags & wxFRD_COLOUR_COMMENTS);
    data.SetEnablePipeSupport(flags & wxFRD_ENABLE_PIPE_SUPPORT);
    wxArrayString searchWhere = m_listPaths->GetStrings();
    wxArrayString files;
    wxArrayString rootDirs;

    for(size_t i = 0; i < searchWhere.GetCount(); ++i) {
        const wxString& rootDir = searchWhere.Item(i);
        // Check both translations and otherwise: the history may contain either
        if((rootDir == wxGetTranslation(SEARCH_IN_WORKSPACE)) || (rootDir == SEARCH_IN_WORKSPACE)) {
            if(!clWorkspaceManager::Get().IsWorkspaceOpened()) continue;
            clWorkspaceManager::Get().GetWorkspace()->GetWorkspaceFiles(files);

        } else if((rootDir == wxGetTranslation(SEARCH_IN_PROJECT)) || (rootDir == SEARCH_IN_PROJECT)) {
            if(!clWorkspaceManager::Get().IsWorkspaceOpened()) continue;
            if(clWorkspaceManager::Get().GetWorkspace()->IsProjectSupported()) {
                // get the active project files
                clWorkspaceManager::Get().GetWorkspace()->GetProjectFiles("", files);
            } else {
                // search the entire workspace
                clWorkspaceManager::Get().GetWorkspace()->GetWorkspaceFiles(files);
            }

        } else if((rootDir == wxGetTranslation(SEARCH_IN_CURR_FILE_PROJECT)) ||
                  (rootDir == SEARCH_IN_CURR_FILE_PROJECT)) {

            if(!clWorkspaceManager::Get().IsWorkspaceOpened()) continue;
            IEditor* editor = clGetManager()->GetActiveEditor();
            if(!editor) continue;

            if(clWorkspaceManager::Get().GetWorkspace()->IsProjectSupported()) {
                wxString projectName =
                    clWorkspaceManager::Get().GetWorkspace()->GetProjectFromFile(editor->GetFileName());
                clWorkspaceManager::Get().GetWorkspace()->GetProjectFiles(projectName, files);
            } else {
                // search the entire workspace
                clWorkspaceManager::Get().GetWorkspace()->GetWorkspaceFiles(files);
            }

        } else if((rootDir == wxGetTranslation(SEARCH_IN_CURRENT_FILE)) || (rootDir == SEARCH_IN_CURRENT_FILE)) {
            LEditor* editor = clMainFrame::Get()->GetMainBook()->GetActiveEditor();
            if(editor) {
                files.Add(editor->GetFileName().GetFullPath());
            }
        } else if((rootDir == wxGetTranslation(SEARCH_IN_OPEN_FILES)) || (rootDir == SEARCH_IN_OPEN_FILES)) {
            std::vector<LEditor*> editors;
            clMainFrame::Get()->GetMainBook()->GetAllEditors(editors, MainBook::kGetAll_IncludeDetached);

            for(size_t n = 0; n < editors.size(); ++n) {
                LEditor* editor = dynamic_cast<LEditor*>(*(editors.begin() + n));
                if(editor) {
                    files.Add(editor->GetFileName().GetFullPath());
                }
            }
        } else if(wxFileName::DirExists(searchWhere.Item(i))) {
            rootDirs.Add(searchWhere.Item(i));
        }
    }

    // Remove duplicates
    wxStringSet_t filesSet;
    wxArrayString uniqueFiles;
    std::for_each(files.begin(), files.end(), [&](const wxString& file) {
        if(filesSet.count(file) == 0) {
            filesSet.insert(file);
            uniqueFiles.Add(file);
        }
    });

    files.swap(uniqueFiles);

    data.SetFiles(files);       // list of files
    data.SetRootDirs(rootDirs); // folders
    data.UseNewTab(false);
    data.SetExtensions(m_fileTypes->GetValue());
    return data;
}
예제 #19
0
SearchData TaskPanel::DoGetSearchData()
{
    SearchData data;
    data.SetDisplayScope(true);
    data.SetRegularExpression(true);
    data.SetMatchCase(false);
    data.SetMatchWholeWord(false);
    data.SetEncoding(m_choiceEncoding->GetStringSelection());
    data.SetOwner(this);

    wxString sfind;

    // Load all info from disk
    TasksPanelData d;
    EditorConfigST::Get()->ReadObject(wxT("TasksPanelData"), &d);

    std::map<wxString, wxString>::const_iterator iter = d.GetTasks().begin();
    for(; iter != d.GetTasks().end(); iter++) {
        wxString name = iter->first;
        wxString regex = iter->second;
        bool enabled = (d.GetEnabledItems().Index(iter->first) != wxNOT_FOUND);

        regex.Trim().Trim(false);
        wxRegEx re(regex);
        if(enabled && !regex.IsEmpty() && re.IsValid()) sfind << wxT("(") << regex << wxT(")|");
    }

    if(sfind.empty() == false) sfind.RemoveLast();

    data.SetFindString(sfind);

    wxString rootDir = m_scope->GetStringSelection();
    wxArrayString rootDirs;
    rootDirs.push_back(rootDir);
    data.SetRootDirs(rootDirs);

    wxArrayString files;
    if(rootDir == wxGetTranslation(SEARCH_IN_WORKSPACE)) {
        ManagerST::Get()->GetWorkspaceFiles(files);

    } else if(rootDir == wxGetTranslation(SEARCH_IN_PROJECT)) {
        ManagerST::Get()->GetActiveProjectFiles(files);

    } else if(rootDir == wxGetTranslation(SEARCH_IN_CURR_FILE_PROJECT)) {
        ManagerST::Get()->GetActiveFileProjectFiles(files);
    }
    data.SetFiles(files);
    data.SetExtensions(wxT("*.*"));

    return data;
}
예제 #20
0
SearchData FindInFilesDialog::DoGetSearchData()
{
    SearchData data;
    wxString findStr(m_data.GetFindString());
    if(m_findString->GetValue().IsEmpty() == false) {
        findStr = m_findString->GetValue();
    }

    data.SetFindString(findStr);

    m_data.SetFlags(GetSearchFlags());
    size_t flags = m_data.GetFlags();

    // If the 'Skip comments' is ON, remove the
    // 'colour comments' flag
    if(flags & wxFRD_SKIP_COMMENTS) {
        flags &= ~wxFRD_COLOUR_COMMENTS;
    }

    data.SetMatchCase((flags & wxFRD_MATCHCASE) != 0);
    data.SetMatchWholeWord((flags & wxFRD_MATCHWHOLEWORD) != 0);
    data.SetRegularExpression((flags & wxFRD_REGULAREXPRESSION) != 0);
    data.SetDisplayScope((flags & wxFRD_DISPLAYSCOPE) != 0);
    data.SetEncoding(m_choiceEncoding->GetStringSelection());
    data.SetSkipComments(flags & wxFRD_SKIP_COMMENTS);
    data.SetSkipStrings(flags & wxFRD_SKIP_STRINGS);
    data.SetColourComments(flags & wxFRD_COLOUR_COMMENTS);
    wxArrayString rootDirs;
    for(size_t i = 0; i < m_listPaths->GetCount(); ++i) {
        rootDirs.push_back(m_listPaths->GetString(i));
    }
    if(rootDirs.IsEmpty()) {
        wxString dir = m_dirPicker->GetPath();
        if(dir.IsEmpty() == false) {
            rootDirs.push_back(dir);
        }
    }
    data.SetRootDirs(rootDirs);

    wxArrayString files;
    for(size_t i = 0; i < rootDirs.GetCount(); ++i) {
        const wxString& rootDir = rootDirs.Item(i);
        // Check both translations and otherwise: the history may contain either
        if((rootDir == wxGetTranslation(SEARCH_IN_WORKSPACE)) || (rootDir == SEARCH_IN_WORKSPACE)) {
            ManagerST::Get()->GetWorkspaceFiles(files);

        } else if((rootDir == wxGetTranslation(SEARCH_IN_PROJECT)) || (rootDir == SEARCH_IN_PROJECT)) {
            ManagerST::Get()->GetActiveProjectFiles(files);

        } else if((rootDir == wxGetTranslation(SEARCH_IN_CURR_FILE_PROJECT)) ||
                  (rootDir == SEARCH_IN_CURR_FILE_PROJECT)) {
            ManagerST::Get()->GetActiveFileProjectFiles(files);

        } else if((rootDir == wxGetTranslation(SEARCH_IN_CURRENT_FILE)) || (rootDir == SEARCH_IN_CURRENT_FILE)) {
            LEditor* editor = clMainFrame::Get()->GetMainBook()->GetActiveEditor();
            if(editor) {
                files.Add(editor->GetFileName().GetFullPath());
            }
        } else if((rootDir == wxGetTranslation(SEARCH_IN_OPEN_FILES)) || (rootDir == SEARCH_IN_OPEN_FILES)) {
            std::vector<LEditor*> editors;
            clMainFrame::Get()->GetMainBook()->GetAllEditors(editors, MainBook::kGetAll_IncludeDetached);

            for(size_t n = 0; n < editors.size(); ++n) {
                LEditor* editor = dynamic_cast<LEditor*>(*(editors.begin() + n));
                if(editor) {
                    files.Add(editor->GetFileName().GetFullPath());
                }
            }
        }
    }

    data.SetFiles(files);
    data.UseNewTab(m_checkBoxSeparateTab->IsChecked());
    data.SetExtensions(m_fileTypes->GetValue());
    return data;
}
예제 #21
0
void SearchOperation::doSearch( SearchData& searchData, LineNumber initialLine )
{
    const auto& config = Persistable::get<Configuration>();

    const auto nbSourceLines = sourceLogData_->getNbLine();
    LineLength maxLength = 0_length;
    LinesCount nbMatches = searchData.getNbMatches();

    const auto nbLinesInChunk = LinesCount( config.searchReadBufferSizeLines() );

    LOG( logDEBUG ) << "Searching from line " << initialLine << " to " << nbSourceLines;

    if ( initialLine < startLine_ ) {
        initialLine = startLine_;
    }

    const auto endLine = qMin( LineNumber( nbSourceLines.get() ), endLine_ );

    using namespace std::chrono;
    high_resolution_clock::time_point t1 = high_resolution_clock::now();

    QSemaphore searchCompleted;
    QSemaphore blocksDone;

    using SearchBlockQueue = moodycamel::BlockingConcurrentQueue<SearchBlockData>;
    using ProcessMatchQueue = moodycamel::BlockingConcurrentQueue<PartialSearchResults>;

    SearchBlockQueue searchBlockQueue;
    ProcessMatchQueue processMatchQueue;

    std::vector<QFuture<void>> matchers;

    const auto matchingThreadsCount = [&config]()
    {
        if ( !config.useParallelSearch() ) {
            return 1;
        }

        return qMax( 1,  config.searchThreadPoolSize() == 0 
                        ? QThread::idealThreadCount() - 1 
                        : static_cast<int>( config.searchThreadPoolSize() ) );    
    }();

    LOG( logINFO ) << "Using " << matchingThreadsCount << " matching threads";

    auto localThreadPool = std::make_unique<QThreadPool>();
    localThreadPool->setMaxThreadCount( matchingThreadsCount + 2 );

    const auto makeMatcher = [this, &searchBlockQueue, &processMatchQueue,
                              pool = localThreadPool.get()]( size_t index ) {
        // copy and optimize regex for each thread
        auto regexp = QRegularExpression{ regexp_.pattern(), regexp_.patternOptions() };
        regexp.optimize();
        return QtConcurrent::run( pool, [regexp, index, &searchBlockQueue, &processMatchQueue]() {
            auto cToken = moodycamel::ConsumerToken{ searchBlockQueue };
            auto pToken = moodycamel::ProducerToken{ processMatchQueue };

            for ( ;; ) {
                SearchBlockData blockData;
                searchBlockQueue.wait_dequeue( cToken, blockData );

                LOG( logDEBUG ) << "Searcher " << index << " " << blockData.chunkStart;

                const auto lastBlock = blockData.lines.empty();

                if ( !lastBlock ) {
                    blockData.results
                        = filterLines( regexp, blockData.lines, blockData.chunkStart );
                }

                LOG( logDEBUG ) << "Searcher " << index << " sending matches "
                                << blockData.results.matchingLines.size();

                processMatchQueue.enqueue( pToken, std::move( blockData.results ) );

                if ( lastBlock ) {
                    LOG( logDEBUG ) << "Searcher " << index << " last block";
                    return;
                }
            }
        } );
    };

    for ( int i = 0; i < matchingThreadsCount; ++i ) {
        matchers.emplace_back( makeMatcher( i ) );
    }

    auto processMatches = QtConcurrent::run( localThreadPool.get(), [&]() {
        auto cToken = moodycamel::ConsumerToken{ processMatchQueue };

        size_t matchersDone = 0;

        int reportedPercentage = 0;
        auto reportedMatches = nbMatches;
        LinesCount totalProcessedLines = 0_lcount;

        const auto totalLines = endLine - initialLine;

        for ( ;; ) {
            PartialSearchResults matchResults;
            processMatchQueue.wait_dequeue( cToken, matchResults );

            LOG( logDEBUG ) << "Combining match results from " << matchResults.chunkStart;

            if ( matchResults.processedLines.get() ) {

                maxLength = qMax( maxLength, matchResults.maxLength );
                nbMatches += LinesCount(
                    static_cast<LinesCount::UnderlyingType>( matchResults.matchingLines.size() ) );

                const auto processedLines = LinesCount{ matchResults.chunkStart.get()
                                                        + matchResults.processedLines.get() };

                totalProcessedLines += matchResults.processedLines;

                // After each block, copy the data to shared data
                // and update the client
                searchData.addAll( maxLength, matchResults.matchingLines, processedLines );

                LOG( logDEBUG ) << "done Searching chunk starting at " << matchResults.chunkStart
                                << ", " << matchResults.processedLines << " lines read.";

                blocksDone.release( matchResults.processedLines.get() );
            }
            else {
                matchersDone++;
            }

            const int percentage 
                = static_cast<int>( std::floor( 100.f * ( totalProcessedLines ).get() / totalLines.get() ) );

            if ( percentage > reportedPercentage || nbMatches > reportedMatches ) {

                emit searchProgressed( nbMatches, std::min( 99, percentage ), initialLine );

                reportedPercentage = percentage;
                reportedMatches = nbMatches;
            }

            if ( matchersDone == matchers.size() ) {
                searchCompleted.release();
                return;
            }
        }
    } );

    auto pToken =  moodycamel::ProducerToken{ searchBlockQueue };

    blocksDone.release( nbLinesInChunk.get() * ( static_cast<uint32_t>( matchers.size() ) + 1 ) );

    for ( auto chunkStart = initialLine; chunkStart < endLine;
          chunkStart = chunkStart + nbLinesInChunk ) {
        if ( *interruptRequested_ )
            break;

        LOG( logDEBUG ) << "Reading chunk starting at " << chunkStart;

        const auto linesInChunk
            = LinesCount( qMin( nbLinesInChunk.get(), ( endLine - chunkStart ).get() ) );
        auto lines = sourceLogData_->getLines( chunkStart, linesInChunk );

        LOG( logDEBUG ) << "Sending chunk starting at " << chunkStart << ", " << lines.size()
                        << " lines read.";

        blocksDone.acquire( static_cast<uint32_t>( lines.size() ) );

        searchBlockQueue.enqueue( pToken,
                                  { chunkStart, std::move( lines ), PartialSearchResults{} } );

        LOG( logDEBUG ) << "Sent chunk starting at " << chunkStart << ", " << lines.size()
                        << " lines read.";
    }

    for ( size_t i = 0; i < matchers.size(); ++i ) {
        searchBlockQueue.enqueue( pToken,
                                  { endLine, std::vector<QString>{}, PartialSearchResults{} } );
    }

    searchCompleted.acquire();

    high_resolution_clock::time_point t2 = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>( t2 - t1 ).count();

    LOG( logINFO ) << "Searching done, took " << duration / 1000.f << " ms";
    LOG( logINFO ) << "Searching perf "
                   << static_cast<uint32_t>(
                          std::floor( 1000 * 1000.f * ( endLine - initialLine ).get() / duration ) )
                   << " lines/s";

    emit searchProgressed( nbMatches, 100, initialLine );
}