moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kiten / rad.cpp
blob9ad50b3734fba281c388f39df50cb6a7df71dd54
1 /**
2 This file is part of Kiten, a KDE Japanese Reference Tool...
3 Copyright (C) 2001 Jason Katz-Brown <jason@katzbrown.com>
4 (C) 2005 Paul Temple <paul.temple@gmx.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA
20 **/
22 #include <kapplication.h>
23 #include <kconfig.h>
24 #include <kdebug.h>
25 #include <kdialog.h>
26 #include <klistbox.h>
27 #include <klocale.h>
28 #include <kmessagebox.h>
29 #include <kpushbutton.h>
30 #include <kstandarddirs.h>
32 #include <qbuttongroup.h>
33 #include <qcheckbox.h>
34 #include <qfile.h>
35 #include <qlabel.h>
36 #include <qlayout.h>
37 #include <qspinbox.h>
38 #include <qtextcodec.h>
39 #include <qtooltip.h>
41 #include "kitenconfig.h"
42 #include "rad.h"
44 Rad::Rad() : QObject()
46 loaded = false;
49 void Rad::load()
51 if (loaded)
52 return;
54 KStandardDirs *dirs = KGlobal::dirs();
55 QString radkfile = dirs->findResource("data", "kiten/radkfile");
56 if (radkfile.isNull())
58 KMessageBox::error(0, i18n("Kanji radical information file not installed, so radical searching cannot be used."));
59 return;
62 QFile f(radkfile);
64 if (!f.open(IO_ReadOnly))
66 KMessageBox::error(0, i18n("Kanji radical information could not be loaded, so radical searching cannot be used."));
69 QTextStream t(&f);
70 t.setCodec(QTextCodec::codecForName("eucJP"));
71 Radical cur;
72 while (!t.eof())
74 QString s = t.readLine();
76 QChar first = s.at(0);
77 if (first == '#') // comment!
79 // nothing
81 else if (first == '$') // header
83 // save previous one
84 if( !cur.kanji().isNull() )
85 list.append(cur);
87 //first entry is trim(last 4 chars).. <rad><space><strokes>
88 unsigned int strokes = s.right(2).toUInt();
89 QString radical = QString(s.at(2));
90 cur = Radical(radical, strokes);
92 else // continuation
94 cur.addKanji(s);
98 // we gotta append the last one!!
99 // this nagged jasonkb for a bit wondering why fue wasn't showing up ;)
100 list.append(cur);
102 f.close();
104 loaded = true;
107 QStringList Rad::radByStrokes(unsigned int strokes)
109 load();
111 QStringList ret;
112 bool hadOne = false;
113 QValueListIterator<Radical> it = list.begin();
117 if ((*it).strokes() == strokes)
119 ret.append((*it).radical());
120 hadOne = true;
122 else if(hadOne) // shortcut because it's a sorted list
124 return ret;
127 while (++it != list.end());
129 return ret;
132 QStringList Rad::kanjiByRad(const QString &text)
134 //kdDebug() << "kanjiByRad, text is " << text << endl;
135 load();
136 QStringList ret;
138 QValueListIterator<Radical> it;
139 for (it = list.begin(); it != list.end() && (*it).radical() != text; ++it)
141 //kdDebug() << "kanjiByRad, looping, radical is " << (*it).radical() << endl;
144 QString kanji = (*it).kanji();
145 for (unsigned i = 0; i < kanji.length(); ++i)
147 //kdDebug() << "kanjiByRad, i is " << i << endl;
148 ret.append(QString(kanji.at(i)));
151 return ret;
154 QStringList Rad::kanjiByRad(const QStringList &list)
156 //kdDebug() << "kanjiByRad (list version)\n";
158 QStringList ret;
159 QValueList<QStringList> lists;
161 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it)
163 //kdDebug() << "loading radical " << *it << endl;
164 lists.append(kanjiByRad(*it));
167 QStringList first = lists.first();
168 lists.pop_front();
170 for (QStringList::Iterator kit = first.begin(); kit != first.end(); ++kit)
172 //kdDebug() << "kit is " << *kit << endl;
173 QValueList<bool> outcomes;
174 for (QValueList<QStringList>::Iterator it = lists.begin(); it != lists.end(); ++it)
176 //kdDebug() << "looping through lists\n";
177 outcomes.append((*it).contains(*kit) > 0);
180 const bool containsBool = false;
181 if ((outcomes.contains(containsBool) < 1))
183 //kdDebug() << "appending " << *kit << endl;
184 ret.append(*kit);
186 else
188 //kdDebug() << "not appending " << *kit << endl;
192 return ret;
195 Radical Rad::radByKanji(const QString &text)
197 load();
198 QString ret;
200 QValueListIterator<Radical> it;
201 for (it = list.end(); it != list.begin() && (*it).kanji().find(text) == -1; --it);
203 return (*it);
206 unsigned int Rad::strokesByRad(const QString &text)
208 load();
209 QValueListIterator<Radical> it;
210 for(it = list.begin(); it != list.end() && (*it).radical() != text; ++it);
212 return (*it).strokes();
215 Rad::~Rad()
219 ///////////////////////////////////////////////
221 RadWidget::RadWidget(Rad *_rad, QWidget *parent, const char *name) : QWidget(parent, name)
223 hotlistNum = 3;
225 rad = _rad;
226 QHBoxLayout *hlayout = new QHBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint());
227 QVBoxLayout *vlayout = new QVBoxLayout(hlayout, KDialog::spacingHint());
229 hotlistGroup = new QButtonGroup(1, Horizontal, i18n("Hotlist"), this);
230 //hotlistGroup->setRadioButtonExclusive(true);
231 vlayout->addWidget(hotlistGroup);
233 Config* config = Config::self();
235 hotlist = config->hotlist();
237 while (hotlist.size() > hotlistNum)
238 hotlist.pop_front();
240 for (unsigned int i = 0; i < hotlistNum; ++i)
242 if (i >= hotlistNum)
243 break;
245 hotlistGroup->insert(new KPushButton(*hotlist.at(i), hotlistGroup), i);
247 connect(hotlistGroup, SIGNAL(clicked(int)), SLOT(hotlistClicked(int)));
249 QVBoxLayout *layout = new QVBoxLayout(vlayout, KDialog::spacingHint());
251 totalStrokes = new QCheckBox(i18n("Search by total strokes"), this);
252 connect(totalStrokes, SIGNAL(clicked()), this, SLOT(totalClicked()));
253 layout->addWidget(totalStrokes);
255 QHBoxLayout *strokesLayout = new QHBoxLayout(layout, KDialog::spacingHint());
256 totalSpin = new QSpinBox(1, 30, 1, this);
257 strokesLayout->addWidget(totalSpin);
258 strokesLayout->addStretch();
259 totalErrLabel = new QLabel(i18n("+/-"), this);
260 strokesLayout->addWidget(totalErrLabel);
261 totalErrSpin = new QSpinBox(0, 15, 1, this);
262 strokesLayout->addWidget(totalErrSpin);
264 ok = new KPushButton(i18n("&Look Up"), this);
265 ok->setEnabled(false);
266 connect(ok, SIGNAL(clicked()), SLOT(apply()));
267 layout->addWidget(ok);
268 cancel = new KPushButton( KStdGuiItem::cancel(), this );
270 connect(cancel, SIGNAL(clicked()), SLOT(close()));
271 layout->addWidget(cancel);
273 QVBoxLayout *middlevLayout = new QVBoxLayout(hlayout, KDialog::spacingHint());
275 strokesSpin = new QSpinBox(1, 17, 1, this);
276 QToolTip::add(strokesSpin, i18n("Show radicals having this number of strokes"));
277 middlevLayout->addWidget(strokesSpin);
279 List = new KListBox(this);
280 middlevLayout->addWidget(List);
281 connect(List, SIGNAL(executed(QListBoxItem *)), this, SLOT(executed(QListBoxItem *)));
282 connect(strokesSpin, SIGNAL(valueChanged(int)), this, SLOT(updateList(int)));
284 QVBoxLayout *rightvlayout = new QVBoxLayout(hlayout, KDialog::spacingHint());
285 selectedList = new KListBox(this);
286 rightvlayout->addWidget(selectedList);
287 connect(selectedList, SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
289 remove = new KPushButton(i18n("&Remove"), this);
290 rightvlayout->addWidget(remove);
291 connect(remove, SIGNAL(clicked()), this, SLOT(removeSelected()));
292 remove->setEnabled(false);
294 clear = new KPushButton(KStdGuiItem::clear(), this);
295 rightvlayout->addWidget(clear);
296 connect(clear, SIGNAL(clicked()), this, SLOT(clearSelected()));
297 clear->setEnabled(false);
299 setCaption(kapp->makeStdCaption(i18n("Radical Selector")));
301 strokesSpin->setValue(config->strokes());
302 strokesSpin->setFocus();
304 totalSpin->setValue(config->totalStrokes());
305 totalErrSpin->setValue(config->totalStrokesErrorMargin());
306 totalStrokes->setChecked(config->searchByTotal());
308 // make sure the right parts of the total stroke
309 // selection system are enabled
310 totalClicked();
312 // initially show the list of radicals to choose from
313 updateList(strokesSpin->value());
316 RadWidget::~RadWidget()
320 void RadWidget::hotlistClicked(int num)
322 addToSelected(*hotlist.at(num));
325 void RadWidget::executed(QListBoxItem *item)
327 addToSelected(item->text());
330 void RadWidget::clearSelected()
332 selectedList->clear();
333 selected.clear();
334 numChanged();
337 void RadWidget::removeSelected()
339 int currentItem = selectedList->currentItem();
340 if (currentItem != -1)
342 selectedList->removeItem(currentItem);
343 selected.remove(selected.at(currentItem));
345 numChanged();
346 selectionChanged();
350 void RadWidget::numChanged()
352 ok->setEnabled(selectedList->count() > 0);
353 clear->setEnabled(selectedList->count() > 0);
356 void RadWidget::addRadical(const QString &radical)
358 addToSelected(radical);
361 void RadWidget::addToSelected(const QString &text)
363 if (!text.isNull() && !selected.contains(text))
365 selectedList->insertItem(text);
366 selected.append(text);
368 numChanged();
369 selectionChanged();
373 void RadWidget::selectionChanged()
375 //kdDebug() << "selectionChanged()" << endl;
376 remove->setEnabled(selectedList->currentItem() != -1);
379 void RadWidget::updateList(int strokes)
381 List->clear();
382 List->insertStringList(rad->radByStrokes(static_cast<unsigned int>(strokes)));
385 void RadWidget::apply()
388 if (selected.count() < 1)
389 return;
391 emit set(selected, totalStrokes->isChecked() ? totalSpin->value() : 0, totalErrSpin->value());
393 Config* config = Config::self();
394 config->setStrokes(strokesSpin->value());
395 config->setTotalStrokes(totalSpin->value());
396 config->setTotalStrokesErrorMargin(totalErrSpin->value());
397 config->setSearchByTotal(totalStrokes->isChecked());
399 for (QStringList::Iterator it = selected.begin(); it != selected.end(); ++it)
401 if (hotlist.find(*it) == hotlist.end())
403 if (hotlist.size() >= hotlistNum)
404 hotlist.pop_front(); // stupid stl functions in Qt .. ;)
405 hotlist.append(*it);
407 config->setHotlist(hotlist);
410 config->writeConfig();
411 close();
414 void RadWidget::totalClicked()
416 bool enable = totalStrokes->isChecked();
417 totalSpin->setEnabled(enable);
418 totalErrSpin->setEnabled(enable);
419 totalErrLabel->setEnabled(enable);
422 //////////////////////////////////////////////
424 Radical::Radical(QString text, unsigned int strokes)
426 _Radical = text;
427 Strokes = strokes;
430 void Radical::addKanji(const QString &text)
432 Kanji.append(text);
435 #include "rad.moc"