1 /**********************************************************************************************
2     Copyright (C) 2019 Henri Hornburg <hrnbg@t-online.de>
3 
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation, either version 3 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 
17 **********************************************************************************************/
18 
19 #ifndef CSEARCH_H
20 #define CSEARCH_H
21 
22 #include <functional>
23 #include <QList>
24 #include <QString>
25 
26 #include "gis/IGisItem.h"
27 #include "units/IUnit.h"
28 
29 class IGisItem;
30 
31 struct searchValue_t //Outside of CSearch to avoid problem of nested type
32 {
33     qreal value1 = NOFLOAT;
34     qreal value2 = NOFLOAT;
35     QString str1 = "";
36     QString str2 = "";
37     QString toString(bool lowerCase = false) const
38     {
39         QString str;
40         if(value1 != NOFLOAT)
41         {
42             str.append(QString::number(value1));
43         }
44         str.append(str1);
45         if(value2 != NOFLOAT)
46         {
47             str.append(QString::number(value2));
48         }
49         str.append(str2);
50 
51         if(lowerCase)
52         {
53             return str.toLower();
54         }
55         else
56         {
57             return str;
58         }
59     }
60 };
61 
62 enum searchProperty_e: unsigned int
63 {
64     eSearchPropertyNoMatch,
65 
66     //General keywords
67     eSearchPropertyGeneralName,
68     eSearchPropertyGeneralFullText,
69     eSearchPropertyGeneralElevation,
70     eSearchPropertyGeneralDate,
71     eSearchPropertyGeneralComment,
72     eSearchPropertyGeneralDescription,
73     eSearchPropertyGeneralRating,
74     eSearchPropertyGeneralKeywords,
75     eSearchPropertyGeneralType,
76 
77     //Area keywords
78     eSearchPropertyAreaArea,
79 
80     //Geocache keywords
81     eSearchPropertyGeocacheDifficulty,
82     eSearchPropertyGeocacheTerrain,
83     eSearchPropertyGeocachePositiveAttributes,
84     eSearchPropertyGeocacheNegatedAttributes,
85     eSearchPropertyGeocacheSize,
86     eSearchPropertyGeocacheGCCode,
87     eSearchPropertyGeocacheGCName,
88     eSearchPropertyGeocacheStatus,
89     eSearchPropertyGeocacheGCType,
90     eSearchPropertyGeocacheLoggedBy,
91     eSearchPropertyGeocacheLastLogDate,
92     eSearchPropertyGeocacheLastLogType,
93     eSearchPropertyGeocacheLastLogBy,
94     eSearchPropertyGeocacheGCOwner,
95 
96     //Waypoint keywords
97 
98 
99     //Route / track keywords
100     eSearchPropertyRteTrkDistance,
101     eSearchPropertyRteTrkAscent,
102     eSearchPropertyRteTrkDescent,
103     eSearchPropertyRteTrkMinElevation,
104     eSearchPropertyRteTrkMaxElevation,
105     eSearchPropertyRteTrkMaxSpeed,
106     eSearchPropertyRteTrkMinSpeed,
107     eSearchPropertyRteTrkAvgSpeed,
108     eSearchPropertyRteTrkActivity,
109     eSearchPropertyRteTrkTotalTime,
110     eSearchPropertyRteTrkTimeMoving
111 };
112 
113 class CSearch
114 {
115     Q_DECLARE_TR_FUNCTIONS(CSearch)
116 public:
117 
118     enum search_type_e
119     {
120         eSearchTypeNone,
121         eSearchTypeWith,
122         eSearchTypeWithout,
123         eSearchTypeSmaller,
124         eSearchTypeBigger,
125         eSearchTypeBetween,
126         eSearchTypeEquals,
127         eSearchTypeRegEx
128     };
129 
130     enum search_mode_e
131     {
132         eSearchModeName,
133         eSearchModeText
134     };
135 
136     struct search_t
137     {
138         searchProperty_e property = eSearchPropertyNoMatch;
139         search_type_e searchType = eSearchTypeNone;
140         searchValue_t searchValue;
141     };
142 
143     CSearch(QString searchstring);
144 
getSearchType(QString keyword)145     search_type_e getSearchType(QString keyword)
146     {
147         return keywordSearchTypeMap.value(keyword, eSearchTypeNone);
148     }
149 
getSyntaxError()150     bool getSyntaxError()
151     {
152         return syntaxError;
153     }
154 
isAutodetectedProperty()155     bool isAutodetectedProperty()
156     {
157         return autoDetectedProperty;
158     }
159 
getSearchText()160     const QString& getSearchText()
161     {
162         return searchText;
163     }
164 
getSearchTypeKeywords()165     static QStringList getSearchTypeKeywords()
166     {
167         return keywordSearchTypeMap.keys();
168     }
169 
getSearchTypeExample(QString searchType)170     static QString getSearchTypeExample(QString searchType)
171     {
172         return keywordSearchExampleMap.value(searchType, tr("No information available"));
173     }
174 
getSearchPropertyKeywords()175     static QStringList getSearchPropertyKeywords()
176     {
177         return searchPropertyEnumMap.keys();
178     }
179 
getSearchPropertyMeaning(QString property)180     static QString getSearchPropertyMeaning(QString property)
181     {
182         return searchPropertyMeaningMap.value(searchPropertyEnumMap.value(property), tr("No information available"));
183     }
184 
185     bool getSearchResult(IGisItem* item);
186 
getCaseSensitivity()187     static Qt::CaseSensitivity getCaseSensitivity()
188     {
189         return caseSensitivity;
190     }
setCaseSensitivity(const Qt::CaseSensitivity & value)191     static void setCaseSensitivity(const Qt::CaseSensitivity& value)
192     {
193         caseSensitivity = value;
194     }
195 
getSearchMode()196     static search_mode_e getSearchMode()
197     {
198         return searchMode;
199     }
setSearchMode(const search_mode_e & value)200     static void setSearchMode(const search_mode_e& value)
201     {
202         searchMode = value;
203     }
204 
init()205     static void init()
206     {
207         searchPropertyMeaningMap = initSearchPropertyMeaningMap();
208         searchPropertyEnumMap = initSearchPropertyEnumMap();
209         keywordSearchExampleMap = initKeywordSearchExampleMap();
210         keywordSearchTypeMap = initKeywordSearchTypeMap();
211     }
212 
213 private:
214 
215     static Qt::CaseSensitivity caseSensitivity;
216     static search_mode_e searchMode;
217 
218     bool adjustUnits(const searchValue_t& itemValue, searchValue_t& searchValue);
219     void improveQuery();
220 
221     search_t search;
222     QString searchText;
223     bool syntaxError = false;
224     bool autoDetectedProperty = false;
225 
226     static QMap<QString, search_type_e> keywordSearchTypeMap;
227     static QMap<QString, search_type_e> initKeywordSearchTypeMap();
228 
229     static QMap<QString, QString> keywordSearchExampleMap;
230     static QMap<QString, QString> initKeywordSearchExampleMap();
231 
232     static QMap<QString, searchProperty_e> searchPropertyEnumMap;
233     static QMap<QString, searchProperty_e> initSearchPropertyEnumMap();
234 
235     static QMap<searchProperty_e, QString> searchPropertyMeaningMap;
236     static QMap<searchProperty_e, QString> initSearchPropertyMeaningMap();
237 
238     //First is itemValue, second is searchValue, which is non const to adjust units
239     using fSearch = std::function<bool (const searchValue_t&, searchValue_t&)>;
240     QMap<search_type_e, fSearch > searchTypeLambdaMap;
241     QMap<search_type_e, fSearch > initSearchTypeLambdaMap();
242 };
243 
244 #endif // CSEARCH_H
245