diff options
Diffstat (limited to 'kiten/rad.cpp')
-rw-r--r-- | kiten/rad.cpp | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/kiten/rad.cpp b/kiten/rad.cpp new file mode 100644 index 00000000..79986301 --- /dev/null +++ b/kiten/rad.cpp @@ -0,0 +1,435 @@ +/** + This file is part of Kiten, a KDE Japanese Reference Tool... + Copyright (C) 2001 Jason Katz-Brown <jason@katzbrown.com> + (C) 2005 Paul Temple <paul.temple@gmx.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + USA +**/ + +#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kdialog.h> +#include <klistbox.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kpushbutton.h> +#include <kstandarddirs.h> + +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qfile.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qspinbox.h> +#include <qtextcodec.h> +#include <qtooltip.h> + +#include "kitenconfig.h" +#include "rad.h" + +Rad::Rad() : QObject() +{ + loaded = false; +} + +void Rad::load() +{ + if (loaded) + return; + + KStandardDirs *dirs = KGlobal::dirs(); + QString radkfile = dirs->findResource("data", "kiten/radkfile"); + if (radkfile.isNull()) + { + KMessageBox::error(0, i18n("Kanji radical information file not installed, so radical searching cannot be used.")); + return; + } + + QFile f(radkfile); + + if (!f.open(IO_ReadOnly)) + { + KMessageBox::error(0, i18n("Kanji radical information could not be loaded, so radical searching cannot be used.")); + } + + QTextStream t(&f); + t.setCodec(QTextCodec::codecForName("eucJP")); + Radical cur; + while (!t.eof()) + { + QString s = t.readLine(); + + QChar first = s.at(0); + if (first == '#') // comment! + { + // nothing + } + else if (first == '$') // header + { + // save previous one + if( !cur.kanji().isNull() ) + list.append(cur); + + //first entry is trim(last 4 chars).. <rad><space><strokes> + unsigned int strokes = s.right(2).toUInt(); + QString radical = QString(s.at(2)); + cur = Radical(radical, strokes); + } + else // continuation + { + cur.addKanji(s); + } + } + + // we gotta append the last one!! + // this nagged jasonkb for a bit wondering why fue wasn't showing up ;) + list.append(cur); + + f.close(); + + loaded = true; +} + +QStringList Rad::radByStrokes(unsigned int strokes) +{ + load(); + + QStringList ret; + bool hadOne = false; + QValueListIterator<Radical> it = list.begin(); + + do + { + if ((*it).strokes() == strokes) + { + ret.append((*it).radical()); + hadOne = true; + } + else if(hadOne) // shortcut because it's a sorted list + { + return ret; + } + } + while (++it != list.end()); + + return ret; +} + +QStringList Rad::kanjiByRad(const QString &text) +{ + //kdDebug() << "kanjiByRad, text is " << text << endl; + load(); + QStringList ret; + + QValueListIterator<Radical> it; + for (it = list.begin(); it != list.end() && (*it).radical() != text; ++it) + { + //kdDebug() << "kanjiByRad, looping, radical is " << (*it).radical() << endl; + } + + QString kanji = (*it).kanji(); + for (unsigned i = 0; i < kanji.length(); ++i) + { + //kdDebug() << "kanjiByRad, i is " << i << endl; + ret.append(QString(kanji.at(i))); + } + + return ret; +} + +QStringList Rad::kanjiByRad(const QStringList &list) +{ + //kdDebug() << "kanjiByRad (list version)\n"; + + QStringList ret; + QValueList<QStringList> lists; + + for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) + { + //kdDebug() << "loading radical " << *it << endl; + lists.append(kanjiByRad(*it)); + } + + QStringList first = lists.first(); + lists.pop_front(); + + for (QStringList::Iterator kit = first.begin(); kit != first.end(); ++kit) + { + //kdDebug() << "kit is " << *kit << endl; + QValueList<bool> outcomes; + for (QValueList<QStringList>::Iterator it = lists.begin(); it != lists.end(); ++it) + { + //kdDebug() << "looping through lists\n"; + outcomes.append((*it).contains(*kit) > 0); + } + + const bool containsBool = false; + if ((outcomes.contains(containsBool) < 1)) + { + //kdDebug() << "appending " << *kit << endl; + ret.append(*kit); + } + else + { + //kdDebug() << "not appending " << *kit << endl; + } + } + + return ret; +} + +Radical Rad::radByKanji(const QString &text) +{ + load(); + QString ret; + + QValueListIterator<Radical> it; + for (it = list.end(); it != list.begin() && (*it).kanji().find(text) == -1; --it); + + return (*it); +} + +unsigned int Rad::strokesByRad(const QString &text) +{ + load(); + QValueListIterator<Radical> it; + for(it = list.begin(); it != list.end() && (*it).radical() != text; ++it); + + return (*it).strokes(); +} + +Rad::~Rad() +{ +} + +/////////////////////////////////////////////// + +RadWidget::RadWidget(Rad *_rad, QWidget *parent, const char *name) : QWidget(parent, name) +{ + hotlistNum = 3; + + rad = _rad; + QHBoxLayout *hlayout = new QHBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint()); + QVBoxLayout *vlayout = new QVBoxLayout(hlayout, KDialog::spacingHint()); + + hotlistGroup = new QButtonGroup(1, Horizontal, i18n("Hotlist"), this); + //hotlistGroup->setRadioButtonExclusive(true); + vlayout->addWidget(hotlistGroup); + + Config* config = Config::self(); + + hotlist = config->hotlist(); + + while (hotlist.size() > hotlistNum) + hotlist.pop_front(); + + for (unsigned int i = 0; i < hotlistNum; ++i) + { + if (i >= hotlistNum) + break; + + hotlistGroup->insert(new KPushButton(*hotlist.at(i), hotlistGroup), i); + } + connect(hotlistGroup, SIGNAL(clicked(int)), SLOT(hotlistClicked(int))); + + QVBoxLayout *layout = new QVBoxLayout(vlayout, KDialog::spacingHint()); + + totalStrokes = new QCheckBox(i18n("Search by total strokes"), this); + connect(totalStrokes, SIGNAL(clicked()), this, SLOT(totalClicked())); + layout->addWidget(totalStrokes); + + QHBoxLayout *strokesLayout = new QHBoxLayout(layout, KDialog::spacingHint()); + totalSpin = new QSpinBox(1, 30, 1, this); + strokesLayout->addWidget(totalSpin); + strokesLayout->addStretch(); + totalErrLabel = new QLabel(i18n("+/-"), this); + strokesLayout->addWidget(totalErrLabel); + totalErrSpin = new QSpinBox(0, 15, 1, this); + strokesLayout->addWidget(totalErrSpin); + + ok = new KPushButton(i18n("&Look Up"), this); + ok->setEnabled(false); + connect(ok, SIGNAL(clicked()), SLOT(apply())); + layout->addWidget(ok); + cancel = new KPushButton( KStdGuiItem::cancel(), this ); + + connect(cancel, SIGNAL(clicked()), SLOT(close())); + layout->addWidget(cancel); + + QVBoxLayout *middlevLayout = new QVBoxLayout(hlayout, KDialog::spacingHint()); + + strokesSpin = new QSpinBox(1, 17, 1, this); + QToolTip::add(strokesSpin, i18n("Show radicals having this number of strokes")); + middlevLayout->addWidget(strokesSpin); + + List = new KListBox(this); + middlevLayout->addWidget(List); + connect(List, SIGNAL(executed(QListBoxItem *)), this, SLOT(executed(QListBoxItem *))); + connect(strokesSpin, SIGNAL(valueChanged(int)), this, SLOT(updateList(int))); + + QVBoxLayout *rightvlayout = new QVBoxLayout(hlayout, KDialog::spacingHint()); + selectedList = new KListBox(this); + rightvlayout->addWidget(selectedList); + connect(selectedList, SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); + + remove = new KPushButton(i18n("&Remove"), this); + rightvlayout->addWidget(remove); + connect(remove, SIGNAL(clicked()), this, SLOT(removeSelected())); + remove->setEnabled(false); + + clear = new KPushButton(KStdGuiItem::clear(), this); + rightvlayout->addWidget(clear); + connect(clear, SIGNAL(clicked()), this, SLOT(clearSelected())); + clear->setEnabled(false); + + setCaption(kapp->makeStdCaption(i18n("Radical Selector"))); + + strokesSpin->setValue(config->strokes()); + strokesSpin->setFocus(); + + totalSpin->setValue(config->totalStrokes()); + totalErrSpin->setValue(config->totalStrokesErrorMargin()); + totalStrokes->setChecked(config->searchByTotal()); + + // make sure the right parts of the total stroke + // selection system are enabled + totalClicked(); + + // initially show the list of radicals to choose from + updateList(strokesSpin->value()); +} + +RadWidget::~RadWidget() +{ +} + +void RadWidget::hotlistClicked(int num) +{ + addToSelected(*hotlist.at(num)); +} + +void RadWidget::executed(QListBoxItem *item) +{ + addToSelected(item->text()); +} + +void RadWidget::clearSelected() +{ + selectedList->clear(); + selected.clear(); + numChanged(); +} + +void RadWidget::removeSelected() +{ + int currentItem = selectedList->currentItem(); + if (currentItem != -1) + { + selectedList->removeItem(currentItem); + selected.remove(selected.at(currentItem)); + + numChanged(); + selectionChanged(); + } +} + +void RadWidget::numChanged() +{ + ok->setEnabled(selectedList->count() > 0); + clear->setEnabled(selectedList->count() > 0); +} + +void RadWidget::addRadical(const QString &radical) +{ + addToSelected(radical); +} + +void RadWidget::addToSelected(const QString &text) +{ + if (!text.isNull() && !selected.contains(text)) + { + selectedList->insertItem(text); + selected.append(text); + + numChanged(); + selectionChanged(); + } +} + +void RadWidget::selectionChanged() +{ + //kdDebug() << "selectionChanged()" << endl; + remove->setEnabled(selectedList->currentItem() != -1); +} + +void RadWidget::updateList(int strokes) +{ + List->clear(); + List->insertStringList(rad->radByStrokes(static_cast<unsigned int>(strokes))); +} + +void RadWidget::apply() +{ + + if (selected.count() < 1) + return; + + emit set(selected, totalStrokes->isChecked() ? totalSpin->value() : 0, totalErrSpin->value()); + + Config* config = Config::self(); + config->setStrokes(strokesSpin->value()); + config->setTotalStrokes(totalSpin->value()); + config->setTotalStrokesErrorMargin(totalErrSpin->value()); + config->setSearchByTotal(totalStrokes->isChecked()); + + for (QStringList::Iterator it = selected.begin(); it != selected.end(); ++it) + { + if (hotlist.find(*it) == hotlist.end()) + { + if (hotlist.size() >= hotlistNum) + hotlist.pop_front(); // stupid stl functions in Qt .. ;) + hotlist.append(*it); + + config->setHotlist(hotlist); + } + } + config->writeConfig(); + close(); +} + +void RadWidget::totalClicked() +{ + bool enable = totalStrokes->isChecked(); + totalSpin->setEnabled(enable); + totalErrSpin->setEnabled(enable); + totalErrLabel->setEnabled(enable); +} + +////////////////////////////////////////////// + +Radical::Radical(QString text, unsigned int strokes) +{ + _Radical = text; + Strokes = strokes; +} + +void Radical::addKanji(const QString &text) +{ + Kanji.append(text); +} + +#include "rad.moc" |