diff options
Diffstat (limited to 'kiten/widgets.cpp')
-rw-r--r-- | kiten/widgets.cpp | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/kiten/widgets.cpp b/kiten/widgets.cpp new file mode 100644 index 00000000..989c777d --- /dev/null +++ b/kiten/widgets.cpp @@ -0,0 +1,514 @@ +/** + 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 <kaction.h> +#include <kapplication.h> +#include <kconfig.h> +#include <klistview.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kprinter.h> +#include <kprocess.h> +#include <kstandarddirs.h> +#include <kstatusbar.h> +#include <qfileinfo.h> +#include <qpaintdevicemetrics.h> +#include <qpainter.h> +#include <qregexp.h> +#include <qsimplerichtext.h> +#include <qtextcodec.h> + +#include <cassert> + +#include "kitenconfig.h" +#include "dict.h" +#include "kromajiedit.h" +#include "widgets.h" + +ResultView::ResultView(bool showLinks, QWidget *parent, const char *name) + : KTextBrowser(parent, name) +{ + setReadOnly(true); + setLinkUnderline(false); + basicMode = false; + links = showLinks; + + // don't let ktextbrowser internally handle link clicks + setNotifyClick(true); +} + +void ResultView::addResult(Dict::Entry result, bool common) +{ + if (result.dictName() != "__NOTSET") + { + addHeader((common? i18n("Common results from %1") : i18n("Results from %1")).arg(result.dictName()), 5); + return; + } + if (result.header() != "__NOTSET") + { + addHeader(result.header()); + return; + } + + QString html; + if (result.kanaOnly()) + html = QString("<p><font size=\"+2\">%1</font> ").arg(result.firstReading()); + else + html = QString("<p><font size=\"+2\">%1</font>: %2 ").arg(putchars(result.kanji())).arg(result.firstReading()); + + QStringList::Iterator it; + QStringList Meanings = result.meanings(); + for (it = Meanings.begin(); it != Meanings.end(); ++it) + { + if ((*it).find("(P)") >= 0) + { + if (common) + continue; + else + { + html += QString("<strong>") + i18n("Common") + QString("</strong> "); + } + } + else + { + html += (*it); + html += "; "; + } + } + + html += "</p>"; + + append(html); +} + +void ResultView::addKanjiResult(Dict::Entry result, bool common, Radical rad) +{ + if (result.dictName() != "__NOTSET") + { + addHeader((common? i18n("Common results from %1") : i18n("Results from %1")).arg(result.dictName()), 5); + return; + } + if (result.header() != "__NOTSET") + { + addHeader(result.header()); + return; + } + + QString html; + html = QString("<p><font size=\"+3\">%1</font>: %2 ").arg(putchars(result.kanji())); + + unsigned int freq = result.freq(); + if (freq == 0) // does it have a frequency? + html = html.arg(i18n("Rare")); + else + // this isn't a number of times, it's simply an index of + // probability + html = html.arg(i18n("Probability rank #%1").arg(freq)); + + html += "<br />"; + + QStringList::Iterator it; + QStringList Readings = result.readings(); + for (it = Readings.begin(); it != Readings.end(); ++it) + { + if ((*it) == "T1") + { + if (basicMode) + break; + + html.truncate(html.length() - 2); // get rid of last , + html += i18n("<br />In names: "); + } + else + { + if ((*it) == "T2") + { + if (basicMode) + break; + + html.truncate(html.length() - 2); + html += i18n("<br />As radical: "); + } + else + { + html += (*it); + html += ", "; + } + } + } + html.truncate(html.length() - 2); + + html += "<br />"; + + QStringList Meanings = result.meanings(); + for (it = Meanings.begin(); it != Meanings.end(); ++it) + { + html += (*it); + html += "; "; + } + html.truncate(html.length() - 2); + html += "<br />"; + html += i18n("Grade Level: %1. Strokes: %2."); + + switch (result.grade()) + { + case 0: + html = html.arg(i18n("None")); + break; + case 8: + html = html.arg(i18n("In Jouyou")); + break; + case 9: + html = html.arg(i18n("In Jinmeiyou")); + break; + default: + html = html.arg(result.grade()); + } + + html = html.arg(result.strokes()); + + if (result.miscount() != 0) + html.append(i18n(" Common Miscount: %1.").arg(result.miscount())); + + if (!!rad.radical()) + html.append(i18n(" Largest radical: %1, with %2 strokes.").arg(QString("<a href=\"__radical:%1\">%2</a>").arg(rad.radical()).arg(rad.radical())).arg(rad.strokes())); + + html += "</p>"; + + append(html); +} + +void ResultView::addHeader(const QString &header, unsigned int degree) +{ + append(QString("<h%1>%2</h%3>").arg(degree).arg(header).arg(degree)); +} + +QString ResultView::putchars(const QString &text) +{ + if (!links) + return text; + + unsigned int len = text.length(); + QString ret; + + for (unsigned i = 0; i < len; i++) + { + if (Dict::textType(QString(text.at(i))) == Dict::Text_Kanji) + ret.append(QString("<a href=\"%1\">%1</a>").arg(text.at(i)).arg(text.at(i))); + else + ret.append(text.at(i)); + } + + return ret; +} + +void ResultView::append(const QString &text) +{ + printText.append(text); +} + +void ResultView::clear() +{ + printText = ""; +} + +void ResultView::flush() +{ + setText(printText); + setCursorPosition(0, 0); + ensureCursorVisible(); +} + +void ResultView::print(QString title) +{ + KPrinter printer; + printer.setFullPage(true); + if (printer.setup(this, i18n("Print Japanese Reference"))) + { + QPainter p(&printer); + QPaintDeviceMetrics metrics(p.device()); + int dpix = metrics.logicalDpiX(); + int dpiy = metrics.logicalDpiY(); + const int margin = 72; // pt + + QRect body(dpix, dpiy, metrics.width() - margin * dpix / margin * 2, metrics.height() - margin * dpiy / margin * 2); + + QSimpleRichText richText(title.isNull()? printText : i18n("<h1>Search for \"%1\"</h1>").arg(title) + printText, font(), context(), styleSheet(), mimeSourceFactory(), body.height(), Qt::black, false); + richText.setWidth(&p, body.width()); + QRect view(body); + int page = 1; + + QColorGroup goodColorGroup = QColorGroup(colorGroup()); + goodColorGroup.setColor(QColorGroup::Link, Qt::black); + + do + { + richText.draw(&p, body.left(), body.top(), view, goodColorGroup); + view.moveBy(0, body.height()); + p.translate(0, -body.height()); + + QFont myFont(font()); + myFont.setPointSize(9); + p.setFont(myFont); + QString footer(QString("%1 - Kiten").arg(QString::number(page))); + p.drawText(view.right() - p.fontMetrics().width(footer), view.bottom() + p.fontMetrics().ascent() + 5, footer); + + + if (view.top() >= richText.height()) + break; + + printer.newPage(); + page++; + + kapp->processEvents(); + } + while (true); + } +} + +void ResultView::updateFont() +{ + setFont(Config::self()->font()); +} + +///////////////////////////////////////////////////// +// nice EDICT dictionary editor + +eEdit::eEdit(const QString &_filename, QWidget *parent, const char *name) + : KMainWindow(parent, name) + , filename(_filename) +{ + List = new KListView(this); + setCentralWidget(List); + + List->addColumn(i18n("Kanji")); + List->addColumn(i18n("Reading")); + List->addColumn(i18n("Meanings")); + List->addColumn(i18n("Common")); + List->setItemsRenameable(true); + List->setRenameable(0); + List->setRenameable(1); + List->setRenameable(2); + List->setRenameable(3); + + List->setAllColumnsShowFocus(true); + List->setColumnWidthMode(0, QListView::Maximum); + List->setColumnWidthMode(1, QListView::Maximum); + List->setColumnWidthMode(2, QListView::Maximum); + List->setColumnWidthMode(3, QListView::Maximum); + List->setMultiSelection(true); + List->setDragEnabled(true); + + saveAct = KStdAction::save(this, SLOT(save()), actionCollection()); + removeAct = new KAction(i18n("&Delete"), "edit_remove", CTRL + Key_X, this, SLOT(del()), actionCollection(), "del"); + (void) new KAction(i18n("&Disable Dictionary"), 0, this, SLOT(disable()), actionCollection(), "disable"); + addAct = new KAction(i18n("&Add"), "edit_add", CTRL + Key_A, this, SLOT(add()), actionCollection(), "add"); + (void) KStdAction::close(this, SLOT(close()), actionCollection()); + + createGUI("eeditui.rc"); + //closeAction->plug(toolBar()); + + openFile(filename); + + isMod = false; +} + +eEdit::~eEdit() +{ +} + +void eEdit::add() +{ + if (List) + new KListViewItem(List); +} + +void eEdit::openFile(const QString &file) +{ + QFile f(file); + if (!f.open(IO_ReadOnly)) + return; + + QTextStream t(&f); + QString s; + + while (!t.eof()) + { + s = t.readLine(); + if (s.left(1) == "#" || s.isEmpty()) + continue; + Dict::Entry entry = Dict::parse(s); + QString meanings = Dict::prettyMeaning(entry.meanings()); + bool common = meanings.find(QString("(P)")) >= 0; + meanings.replace(QRegExp("; "), "/"); + meanings.replace(QRegExp("/\\(P\\)"), ""); + new QListViewItem(List, entry.kanji(), Dict::prettyKanjiReading(entry.readings()), meanings, common? i18n("yes") : i18n("no")); + } +} + +void eEdit::save() +{ + QFile f(filename); + if (!f.open(IO_WriteOnly)) + return; + QTextStream t(&f); + + t << "# Generated by Kiten's EDICT editor" << endl << "# http://katzbrown.com/kiten" << endl << endl; + + QListViewItemIterator it(List); + for (; it.current(); ++it) + { + QString kanji = it.current()->text(0); + QString reading = it.current()->text(1); + QString text = kanji.isEmpty()? reading : kanji; + + QString meanings = it.current()->text(2); + if (meanings.right(1) != "/") + meanings.append("/"); + if (meanings.left(1) != "/") + meanings.prepend("/"); + + QString commonString = it.current()->text(3).lower(); + bool common = (commonString == "true" || commonString == "yes" || commonString == "1" || commonString == "common"); + + text.append(" "); + if (!kanji.isEmpty()) + text.append(QString("[%1] ").arg(reading)); + text.append(meanings); + + if (common) + text.append("(P)/"); + + t << text << endl; + } + + f.flush(); + + // find the index generator executable + KProcess proc; + proc << KStandardDirs::findExe("kitengen") << filename << KGlobal::dirs()->saveLocation("data", "kiten/xjdx/", true) + QFileInfo(filename).baseName() + ".xjdx"; + // TODO: put up a status dialog and event loop instead of blocking + proc.start(KProcess::Block, KProcess::NoCommunication); + + statusBar()->message(i18n("Saved")); + isMod = false; +} + +void eEdit::disable() +{ + int result = KMessageBox::warningYesNo(this, i18n("Disabling your personal dictionary will delete its contents.\n\n(You can however always create your dictionary again.)"), QString::null, i18n("Disable"), KStdGuiItem::cancel(), "DisableAsk", true); + if (result == KMessageBox::No) + return; + + QFile::remove(filename); + delete this; +} + +void eEdit::del() +{ + QPtrList<QListViewItem> selected = List->selectedItems(); + assert(selected.count()); + + for(QPtrListIterator<QListViewItem> i(selected); *i; ++i) + delete *i; + + isMod = true; +} + +///////////////////////////////////////////////////// +// sorta taken from konqy + +EditAction::EditAction(const QString& text, int accel, const QObject *receiver, const char *member, QObject* parent, const char* name) + : KAction(text, accel, parent, name) +{ + m_receiver = receiver; + m_member = member; +} + +EditAction::~EditAction() +{ +} + +int EditAction::plug( QWidget *w, int index ) +{ + // if ( !w->inherits( "KToolBar" ) ) + // return -1; + + KToolBar *toolBar = (KToolBar *)w; + + int id = KAction::getToolButtonID(); + + KRomajiEdit *comboBox = new KRomajiEdit(toolBar, "search edit"); + toolBar->insertWidget( id, 70, comboBox, index ); + connect( comboBox, SIGNAL( returnPressed()), m_receiver, m_member ); + + addContainer(toolBar, id); + + connect( toolBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + + toolBar->setItemAutoSized( id, true ); + + m_combo = comboBox; + + emit plugged(); + + //QWhatsThis::add( comboBox, whatsThis() ); + + return containerCount() - 1; +} + +void EditAction::unplug( QWidget *w ) +{ +// if ( !w->inherits( "KToolBar" ) ) +// return; + + KToolBar *toolBar = (KToolBar *)w; + + int idx = findContainer( w ); + + toolBar->removeItem( itemId( idx ) ); + + removeContainer( idx ); + m_combo = 0L; +} + +void EditAction::clear() +{ + m_combo->clear(); + m_combo->setFocus(); +} + +void EditAction::insert(const QString &text) +{ + m_combo->insert(text); +} + +void EditAction::setText(const QString &text) +{ + m_combo->setText(text); +} + +QGuardedPtr<KLineEdit> EditAction::editor() +{ + return m_combo; +} + +#include "widgets.moc" |