You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
515 lines
12 KiB
515 lines
12 KiB
/**
|
|
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 <tqfileinfo.h>
|
|
#include <tqpaintdevicemetrics.h>
|
|
#include <tqpainter.h>
|
|
#include <tqregexp.h>
|
|
#include <tqsimplerichtext.h>
|
|
#include <tqtextcodec.h>
|
|
|
|
#include <cassert>
|
|
|
|
#include "kitenconfig.h"
|
|
#include "dict.h"
|
|
#include "kromajiedit.h"
|
|
#include "widgets.h"
|
|
|
|
ResultView::ResultView(bool showLinks, TQWidget *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")).tqarg(result.dictName()), 5);
|
|
return;
|
|
}
|
|
if (result.header() != "__NOTSET")
|
|
{
|
|
addHeader(result.header());
|
|
return;
|
|
}
|
|
|
|
TQString html;
|
|
if (result.kanaOnly())
|
|
html = TQString("<p><font size=\"+2\">%1</font> ").tqarg(result.firstReading());
|
|
else
|
|
html = TQString("<p><font size=\"+2\">%1</font>: %2 ").tqarg(putchars(result.kanji())).tqarg(result.firstReading());
|
|
|
|
TQStringList::Iterator it;
|
|
TQStringList Meanings = result.meanings();
|
|
for (it = Meanings.begin(); it != Meanings.end(); ++it)
|
|
{
|
|
if ((*it).find("(P)") >= 0)
|
|
{
|
|
if (common)
|
|
continue;
|
|
else
|
|
{
|
|
html += TQString("<strong>") + i18n("Common") + TQString("</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")).tqarg(result.dictName()), 5);
|
|
return;
|
|
}
|
|
if (result.header() != "__NOTSET")
|
|
{
|
|
addHeader(result.header());
|
|
return;
|
|
}
|
|
|
|
TQString html;
|
|
html = TQString("<p><font size=\"+3\">%1</font>: %2 ").tqarg(putchars(result.kanji()));
|
|
|
|
unsigned int freq = result.freq();
|
|
if (freq == 0) // does it have a frequency?
|
|
html = html.tqarg(i18n("Rare"));
|
|
else
|
|
// this isn't a number of times, it's simply an index of
|
|
// probability
|
|
html = html.tqarg(i18n("Probability rank #%1").tqarg(freq));
|
|
|
|
html += "<br />";
|
|
|
|
TQStringList::Iterator it;
|
|
TQStringList 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 />";
|
|
|
|
TQStringList 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.tqarg(i18n("None"));
|
|
break;
|
|
case 8:
|
|
html = html.tqarg(i18n("In Jouyou"));
|
|
break;
|
|
case 9:
|
|
html = html.tqarg(i18n("In Jinmeiyou"));
|
|
break;
|
|
default:
|
|
html = html.tqarg(result.grade());
|
|
}
|
|
|
|
html = html.tqarg(result.strokes());
|
|
|
|
if (result.miscount() != 0)
|
|
html.append(i18n(" Common Miscount: %1.").tqarg(result.miscount()));
|
|
|
|
if (!!rad.radical())
|
|
html.append(i18n(" Largest radical: %1, with %2 strokes.").tqarg(TQString("<a href=\"__radical:%1\">%2</a>").tqarg(rad.radical()).tqarg(rad.radical())).tqarg(rad.strokes()));
|
|
|
|
html += "</p>";
|
|
|
|
append(html);
|
|
}
|
|
|
|
void ResultView::addHeader(const TQString &header, unsigned int degree)
|
|
{
|
|
append(TQString("<h%1>%2</h%3>").tqarg(degree).tqarg(header).tqarg(degree));
|
|
}
|
|
|
|
TQString ResultView::putchars(const TQString &text)
|
|
{
|
|
if (!links)
|
|
return text;
|
|
|
|
unsigned int len = text.length();
|
|
TQString ret;
|
|
|
|
for (unsigned i = 0; i < len; i++)
|
|
{
|
|
if (Dict::textType(TQString(text.at(i))) == Dict::Text_Kanji)
|
|
ret.append(TQString("<a href=\"%1\">%1</a>").tqarg(text.tqat(i)).tqarg(text.tqat(i)));
|
|
else
|
|
ret.append(text.at(i));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ResultView::append(const TQString &text)
|
|
{
|
|
printText.append(text);
|
|
}
|
|
|
|
void ResultView::clear()
|
|
{
|
|
printText = "";
|
|
}
|
|
|
|
void ResultView::flush()
|
|
{
|
|
setText(printText);
|
|
setCursorPosition(0, 0);
|
|
ensureCursorVisible();
|
|
}
|
|
|
|
void ResultView::print(TQString title)
|
|
{
|
|
KPrinter printer;
|
|
printer.setFullPage(true);
|
|
if (printer.setup(this, i18n("Print Japanese Reference")))
|
|
{
|
|
TQPainter p(&printer);
|
|
TQPaintDeviceMetrics metrics(p.device());
|
|
int dpix = metrics.logicalDpiX();
|
|
int dpiy = metrics.logicalDpiY();
|
|
const int margin = 72; // pt
|
|
|
|
TQRect body(dpix, dpiy, metrics.width() - margin * dpix / margin * 2, metrics.height() - margin * dpiy / margin * 2);
|
|
|
|
TQSimpleRichText richText(title.isNull()? printText : i18n("<h1>Search for \"%1\"</h1>").tqarg(title) + printText, font(), context(), styleSheet(), mimeSourceFactory(), body.height(), TQt::black, false);
|
|
richText.setWidth(&p, body.width());
|
|
TQRect view(body);
|
|
int page = 1;
|
|
|
|
TQColorGroup goodColorGroup = TQColorGroup(colorGroup());
|
|
goodColorGroup.setColor(TQColorGroup::Link, TQt::black);
|
|
|
|
do
|
|
{
|
|
richText.draw(&p, body.left(), body.top(), view, goodColorGroup);
|
|
view.moveBy(0, body.height());
|
|
p.translate(0, -body.height());
|
|
|
|
TQFont myFont(font());
|
|
myFont.setPointSize(9);
|
|
p.setFont(myFont);
|
|
TQString footer(TQString("%1 - Kiten").tqarg(TQString::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 TQString &_filename, TQWidget *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, TQListView::Maximum);
|
|
List->setColumnWidthMode(1, TQListView::Maximum);
|
|
List->setColumnWidthMode(2, TQListView::Maximum);
|
|
List->setColumnWidthMode(3, TQListView::Maximum);
|
|
List->setMultiSelection(true);
|
|
List->setDragEnabled(true);
|
|
|
|
saveAct = KStdAction::save(TQT_TQOBJECT(this), TQT_SLOT(save()), actionCollection());
|
|
removeAct = new KAction(i18n("&Delete"), "edit_remove", CTRL + Key_X, TQT_TQOBJECT(this), TQT_SLOT(del()), actionCollection(), "del");
|
|
(void) new KAction(i18n("&Disable Dictionary"), 0, TQT_TQOBJECT(this), TQT_SLOT(disable()), actionCollection(), "disable");
|
|
addAct = new KAction(i18n("&Add"), "edit_add", CTRL + Key_A, TQT_TQOBJECT(this), TQT_SLOT(add()), actionCollection(), "add");
|
|
(void) KStdAction::close(TQT_TQOBJECT(this), TQT_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 TQString &file)
|
|
{
|
|
TQFile f(file);
|
|
if (!f.open(IO_ReadOnly))
|
|
return;
|
|
|
|
TQTextStream t(&f);
|
|
TQString s;
|
|
|
|
while (!t.eof())
|
|
{
|
|
s = t.readLine();
|
|
if (s.left(1) == "#" || s.isEmpty())
|
|
continue;
|
|
Dict::Entry entry = Dict::parse(s);
|
|
TQString meanings = Dict::prettyMeaning(entry.meanings());
|
|
bool common = meanings.find(TQString("(P)")) >= 0;
|
|
meanings.replace(TQRegExp("; "), "/");
|
|
meanings.replace(TQRegExp("/\\(P\\)"), "");
|
|
new TQListViewItem(List, entry.kanji(), Dict::prettyKanjiReading(entry.readings()), meanings, common? i18n("yes") : i18n("no"));
|
|
}
|
|
}
|
|
|
|
void eEdit::save()
|
|
{
|
|
TQFile f(filename);
|
|
if (!f.open(IO_WriteOnly))
|
|
return;
|
|
TQTextStream t(&f);
|
|
|
|
t << "# Generated by Kiten's EDICT editor" << endl << "# http://katzbrown.com/kiten" << endl << endl;
|
|
|
|
TQListViewItemIterator it(List);
|
|
for (; it.current(); ++it)
|
|
{
|
|
TQString kanji = it.current()->text(0);
|
|
TQString reading = it.current()->text(1);
|
|
TQString text = kanji.isEmpty()? reading : kanji;
|
|
|
|
TQString meanings = it.current()->text(2);
|
|
if (meanings.right(1) != "/")
|
|
meanings.append("/");
|
|
if (meanings.left(1) != "/")
|
|
meanings.prepend("/");
|
|
|
|
TQString commonString = it.current()->text(3).lower();
|
|
bool common = (commonString == "true" || commonString == "yes" || commonString == "1" || commonString == "common");
|
|
|
|
text.append(" ");
|
|
if (!kanji.isEmpty())
|
|
text.append(TQString("[%1] ").tqarg(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) + TQFileInfo(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.)"), TQString(), i18n("Disable"), KStdGuiItem::cancel(), "DisableAsk", true);
|
|
if (result == KMessageBox::No)
|
|
return;
|
|
|
|
TQFile::remove(filename);
|
|
delete this;
|
|
}
|
|
|
|
void eEdit::del()
|
|
{
|
|
TQPtrList<TQListViewItem> selected = List->selectedItems();
|
|
assert(selected.count());
|
|
|
|
for(TQPtrListIterator<TQListViewItem> i(selected); *i; ++i)
|
|
delete *i;
|
|
|
|
isMod = true;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////
|
|
// sorta taken from konqy
|
|
|
|
EditAction::EditAction(const TQString& text, int accel, const TQObject *receiver, const char *member, TQObject* parent, const char* name)
|
|
: KAction(text, accel, parent, name)
|
|
{
|
|
m_receiver = receiver;
|
|
m_member = member;
|
|
}
|
|
|
|
EditAction::~EditAction()
|
|
{
|
|
}
|
|
|
|
int EditAction::plug( TQWidget *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, TQT_SIGNAL( returnPressed()), m_receiver, m_member );
|
|
|
|
addContainer(toolBar, id);
|
|
|
|
connect( toolBar, TQT_SIGNAL( destroyed() ), TQT_TQOBJECT(this), TQT_SLOT( slotDestroyed() ) );
|
|
|
|
toolBar->setItemAutoSized( id, true );
|
|
|
|
m_combo = comboBox;
|
|
|
|
emit plugged();
|
|
|
|
//TQWhatsThis::add( comboBox, whatsThis() );
|
|
|
|
return containerCount() - 1;
|
|
}
|
|
|
|
void EditAction::unplug( TQWidget *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 TQString &text)
|
|
{
|
|
m_combo->insert(text);
|
|
}
|
|
|
|
void EditAction::setText(const TQString &text)
|
|
{
|
|
m_combo->setText(text);
|
|
}
|
|
|
|
TQGuardedPtr<KLineEdit> EditAction::editor()
|
|
{
|
|
return m_combo;
|
|
}
|
|
|
|
#include "widgets.moc"
|