Merge branch 'master' of git+ssh://repo.or.cz/srv/git/jben
[jben.git] / src / frame_ksearch_helpers.cpp
blob8472113ee20084d77148e10c1b0d7d6c5ec6e1de
1 /*
2 Project: J-Ben
3 Author: Paul Goins
4 Website: http://www.vultaire.net/software/jben/
5 License: GNU General Public License (GPL) version 2
6 (http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt)
8 File: frame_ksearch_helpers.cpp
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>
24 #include "frame_ksearch_helpers.h"
26 #include <gtkmm/buttonbox.h>
27 #include <gtkmm/button.h>
28 #include <glibmm/i18n.h>
29 #include <boost/foreach.hpp>
30 #define foreach BOOST_FOREACH
31 #include "kdict.h"
33 typedef std::pair<wchar_t, KInfo> kdict_pair;
34 typedef std::pair<std::string, SkipCode> SkipMiscode;
36 KSearchBox::KSearchBox(const Glib::ustring& label)
37 : Frame(label), layout(false, 5) {
38 set_shadow_type(Gtk::SHADOW_ETCHED_IN);
39 add(layout);
42 void KSearchBox::pack_start(Gtk::Widget& child,
43 Gtk::PackOptions options, guint padding) {
44 layout.pack_start(child, options, padding);
47 void KSearchBox::pack_end(Gtk::Widget& child,
48 Gtk::PackOptions options, guint padding) {
49 layout.pack_end(child, options, padding);
54 KSearchHW::KSearchHW()
55 : KSearchBox(_("Handwriting")), leftLayout(false, 5), btnClear(_("Clear")) {
56 khwp.set_size_request(-1, 75);
57 btnClear.signal_clicked()
58 .connect(sigc::mem_fun(*this, &KSearchHW::OnClear));
60 buttons.pack_start(btnClear, Gtk::PACK_SHRINK);
61 leftLayout.pack_start(khwp, Gtk::PACK_EXPAND_WIDGET);
62 leftLayout.pack_start(buttons, Gtk::PACK_SHRINK);
64 layout.pack_start(leftLayout, Gtk::PACK_EXPAND_WIDGET);
67 std::list<wchar_t> KSearchHW::Filter(std::list<wchar_t> srcList) {
68 std::list<wchar_t> results;
69 std::vector<wchar_t> vwc = khwp.GetResults();
71 /* Append only the results which are also present in the source list. */
72 foreach(wchar_t& wc, vwc) {
73 if(find(srcList.begin(), srcList.end(), wc) != srcList.end())
74 results.push_back(wc);
76 return results;
79 void KSearchHW::OnClear() {
80 khwp.Clear();
83 KSearchStroke::KSearchStroke()
84 : KSearchBox(_("Stroke Count")), leftLayout(false, 5),
85 strokeControls(false, 5),
86 allowCommonMiscounts(_("Include common stroke miscounts")),
87 miscountControls(false, 5),
88 allowMiscounts(_("Include stroke miscounts")), plusMinus(_("+/-")) {
89 strokeCount.set_range(0, 40);
90 strokeCount.set_digits(0);
91 strokeCount.set_increments(1, 10);
92 strokeCount.set_width_chars(2);
93 strokeCount.set_text("0");
94 strokeCount.set_activates_default(false);
95 miscountAdjust.set_range(0,40);
96 miscountAdjust.set_digits(0);
97 miscountAdjust.set_increments(1, 1);
98 miscountAdjust.set_width_chars(2);
99 miscountAdjust.set_text("0");
100 miscountAdjust.set_sensitive(false);
102 allowMiscounts.signal_toggled()
103 .connect(sigc::mem_fun(*this, &KSearchStroke::OnMiscountToggled));
105 strokeControls.pack_start(strokeCount, Gtk::PACK_SHRINK);
106 miscountControls.pack_start(allowMiscounts, Gtk::PACK_SHRINK);
107 miscountControls.pack_start(plusMinus, Gtk::PACK_SHRINK);
108 miscountControls.pack_start(miscountAdjust, Gtk::PACK_SHRINK);
109 leftLayout.pack_start(strokeControls, Gtk::PACK_SHRINK);
110 leftLayout.pack_start(allowCommonMiscounts, Gtk::PACK_SHRINK);
111 leftLayout.pack_start(miscountControls, Gtk::PACK_SHRINK);
112 layout.pack_start(leftLayout, Gtk::PACK_EXPAND_WIDGET);
115 std::list<wchar_t> KSearchStroke::Filter(std::list<wchar_t> srcList) {
116 std::list<wchar_t> results;
118 int mcAdj = 0;
119 if(allowMiscounts.get_active())
120 mcAdj = miscountAdjust.get_value_as_int();
121 bool commonMistrokes = allowCommonMiscounts.get_active();
122 const KDict* kd = KDict::Get();
123 const KInfo* ki;
124 int sc = strokeCount.get_value_as_int();
126 /* Append only the results which are also present in the source list. */
127 foreach(wchar_t& wc, srcList) {
128 ki = kd->GetEntry(wc);
129 if(ki->strokeCount >= sc - mcAdj && ki->strokeCount <= sc + mcAdj)
130 results.push_back(wc);
131 else if(commonMistrokes) {
132 /* I'm -not- going to apply the miscount adjust when searching
133 lists of common mistrokes - kind of defeats the purpose, I
134 think. */
135 foreach(const int& miscount, ki->misstrokes) {
136 if(miscount == sc) {
137 results.push_back(wc);
138 break;
143 return results;
146 void KSearchStroke::OnMiscountToggled() {
147 miscountAdjust.set_sensitive(allowMiscounts.get_active());
150 KSearchSKIP::KSearchSKIP()
151 : KSearchBox(_("SKIP search")), leftLayout(false, 5),
152 skipControls(false, 5), sep1(_("-")), sep2(_("-")),
153 allowMiscodes(_("Include SKIP miscodes")), miscountControls(false, 5),
154 allowMiscounts(_("Include stroke miscounts")), plusMinus(_("+/-")) {
156 /* Based on KANJIDIC2, the max values for these fields are as follows:
157 index1: 4 (by SKIP definition; should never change)
158 index2: 22
159 index3: 28
161 HOWEVER, let's not hard-code them. Set upper bounds to 30 on
162 index2/index3, and if we really need a specific upper bound, have it
163 determined on dictionary load time later. */
165 index1.set_range(0, 4);
166 index1.set_digits(0);
167 index1.set_increments(1, 1);
168 index1.set_width_chars(1);
169 index1.set_text("0");
170 index1.set_activates_default(false);
171 index2.set_range(0, 30);
172 index2.set_digits(0);
173 index2.set_increments(1, 10);
174 index2.set_width_chars(2);
175 index2.set_text("0");
176 index2.set_activates_default(false);
177 index3.set_range(0, 30);
178 index3.set_digits(0);
179 index3.set_increments(1, 10);
180 index3.set_width_chars(2);
181 index3.set_text("0");
182 index3.set_activates_default(false);
183 miscountAdjust.set_range(0,30);
184 miscountAdjust.set_digits(0);
185 miscountAdjust.set_increments(1, 1);
186 miscountAdjust.set_width_chars(2);
187 miscountAdjust.set_text("0");
188 miscountAdjust.set_sensitive(false);
189 allowMiscounts.signal_toggled()
190 .connect(sigc::mem_fun(*this, &KSearchSKIP::OnMiscountToggled));
192 skipControls.pack_start(index1, Gtk::PACK_SHRINK);
193 skipControls.pack_start(sep1, Gtk::PACK_SHRINK);
194 skipControls.pack_start(index2, Gtk::PACK_SHRINK);
195 skipControls.pack_start(sep2, Gtk::PACK_SHRINK);
196 skipControls.pack_start(index3, Gtk::PACK_SHRINK);
197 miscountControls.pack_start(allowMiscounts, Gtk::PACK_SHRINK);
198 miscountControls.pack_start(plusMinus, Gtk::PACK_SHRINK);
199 miscountControls.pack_start(miscountAdjust, Gtk::PACK_SHRINK);
200 leftLayout.pack_start(skipControls, Gtk::PACK_SHRINK);
201 leftLayout.pack_start(allowMiscodes, Gtk::PACK_SHRINK);
202 leftLayout.pack_start(miscountControls, Gtk::PACK_SHRINK);
203 layout.pack_start(leftLayout, Gtk::PACK_EXPAND_WIDGET);
206 std::list<wchar_t> KSearchSKIP::Filter(std::list<wchar_t> srcList) {
207 std::list<wchar_t> results;
209 int mcAdj = 0;
210 if(allowMiscounts.get_active())
211 mcAdj = miscountAdjust.get_value_as_int();
212 bool miscodes = allowMiscodes.get_active();
213 const KDict* kd = KDict::Get();
214 const KInfo* ki;
215 int i1 = index1.get_value_as_int();
216 int i2 = index2.get_value_as_int();
217 int i3 = index3.get_value_as_int();
219 /* Append only the results which are also present in the source list. */
220 foreach(wchar_t& wc, srcList) {
221 ki = kd->GetEntry(wc);
222 if((i1 == 0 || ki->qc_skip.i1 == i1) &&
223 (i2 == 0 ||
224 (ki->qc_skip.i2 >= i2 - mcAdj && ki->qc_skip.i2 <= i2 + mcAdj)) &&
225 (i3 == 0 ||
226 (ki->qc_skip.i3 >= i3 - mcAdj && ki->qc_skip.i3 <= i3 + mcAdj)))
227 results.push_back(wc);
228 else if(miscodes) {
229 foreach(const SkipMiscode& code, ki->skipMisclass) {
230 if((i1 == 0 || code.second.i1 == i1) &&
231 (i2 == 0 ||
232 (code.second.i2 >= i2 - mcAdj &&
233 code.second.i2 <= i2 + mcAdj)) &&
234 (i3 == 0 ||
235 (code.second.i3 >= i3 - mcAdj &&
236 code.second.i3 <= i3 + mcAdj))) {
237 results.push_back(wc);
238 break;
243 return results;
246 void KSearchSKIP::OnMiscountToggled() {
247 miscountAdjust.set_sensitive(allowMiscounts.get_active());