00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kcharselect.h"
00022
00023 #include "kcharselect_p.h"
00024
00025 #include <QtGui/QActionEvent>
00026 #include <QtGui/QDoubleSpinBox>
00027 #include <QtGui/QHeaderView>
00028 #include <QtGui/QBoxLayout>
00029 #include <QtGui/QShortcut>
00030 #include <QtGui/QSplitter>
00031 #include <QtGui/QPushButton>
00032 #include <QtGui/QToolButton>
00033
00034 #include <kcombobox.h>
00035 #include <kdebug.h>
00036 #include <kdialog.h>
00037 #include <klocale.h>
00038 #include <klineedit.h>
00039 #include <ktextbrowser.h>
00040 #include <kfontcombobox.h>
00041 #include <kactioncollection.h>
00042 #include <kstandardaction.h>
00043
00044 K_GLOBAL_STATIC(KCharSelectData, s_data)
00045
00046 class KCharSelectTablePrivate
00047 {
00048 public:
00049 KCharSelectTablePrivate(KCharSelectTable *q): q(q), model()
00050 {}
00051
00052 KCharSelectTable *q;
00053
00054 QFont font;
00055 KCharSelectItemModel *model;
00056 QList<QChar> chars;
00057 QChar chr;
00058
00059 void _k_resizeCells();
00060 void _k_doubleClicked(const QModelIndex & index);
00061 void _k_slotCurrentChanged(const QModelIndex & current, const QModelIndex & previous);
00062 };
00063
00064 class KCharSelect::KCharSelectPrivate
00065 {
00066 public:
00067 struct HistoryItem
00068 {
00069 QChar c;
00070 bool fromSearch;
00071 QString searchString;
00072 };
00073
00074 enum { MaxHistoryItems = 100 };
00075
00076 KCharSelectPrivate(KCharSelect *q)
00077 : q(q)
00078 ,searchLine(0)
00079 ,searchMode(false)
00080 ,historyEnabled(false)
00081 ,inHistory(0)
00082 ,actions(NULL)
00083 {
00084 }
00085
00086 KCharSelect *q;
00087
00088 QToolButton *backButton;
00089 QToolButton *forwardButton;
00090 KLineEdit* searchLine;
00091 KFontComboBox *fontCombo;
00092 QSpinBox *fontSizeSpinBox;
00093 QComboBox *sectionCombo;
00094 QComboBox *blockCombo;
00095 KCharSelectTable *charTable;
00096 KTextBrowser *detailBrowser;
00097
00098 bool searchMode;
00099 bool historyEnabled;
00100 int inHistory;
00101 QList<HistoryItem> history;
00102 KActionCollection* actions;
00103
00104 QString createLinks(QString s);
00105 void historyAdd(const QChar &c, bool fromSearch, const QString &searchString);
00106 void showFromHistory(int index);
00107 void updateBackForwardButtons();
00108 void _k_activateSearchLine();
00109 void _k_back();
00110 void _k_forward();
00111 void _k_fontSelected();
00112 void _k_updateCurrentChar(const QChar &c);
00113 void _k_slotUpdateUnicode(const QChar &c);
00114 void _k_sectionSelected(int index);
00115 void _k_blockSelected(int index);
00116 void _k_searchEditChanged();
00117 void _k_search();
00118 void _k_linkClicked(QUrl url);
00119 };
00120
00121
00122
00123
00124
00125 KCharSelectTable::KCharSelectTable(QWidget *parent, const QFont &_font)
00126 : QTableView(parent), d(new KCharSelectTablePrivate(this))
00127 {
00128 d->font = _font;
00129
00130 setTabKeyNavigation(false);
00131 setSelectionMode(QAbstractItemView::SingleSelection);
00132 QPalette _palette;
00133 _palette.setColor(backgroundRole(), palette().color(QPalette::Base));
00134 setPalette(_palette);
00135 verticalHeader()->setVisible(false);
00136 verticalHeader()->setResizeMode(QHeaderView::Custom);
00137 horizontalHeader()->setVisible(false);
00138 horizontalHeader()->setResizeMode(QHeaderView::Custom);
00139
00140 setFocusPolicy(Qt::StrongFocus);
00141 setDragEnabled(true);
00142 setAcceptDrops(true);
00143 setDropIndicatorShown(false);
00144 setDragDropMode(QAbstractItemView::DragDrop);
00145
00146 connect(this, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(_k_doubleClicked(QModelIndex)));
00147
00148 d->_k_resizeCells();
00149 }
00150
00151 KCharSelectTable::~KCharSelectTable()
00152 {
00153 delete d;
00154 }
00155
00156 void KCharSelectTable::setFont(const QFont &_font)
00157 {
00158 QTableView::setFont(_font);
00159 d->font = _font;
00160 if (d->model) d->model->setFont(_font);
00161 d->_k_resizeCells();
00162 }
00163
00164 QChar KCharSelectTable::chr()
00165 {
00166 return d->chr;
00167 }
00168
00169 QFont KCharSelectTable::font() const
00170 {
00171 return d->font;
00172 }
00173
00174 QList<QChar> KCharSelectTable::displayedChars() const
00175 {
00176 return d->chars;
00177 }
00178
00179 void KCharSelectTable::setChar(const QChar &c)
00180 {
00181 int pos = d->chars.indexOf(c);
00182 if (pos != -1) {
00183 setCurrentIndex(model()->index(pos / model()->columnCount(), pos % model()->columnCount()));
00184 }
00185 }
00186
00187 void KCharSelectTable::setContents(QList<QChar> chars)
00188 {
00189 d->chars = chars;
00190
00191 KCharSelectItemModel *m = d->model;
00192 d->model = new KCharSelectItemModel(chars, d->font, this);
00193 setModel(d->model);
00194 d->_k_resizeCells();
00195 QItemSelectionModel *selectionModel = new QItemSelectionModel(d->model);
00196 setSelectionModel(selectionModel);
00197 setSelectionBehavior(QAbstractItemView::SelectItems);
00198 setSelectionMode(QAbstractItemView::SingleSelection);
00199 connect(selectionModel, SIGNAL(currentChanged(const QModelIndex & , const QModelIndex &)), this, SLOT(_k_slotCurrentChanged(const QModelIndex &, const QModelIndex &)));
00200 connect(d->model, SIGNAL(showCharRequested(QChar)), this, SIGNAL(showCharRequested(QChar)));
00201 delete m;
00202 }
00203
00204 void KCharSelectTable::scrollTo(const QModelIndex & index, ScrollHint hint)
00205 {
00206
00207 if (index.isValid() && index.column() != 0) {
00208 QTableView::scrollTo(d->model->index(index.row(), 0), hint);
00209 } else {
00210 QTableView::scrollTo(index, hint);
00211 }
00212 }
00213
00214 void KCharSelectTablePrivate::_k_slotCurrentChanged(const QModelIndex & current, const QModelIndex & previous)
00215 {
00216 Q_UNUSED(previous);
00217 if (!model) return;
00218 QVariant temp = model->data(current, KCharSelectItemModel::CharacterRole);
00219 if (temp.type() != QVariant::Char)
00220 return;
00221 QChar c = temp.toChar();
00222 chr = c;
00223 emit q->focusItemChanged(c);
00224 }
00225
00226 void KCharSelectTable::resizeEvent(QResizeEvent * e)
00227 {
00228 QTableView::resizeEvent(e);
00229 if (e->size().width() != e->oldSize().width()) {
00230 d->_k_resizeCells();
00231 }
00232 }
00233
00234 void KCharSelectTablePrivate::_k_resizeCells()
00235 {
00236 if (!q->model()) return;
00237 static_cast<KCharSelectItemModel*>(q->model())->updateColumnCount(q->viewport()->size().width());
00238
00239 QChar oldChar = q->chr();
00240
00241 const int new_w = q->viewport()->size().width() / q->model()->columnCount(QModelIndex());
00242 const int columns = q->model()->columnCount(QModelIndex());
00243 const int rows = q->model()->rowCount(QModelIndex());
00244 q->setUpdatesEnabled(false);
00245 QHeaderView* hv = q->horizontalHeader();
00246 int spaceLeft = q->viewport()->size().width() % new_w + 1;
00247 for (int i = 0;i <= columns;i++) {
00248 if (i < spaceLeft) {
00249 hv->resizeSection(i, new_w + 1);
00250 } else {
00251 hv->resizeSection(i, new_w);
00252 }
00253 }
00254
00255 hv = q->verticalHeader();
00256 #ifdef Q_WS_WIN
00257 const int new_h = QFontMetrics(font).lineSpacing() + 1;
00258 #else
00259 const int new_h = QFontMetrics(font).xHeight() * 3;
00260 #endif
00261 for (int i = 0;i < rows;i++) {
00262 hv->resizeSection(i, new_h);
00263 }
00264
00265 q->setUpdatesEnabled(true);
00266 q->setChar(oldChar);
00267 }
00268
00269 void KCharSelectTablePrivate::_k_doubleClicked(const QModelIndex & index)
00270 {
00271 QChar c = model->data(index, KCharSelectItemModel::CharacterRole).toChar();
00272 if (c.isPrint()) {
00273 emit q->activated(c);
00274 }
00275 }
00276
00277 void KCharSelectTable::keyPressEvent(QKeyEvent *e)
00278 {
00279 if (d->model)
00280 switch (e->key()) {
00281 case Qt::Key_Space:
00282 emit activated(' ');
00283 return;
00284 break;
00285 case Qt::Key_Enter: case Qt::Key_Return: {
00286 if (!currentIndex().isValid()) return;
00287 QChar c = d->model->data(currentIndex(), KCharSelectItemModel::CharacterRole).toChar();
00288 if (c.isPrint()) {
00289 emit activated(c);
00290 }
00291 }
00292 return;
00293 break;
00294 }
00295 QTableView::keyPressEvent(e);
00296 }
00297
00298
00299
00300
00301
00302
00303 KCharSelect::KCharSelect(QWidget *parent, const Controls controls)
00304 : QWidget(parent), d(new KCharSelectPrivate(this))
00305 {
00306 init(controls, NULL);
00307 }
00308
00309 KCharSelect::KCharSelect(
00310 QWidget *parent
00311 ,KActionCollection *collection
00312 ,const Controls controls)
00313 : QWidget(parent), d(new KCharSelectPrivate(this))
00314 {
00315 init(controls, collection);
00316 }
00317
00318 void KCharSelect::init(const Controls controls, KActionCollection *collection)
00319 {
00320 if (collection==NULL) {
00321 d->actions = new KActionCollection(this);
00322 d->actions->addAssociatedWidget(this);
00323 } else {
00324 d->actions = collection;
00325 }
00326
00327 QVBoxLayout *mainLayout = new QVBoxLayout(this);
00328 mainLayout->setMargin(0);
00329 if (SearchLine & controls) {
00330 QHBoxLayout *searchLayout = new QHBoxLayout();
00331 mainLayout->addLayout(searchLayout);
00332 d->searchLine = new KLineEdit(this);
00333 searchLayout->addWidget(d->searchLine);
00334 d->searchLine->setClickMessage(i18n("Enter a search term or character here"));
00335 d->searchLine->setClearButtonShown(true);
00336 d->searchLine->setToolTip(i18n("Enter a search term or character here"));
00337 KStandardAction::find(this, SLOT(_k_activateSearchLine()), d->actions);
00338 connect(d->searchLine, SIGNAL(textChanged(QString)), this, SLOT(_k_searchEditChanged()));
00339 connect(d->searchLine, SIGNAL(returnPressed()), this, SLOT(_k_search()));
00340 }
00341
00342 if ((SearchLine & controls) && ((FontCombo & controls) || (FontSize & controls) || (BlockCombos & controls))) {
00343 QFrame* line = new QFrame(this);
00344 line->setFrameShape(QFrame::HLine);
00345 line->setFrameShadow(QFrame::Sunken);
00346 mainLayout->addWidget(line);
00347 }
00348
00349 QHBoxLayout *comboLayout = new QHBoxLayout();
00350
00351 d->backButton = new QToolButton(this);
00352 comboLayout->addWidget(d->backButton);
00353 d->backButton->setEnabled(false);
00354 d->backButton->setText(i18n("Back"));
00355 d->backButton->setIcon(KIcon("go-previous"));
00356 d->backButton->setToolTip(i18n("Previous Character"));
00357
00358 d->forwardButton = new QToolButton(this);
00359 comboLayout->addWidget(d->forwardButton);
00360 d->forwardButton->setEnabled(false);
00361 d->forwardButton->setText(i18n("Forward"));
00362 d->forwardButton->setIcon(KIcon("go-next"));
00363 d->forwardButton->setToolTip(i18n("Next Character"));
00364
00365 KStandardAction::back(d->backButton, SLOT(animateClick()), d->actions);
00366 KStandardAction::forward(d->forwardButton, SLOT(animateClick()), d->actions);
00367 connect(d->backButton, SIGNAL(clicked()), this, SLOT(_k_back()));
00368 connect(d->forwardButton, SIGNAL(clicked()), this, SLOT(_k_forward()));
00369
00370 d->sectionCombo = new KComboBox(this);
00371 d->sectionCombo->setToolTip(i18n("Select a category"));
00372 comboLayout->addWidget(d->sectionCombo);
00373 d->blockCombo = new KComboBox(this);
00374 d->blockCombo->setToolTip(i18n("Select a block to be displayed"));
00375 d->blockCombo->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
00376 comboLayout->addWidget(d->blockCombo, 1);
00377 d->sectionCombo->addItems(s_data->sectionList());
00378 d->blockCombo->setMinimumWidth(QFontMetrics(QWidget::font()).averageCharWidth() * 25);
00379
00380 connect(d->sectionCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(_k_sectionSelected(int)));
00381 connect(d->blockCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(_k_blockSelected(int)));
00382
00383 d->fontCombo = new KFontComboBox(this);
00384 comboLayout->addWidget(d->fontCombo);
00385 d->fontCombo->setEditable(true);
00386 d->fontCombo->resize(d->fontCombo->sizeHint());
00387 d->fontCombo->setToolTip(i18n("Set font"));
00388
00389 d->fontSizeSpinBox = new QSpinBox(this);
00390 comboLayout->addWidget(d->fontSizeSpinBox);
00391 d->fontSizeSpinBox->setValue(QWidget::font().pointSize());
00392 d->fontSizeSpinBox->setRange(1, 400);
00393 d->fontSizeSpinBox->setSingleStep(1);
00394 d->fontSizeSpinBox->setToolTip(i18n("Set font size"));
00395
00396 connect(d->fontCombo, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(_k_fontSelected()));
00397 connect(d->fontSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(_k_fontSelected()));
00398
00399 if ((HistoryButtons & controls) || (FontCombo & controls) || (FontSize & controls) || (BlockCombos & controls)) {
00400 mainLayout->addLayout(comboLayout);
00401 }
00402 if (!(HistoryButtons & controls)) {
00403 d->backButton->hide();
00404 d->forwardButton->hide();
00405 }
00406 if (!(FontCombo & controls)) {
00407 d->fontCombo->hide();
00408 }
00409 if (!(FontSize & controls)) {
00410 d->fontSizeSpinBox->hide();
00411 }
00412 if (!(BlockCombos & controls)) {
00413 d->sectionCombo->hide();
00414 d->blockCombo->hide();
00415 }
00416
00417 QSplitter *splitter = new QSplitter(this);
00418 if ((CharacterTable & controls) || (DetailBrowser & controls)) {
00419 mainLayout->addWidget(splitter);
00420 } else {
00421 splitter->hide();
00422 }
00423 d->charTable = new KCharSelectTable(this, QFont());
00424 if (CharacterTable & controls) {
00425 splitter->addWidget(d->charTable);
00426 d->charTable->setFocus(Qt::OtherFocusReason);
00427 } else {
00428 d->charTable->hide();
00429 }
00430
00431 const QSize sz(200, 200);
00432 d->charTable->resize(sz);
00433 d->charTable->setMinimumSize(sz);
00434
00435 d->charTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00436
00437 setCurrentFont(QFont());
00438
00439 connect(d->charTable, SIGNAL(focusItemChanged(const QChar &)), this, SLOT(_k_updateCurrentChar(const QChar &)));
00440 connect(d->charTable, SIGNAL(activated(const QChar &)), this, SIGNAL(charSelected(const QChar &)));
00441 connect(d->charTable, SIGNAL(focusItemChanged(const QChar &)),
00442 this, SIGNAL(currentCharChanged(const QChar &)));
00443
00444 connect(d->charTable, SIGNAL(showCharRequested(QChar)), this, SLOT(setCurrentChar(QChar)));
00445
00446 d->detailBrowser = new KTextBrowser(this);
00447 if (DetailBrowser & controls) {
00448 splitter->addWidget(d->detailBrowser);
00449 } else {
00450 d->detailBrowser->hide();
00451 }
00452 d->detailBrowser->setOpenLinks(false);
00453 connect(d->detailBrowser, SIGNAL(anchorClicked(QUrl)), this, SLOT(_k_linkClicked(QUrl)));
00454
00455 setFocusPolicy(Qt::StrongFocus);
00456 setFocusProxy(d->charTable);
00457 d->_k_sectionSelected(0);
00458 d->_k_blockSelected(0);
00459 setCurrentChar(0x0);
00460
00461 d->historyEnabled = true;
00462 }
00463
00464 KCharSelect::~KCharSelect()
00465 {
00466 delete d;
00467 }
00468
00469 QSize KCharSelect::sizeHint() const
00470 {
00471 return QWidget::sizeHint();
00472 }
00473
00474 void KCharSelect::setCurrentFont(const QFont &_font)
00475 {
00476 d->fontCombo->setCurrentFont(_font);
00477 d->fontSizeSpinBox->setValue(_font.pointSize());
00478 d->_k_fontSelected();
00479 }
00480
00481 QChar KCharSelect::currentChar() const
00482 {
00483 return d->charTable->chr();
00484 }
00485
00486 QFont KCharSelect::currentFont() const
00487 {
00488 return d->charTable->font();
00489 }
00490
00491 QList<QChar> KCharSelect::displayedChars() const
00492 {
00493 return d->charTable->displayedChars();
00494 }
00495
00496 void KCharSelect::setCurrentChar(const QChar &c)
00497 {
00498 bool oldHistoryEnabled = d->historyEnabled;
00499 d->historyEnabled = false;
00500 int block = s_data->blockIndex(c);
00501 int section = s_data->sectionIndex(block);
00502 d->sectionCombo->setCurrentIndex(section);
00503 int index = d->blockCombo->findData(block);
00504 if (index != -1) {
00505 d->blockCombo->setCurrentIndex(index);
00506 }
00507 d->historyEnabled = oldHistoryEnabled;
00508 d->charTable->setChar(c);
00509 }
00510
00511 void KCharSelect::KCharSelectPrivate::historyAdd(const QChar &c, bool fromSearch, const QString &searchString)
00512 {
00513
00514
00515 if (!historyEnabled) {
00516 return;
00517 }
00518
00519 if (!history.isEmpty() && c == history.last().c) {
00520
00521 return;
00522 }
00523
00524
00525 while (!history.isEmpty() && inHistory != history.count() - 1) {
00526 history.removeLast();
00527 }
00528
00529 while (history.size() >= MaxHistoryItems) {
00530 history.removeFirst();
00531 }
00532
00533 HistoryItem item;
00534 item.c = c;
00535 item.fromSearch = fromSearch;
00536 item.searchString = searchString;
00537 history.append(item);
00538
00539 inHistory = history.count() - 1;
00540 updateBackForwardButtons();
00541 }
00542
00543 void KCharSelect::KCharSelectPrivate::showFromHistory(int index)
00544 {
00545 Q_ASSERT(index >= 0 && index < history.count());
00546 Q_ASSERT(index != inHistory);
00547
00548 inHistory = index;
00549 updateBackForwardButtons();
00550
00551 const HistoryItem &item = history[index];
00552
00553
00554
00555
00556 bool oldHistoryEnabled = historyEnabled;
00557 historyEnabled = false;
00558 if (item.fromSearch) {
00559 if (searchLine->text() != item.searchString) {
00560 searchLine->setText(item.searchString);
00561 _k_search();
00562 }
00563 charTable->setChar(item.c);
00564 } else {
00565 searchLine->clear();
00566 q->setCurrentChar(item.c);
00567 }
00568 historyEnabled = oldHistoryEnabled;
00569 }
00570
00571 void KCharSelect::KCharSelectPrivate::updateBackForwardButtons()
00572 {
00573 backButton->setEnabled(inHistory > 0);
00574 forwardButton->setEnabled(inHistory < history.count() - 1);
00575 }
00576
00577 void KCharSelect::KCharSelectPrivate::_k_activateSearchLine()
00578 {
00579 searchLine->setFocus();
00580 searchLine->selectAll();
00581 }
00582
00583 void KCharSelect::KCharSelectPrivate::_k_back()
00584 {
00585 Q_ASSERT(inHistory > 0);
00586 showFromHistory(inHistory - 1);
00587 }
00588
00589 void KCharSelect::KCharSelectPrivate::_k_forward()
00590 {
00591 Q_ASSERT(inHistory + 1 < history.count());
00592 showFromHistory(inHistory + 1);
00593 }
00594
00595 void KCharSelect::KCharSelectPrivate::_k_fontSelected()
00596 {
00597 QFont font = fontCombo->currentFont();
00598 font.setPointSize(fontSizeSpinBox->value());
00599 charTable->setFont(font);
00600 emit q->currentFontChanged(font);
00601 }
00602
00603 void KCharSelect::KCharSelectPrivate::_k_updateCurrentChar(const QChar &c)
00604 {
00605 if (searchMode) {
00606
00607
00608 int block = s_data->blockIndex(c);
00609 int section = s_data->sectionIndex(block);
00610 sectionCombo->setCurrentIndex(section);
00611 int index = blockCombo->findData(block);
00612 if (index != -1) {
00613 blockCombo->setCurrentIndex(index);
00614 }
00615 }
00616
00617 if( searchLine)
00618 historyAdd(c, searchMode, searchLine->text());
00619
00620 _k_slotUpdateUnicode(c);
00621 }
00622
00623 void KCharSelect::KCharSelectPrivate::_k_slotUpdateUnicode(const QChar &c)
00624 {
00625 QString html;
00626
00627
00628
00629 if (c.isPrint() && c.unicode() != 0xFDD0 && c.unicode() != 0xFDD1) {
00630
00631
00632 QString combiningSpace;
00633 if(s_data->block(c) == i18nc("KCharselect unicode block name", "Combining Diacritical Marks")) {
00634 combiningSpace = " ";
00635 }
00636 html = QString("<p>" + i18n("Character:") + " <font size=\"+4\" face=\"") + charTable->font().family() + "\">" + combiningSpace + "&#" + QString::number(c.unicode()) + ";" + combiningSpace + "</font> " + s_data->formatCode(c.unicode()) + "<br>";
00637 } else {
00638 html = QString("<p>" + i18n("Character:") + " <b>" + i18n("Non-printable") + "</b> ") + s_data->formatCode(c.unicode()) + "<br>";
00639 }
00640 QString name = s_data->name(c);
00641 if (!name.isEmpty()) {
00642 html += i18n("Name: ") + Qt::escape(name) + "</p>";
00643 }
00644 QStringList aliases = s_data->aliases(c);
00645 QStringList notes = s_data->notes(c);
00646 QList<QChar> seeAlso = s_data->seeAlso(c);
00647 QStringList equivalents = s_data->equivalents(c);
00648 QStringList approxEquivalents = s_data->approximateEquivalents(c);
00649 if (!(aliases.isEmpty() && notes.isEmpty() && seeAlso.isEmpty() && equivalents.isEmpty() && approxEquivalents.isEmpty())) {
00650 html += "<p><b>" + i18n("Annotations and Cross References") + "</b></p>";
00651 }
00652
00653 if (!aliases.isEmpty()) {
00654 html += "<p style=\"margin-bottom: 0px;\">" + i18n("Alias names:") + "</p><ul style=\"margin-top: 0px;\">";
00655 foreach(const QString &alias, aliases) {
00656 html += "<li>" + Qt::escape(alias) + "</li>";
00657 }
00658 html += "</ul>";
00659 }
00660
00661 if (!notes.isEmpty()) {
00662 html += "<p style=\"margin-bottom: 0px;\">" + i18n("Notes:") + "</p><ul style=\"margin-top: 0px;\">";
00663 foreach(const QString ¬e, notes) {
00664 html += "<li>" + createLinks(Qt::escape(note)) + "</li>";
00665 }
00666 html += "</ul>";
00667 }
00668
00669 if (!seeAlso.isEmpty()) {
00670 html += "<p style=\"margin-bottom: 0px;\">" + i18n("See also:") + "</p><ul style=\"margin-top: 0px;\">";
00671 foreach(const QChar &c2, seeAlso) {
00672 html += "<li><a href=\"" + QString::number(c2.unicode(), 16) + "\">";
00673 if (c2.isPrint()) {
00674 html += "&#" + QString::number(c2.unicode()) + "; ";
00675 }
00676 html += s_data->formatCode(c2.unicode()) + ' ' + Qt::escape(s_data->name(c2)) + "</a></li>";
00677 }
00678 html += "</ul>";
00679 }
00680
00681 if (!equivalents.isEmpty()) {
00682 html += "<p style=\"margin-bottom: 0px;\">" + i18n("Equivalents:") + "</p><ul style=\"margin-top: 0px;\">";
00683 foreach(const QString &equivalent, equivalents) {
00684 html += "<li>" + createLinks(Qt::escape(equivalent)) + "</li>";
00685 }
00686 html += "</ul>";
00687 }
00688
00689 if (!approxEquivalents.isEmpty()) {
00690 html += "<p style=\"margin-bottom: 0px;\">" + i18n("Approximate equivalents:") + "</p><ul style=\"margin-top: 0px;\">";
00691 foreach(const QString &approxEquivalent, approxEquivalents) {
00692 html += "<li>" + createLinks(Qt::escape(approxEquivalent)) + "</li>";
00693 }
00694 html += "</ul>";
00695 }
00696
00697 QStringList unihan = s_data->unihanInfo(c);
00698 if (unihan.count() == 7) {
00699 html += "<p><b>" + i18n("CJK Ideograph Information") + "</b></p><p>";
00700 bool newline = true;
00701 if (!unihan[0].isEmpty()) {
00702 html += i18n("Definition in English: ") + unihan[0];
00703 newline = false;
00704 }
00705 if (!unihan[2].isEmpty()) {
00706 if (!newline) html += "<br>";
00707 html += i18n("Mandarin Pronunciation: ") + unihan[2];
00708 newline = false;
00709 }
00710 if (!unihan[1].isEmpty()) {
00711 if (!newline) html += "<br>";
00712 html += i18n("Cantonese Pronunciation: ") + unihan[1];
00713 newline = false;
00714 }
00715 if (!unihan[6].isEmpty()) {
00716 if (!newline) html += "<br>";
00717 html += i18n("Japanese On Pronunciation: ") + unihan[6];
00718 newline = false;
00719 }
00720 if (!unihan[5].isEmpty()) {
00721 if (!newline) html += "<br>";
00722 html += i18n("Japanese Kun Pronunciation: ") + unihan[5];
00723 newline = false;
00724 }
00725 if (!unihan[3].isEmpty()) {
00726 if (!newline) html += "<br>";
00727 html += i18n("Tang Pronunciation: ") + unihan[3];
00728 newline = false;
00729 }
00730 if (!unihan[4].isEmpty()) {
00731 if (!newline) html += "<br>";
00732 html += i18n("Korean Pronunciation: ") + unihan[4];
00733 newline = false;
00734 }
00735 html += "</p>";
00736 }
00737
00738 html += "<p><b>" + i18n("General Character Properties") + "</b><br>";
00739 html += i18n("Block: ") + s_data->block(c) + "<br>";
00740 html += i18n("Unicode category: ") + s_data->categoryText(c.category()) + "</p>";
00741
00742 QByteArray utf8 = QString(c).toUtf8();
00743
00744 html += "<p><b>" + i18n("Various Useful Representations") + "</b><br>";
00745 html += i18n("UTF-8:");
00746 foreach(unsigned char c, utf8)
00747 html += ' ' + s_data->formatCode(c, 2, "0x");
00748 html += "<br>" + i18n("UTF-16: ") + s_data->formatCode(c.unicode(), 4, "0x") + "<br>";
00749 html += i18n("C octal escaped UTF-8: ");
00750 foreach(unsigned char c, utf8)
00751 html += s_data->formatCode(c, 3, "\\", 8);
00752 html += "<br>" + i18n("XML decimal entity:") + " &#" + QString::number(c.unicode()) + ";</p>";
00753
00754 detailBrowser->setHtml(html);
00755 }
00756
00757 QString KCharSelect::KCharSelectPrivate::createLinks(QString s)
00758 {
00759 QRegExp rx("\\b([\\dABCDEF]{4})\\b");
00760
00761 QStringList chars;
00762 int pos = 0;
00763
00764 while ((pos = rx.indexIn(s, pos)) != -1) {
00765 chars << rx.cap(1);
00766 pos += rx.matchedLength();
00767 }
00768
00769 QSet<QString> chars2 = QSet<QString>::fromList(chars);
00770 foreach(const QString &c, chars2) {
00771 int unicode = c.toInt(0, 16);
00772 QString link = "<a href=\"" + c + "\">";
00773 if (QChar(unicode).isPrint()) {
00774 link += "&#" + QString::number(unicode) + "; ";
00775 }
00776 link += "U+" + c + ' ';
00777 link += Qt::escape(s_data->name(QChar(unicode))) + "</a>";
00778 s.replace(c, link);
00779 }
00780 return s;
00781 }
00782
00783 void KCharSelect::KCharSelectPrivate::_k_sectionSelected(int index)
00784 {
00785 blockCombo->clear();
00786 QList<int> blocks = s_data->sectionContents(index);
00787 foreach(int block, blocks) {
00788 blockCombo->addItem(s_data->blockName(block), QVariant(block));
00789 }
00790 blockCombo->setCurrentIndex(0);
00791 }
00792
00793 void KCharSelect::KCharSelectPrivate::_k_blockSelected(int index)
00794 {
00795 if (index == -1) {
00796
00797 return;
00798 }
00799 if (searchMode) {
00800
00801 return;
00802 }
00803
00804 int block = blockCombo->itemData(index).toInt();
00805 const QList<QChar> contents = s_data->blockContents(block);
00806 if(contents.count() <= index) {
00807 return;
00808 }
00809 charTable->setContents(contents);
00810 emit q->displayedCharsChanged();
00811 charTable->setChar(contents[0]);
00812 }
00813
00814 void KCharSelect::KCharSelectPrivate::_k_searchEditChanged()
00815 {
00816 if (searchLine->text().isEmpty()) {
00817 sectionCombo->setEnabled(true);
00818 blockCombo->setEnabled(true);
00819
00820
00821 searchMode = false;
00822 QChar c = charTable->chr();
00823 bool oldHistoryEnabled = historyEnabled;
00824 historyEnabled = false;
00825 _k_blockSelected(blockCombo->currentIndex());
00826 historyEnabled = oldHistoryEnabled;
00827 q->setCurrentChar(c);
00828 } else {
00829 sectionCombo->setEnabled(false);
00830 blockCombo->setEnabled(false);
00831
00832 int length = searchLine->text().length();
00833 if (length >= 3) {
00834 _k_search();
00835 }
00836 }
00837 }
00838
00839 void KCharSelect::KCharSelectPrivate::_k_search()
00840 {
00841 if (searchLine->text().isEmpty()) {
00842 return;
00843 }
00844 searchMode = true;
00845 const QList<QChar> contents = s_data->find(searchLine->text());
00846 charTable->setContents(contents);
00847 emit q->displayedCharsChanged();
00848 if (!contents.isEmpty()) {
00849 charTable->setChar(contents[0]);
00850 }
00851 }
00852
00853 void KCharSelect::KCharSelectPrivate::_k_linkClicked(QUrl url)
00854 {
00855 QString hex = url.toString();
00856 if (hex.size() > 4) {
00857 return;
00858 }
00859 int unicode = hex.toInt(0, 16);
00860 searchLine->clear();
00861 q->setCurrentChar(QChar(unicode));
00862 }
00863
00865
00866 QVariant KCharSelectItemModel::data(const QModelIndex &index, int role) const
00867 {
00868 int pos = m_columns * (index.row()) + index.column();
00869 if (pos >= m_chars.size() || index.row() < 0 || index.column() < 0) {
00870 if (role == Qt::BackgroundColorRole) {
00871 return QVariant(qApp->palette().color(QPalette::Button));
00872 }
00873 return QVariant();
00874 }
00875
00876 QChar c = m_chars[pos];
00877 if (!index.isValid())
00878 return QVariant();
00879 else if (role == Qt::ToolTipRole) {
00880 QString s;
00881 if (c.isPrint()) {
00882 s = "&#" + QString::number(c.unicode()) + ';';
00883
00884
00885 if(s_data->block(c) == i18nc("KCharselect unicode block name", "Combining Diacritical Marks")) {
00886 s = " " + s + " ";
00887 }
00888 } else {
00889 s = i18n("Non-printable");
00890 }
00891 QString result = i18nc("Character", "<qt><font size=\"+4\" face=\"%1\">%2</font><br />%3<br />Unicode code point: %4<br />(In decimal: %5)</qt>" , m_font.family() , s , Qt::escape(s_data->name(c)), s_data->formatCode(c.unicode()) , c.unicode());
00892 return QVariant(result);
00893 } else if (role == Qt::TextAlignmentRole)
00894 return QVariant(Qt::AlignHCenter | Qt::AlignVCenter);
00895 else if (role == Qt::DisplayRole) {
00896 if (c.isPrint())
00897 return QVariant(c);
00898 return QVariant();
00899 } else if (role == Qt::BackgroundColorRole) {
00900 QFontMetrics fm = QFontMetrics(m_font);
00901 if (fm.inFont(c) && c.isPrint())
00902 return QVariant(qApp->palette().color(QPalette::Base));
00903 else
00904 return QVariant(qApp->palette().color(QPalette::Button));
00905 } else if (role == Qt::FontRole)
00906 return QVariant(m_font);
00907 else if (role == CharacterRole) {
00908 return QVariant(c);
00909 }
00910 return QVariant();
00911 }
00912
00913 #include "kcharselect.moc"
00914 #include "kcharselect_p.moc"