summaryrefslogtreecommitdiff
path: root/ui/search.cpp
blob: c834b9340d3b83129114bdc6493f9b12072060a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// **************************************************************************
// * This file is part of the FreeFileSync project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html       *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved        *
// **************************************************************************

#include "search.h"
#include <zen/string_tools.h>


using namespace zen;

namespace
{
template <bool respectCase>
class ContainsMatch
{
public:
    ContainsMatch(const wxString& textToFind) : textToFind_(textToFind) {}
    bool operator()(const wxString& phrase) const { return contains(phrase, textToFind_); }

private:
    wxString textToFind_;
};


template <>
class ContainsMatch<false>
{
public:
    ContainsMatch(const wxString& textToFind) : textToFind_(textToFind) { textToFind_.MakeUpper(); }
    bool operator()(wxString&& phrase) const
    {
        //wxWidgets::MakeUpper() is inefficient! But performance is not THAT important for this high-level search functionality
        phrase.MakeUpper();
        return contains(phrase, textToFind_);
    }

private:
    wxString textToFind_;
};

//###########################################################################################

template <bool respectCase>
ptrdiff_t findRow(const Grid& grid, //return -1 if no matching row found
                  const wxString& searchString,
                  size_t rowFirst, //specify area to search:
                  size_t rowLast)  // [rowFirst, rowLast)
{
    if (auto prov = grid.getDataProvider())
    {
        std::vector<Grid::ColumnAttribute> colAttr = grid.getColumnConfig();
        vector_remove_if(colAttr, [](const Grid::ColumnAttribute& ca) { return !ca.visible_; });
        if (!colAttr.empty())
        {
            const ContainsMatch<respectCase> containsMatch(searchString);

            for (size_t row = rowFirst; row < rowLast; ++row)
                for (auto iterCol = colAttr.begin(); iterCol != colAttr.end(); ++iterCol)
                    if (containsMatch(prov->getValue(row, iterCol->type_)))
                        return row;
        }
    }
    return -1;
}
}


std::pair<const Grid*, ptrdiff_t> zen::findGridMatch(const Grid& grid1, const Grid& grid2, const wxString& searchString, bool respectCase)
{
    const size_t rowCountL = grid1.getRowCount();
    const size_t rowCountR = grid2.getRowCount();
    auto cursorPos = grid1.getGridCursor(); //(row, component pos)

    std::pair<const Grid*, ptrdiff_t> result(nullptr, -1);

    size_t cursorRowL = cursorPos.first;
    if (cursorRowL >= rowCountL)
        cursorRowL = 0;
    {
        auto finishSearch = [&](const Grid& grid, size_t rowFirst, size_t rowLast) -> bool
        {
            const ptrdiff_t targetRow = respectCase ?
            findRow<true>( grid, searchString, rowFirst, rowLast) :
            findRow<false>(grid, searchString, rowFirst, rowLast);
            if (targetRow >= 0)
            {
                result = std::make_pair(&grid, targetRow);
                return true;
            }
            return false;
        };

        if (!finishSearch(grid1, cursorRowL + 1, rowCountL))
            if (!finishSearch(grid2, 0, rowCountR))
                finishSearch(grid1, 0, cursorRowL + 1);
    }
    return result;
}
bgstack15