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.
tdeedu/kiten/widgets.cpp

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(tqcolorGroup());
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"