KDEUI
kcharselect.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 00003 Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 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(0) 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_slotSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected); 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; //a search is active 00099 bool historyEnabled; 00100 int inHistory; //index of current char in history 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 /* Class: KCharSelectTable */ 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(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(_k_slotSelectionChanged(const QItemSelection &, const QItemSelection &))); 00200 connect(d->model, SIGNAL(showCharRequested(QChar)), this, SIGNAL(showCharRequested(QChar))); 00201 delete m; // this should hopefully delete aold selection models too, since it is the parent of them (didn't track, if there are setParent calls somewhere. Check that (jowenn) 00202 } 00203 00204 void KCharSelectTable::scrollTo(const QModelIndex & index, ScrollHint hint) 00205 { 00206 // this prevents horizontal scrolling when selecting a character in the last column 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_slotSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected) 00215 { 00216 Q_UNUSED(deselected); 00217 if (!model || selected.indexes().isEmpty()) 00218 return; 00219 QVariant temp = model->data(selected.indexes().at(0), KCharSelectItemModel::CharacterRole); 00220 if (temp.type() != QVariant::Char) 00221 return; 00222 QChar c = temp.toChar(); 00223 chr = c; 00224 emit q->focusItemChanged(c); 00225 } 00226 00227 void KCharSelectTable::resizeEvent(QResizeEvent * e) 00228 { 00229 QTableView::resizeEvent(e); 00230 if (e->size().width() != e->oldSize().width()) { 00231 d->_k_resizeCells(); 00232 } 00233 } 00234 00235 void KCharSelectTablePrivate::_k_resizeCells() 00236 { 00237 if (!q->model()) return; 00238 static_cast<KCharSelectItemModel*>(q->model())->updateColumnCount(q->viewport()->size().width()); 00239 00240 QChar oldChar = q->chr(); 00241 00242 const int new_w = q->viewport()->size().width() / q->model()->columnCount(QModelIndex()); 00243 const int columns = q->model()->columnCount(QModelIndex()); 00244 const int rows = q->model()->rowCount(QModelIndex()); 00245 q->setUpdatesEnabled(false); 00246 QHeaderView* hv = q->horizontalHeader(); 00247 int spaceLeft = q->viewport()->size().width() % new_w + 1; 00248 for (int i = 0;i <= columns;i++) { 00249 if (i < spaceLeft) { 00250 hv->resizeSection(i, new_w + 1); 00251 } else { 00252 hv->resizeSection(i, new_w); 00253 } 00254 } 00255 00256 hv = q->verticalHeader(); 00257 #ifdef Q_WS_WIN 00258 int new_h = QFontMetrics(font).lineSpacing() + 1; 00259 #else 00260 int new_h = QFontMetrics(font).xHeight() * 3; 00261 #endif 00262 if (new_h < 5 || new_h < 4 + QFontMetrics(font).height()) { 00263 new_h = qMax(5, 4 + QFontMetrics(font).height()); 00264 } 00265 for (int i = 0;i < rows;i++) { 00266 hv->resizeSection(i, new_h); 00267 } 00268 00269 q->setUpdatesEnabled(true); 00270 q->setChar(oldChar); 00271 } 00272 00273 void KCharSelectTablePrivate::_k_doubleClicked(const QModelIndex & index) 00274 { 00275 QChar c = model->data(index, KCharSelectItemModel::CharacterRole).toChar(); 00276 if (s_data->isPrint(c)) { 00277 emit q->activated(c); 00278 } 00279 } 00280 00281 void KCharSelectTable::keyPressEvent(QKeyEvent *e) 00282 { 00283 if (d->model) 00284 switch (e->key()) { 00285 case Qt::Key_Space: 00286 emit activated(' '); 00287 return; 00288 break; 00289 case Qt::Key_Enter: case Qt::Key_Return: { 00290 if (!currentIndex().isValid()) return; 00291 QChar c = d->model->data(currentIndex(), KCharSelectItemModel::CharacterRole).toChar(); 00292 if (s_data->isPrint(c)) { 00293 emit activated(c); 00294 } 00295 } 00296 return; 00297 break; 00298 } 00299 QTableView::keyPressEvent(e); 00300 } 00301 00302 00303 /******************************************************************/ 00304 /* Class: KCharSelect */ 00305 /******************************************************************/ 00306 00307 #ifndef KDE_NO_DEPRECATED 00308 KCharSelect::KCharSelect(QWidget *parent, const Controls controls) 00309 : QWidget(parent), d(new KCharSelectPrivate(this)) 00310 { 00311 init(controls, NULL); 00312 } 00313 #endif 00314 00315 KCharSelect::KCharSelect( 00316 QWidget *parent 00317 ,KActionCollection *collection 00318 ,const Controls controls) 00319 : QWidget(parent), d(new KCharSelectPrivate(this)) 00320 { 00321 init(controls, collection); 00322 } 00323 00324 void KCharSelect::init(const Controls controls, KActionCollection *collection) 00325 { 00326 if (collection==NULL) { 00327 d->actions = new KActionCollection(this); 00328 d->actions->addAssociatedWidget(this); 00329 } else { 00330 d->actions = collection; 00331 } 00332 00333 QVBoxLayout *mainLayout = new QVBoxLayout(this); 00334 mainLayout->setMargin(0); 00335 if (SearchLine & controls) { 00336 QHBoxLayout *searchLayout = new QHBoxLayout(); 00337 mainLayout->addLayout(searchLayout); 00338 d->searchLine = new KLineEdit(this); 00339 searchLayout->addWidget(d->searchLine); 00340 d->searchLine->setClickMessage(i18n("Enter a search term or character here")); 00341 d->searchLine->setClearButtonShown(true); 00342 d->searchLine->setToolTip(i18n("Enter a search term or character here")); 00343 KStandardAction::find(this, SLOT(_k_activateSearchLine()), d->actions); 00344 connect(d->searchLine, SIGNAL(textChanged(QString)), this, SLOT(_k_searchEditChanged())); 00345 connect(d->searchLine, SIGNAL(returnPressed()), this, SLOT(_k_search())); 00346 } 00347 00348 if ((SearchLine & controls) && ((FontCombo & controls) || (FontSize & controls) || (BlockCombos & controls))) { 00349 QFrame* line = new QFrame(this); 00350 line->setFrameShape(QFrame::HLine); 00351 line->setFrameShadow(QFrame::Sunken); 00352 mainLayout->addWidget(line); 00353 } 00354 00355 QHBoxLayout *comboLayout = new QHBoxLayout(); 00356 00357 d->backButton = new QToolButton(this); 00358 comboLayout->addWidget(d->backButton); 00359 d->backButton->setEnabled(false); 00360 d->backButton->setText(i18nc("Goes to previous character", "Previous in History")); 00361 d->backButton->setIcon(KIcon("go-previous")); 00362 d->backButton->setToolTip(i18n("Previous Character in History")); 00363 00364 d->forwardButton = new QToolButton(this); 00365 comboLayout->addWidget(d->forwardButton); 00366 d->forwardButton->setEnabled(false); 00367 d->forwardButton->setText(i18nc("Goes to next character", "Next in History")); 00368 d->forwardButton->setIcon(KIcon("go-next")); 00369 d->forwardButton->setToolTip(i18n("Next Character in History")); 00370 00371 KStandardAction::back(d->backButton, SLOT(animateClick()), d->actions); 00372 KStandardAction::forward(d->forwardButton, SLOT(animateClick()), d->actions); 00373 connect(d->backButton, SIGNAL(clicked()), this, SLOT(_k_back())); 00374 connect(d->forwardButton, SIGNAL(clicked()), this, SLOT(_k_forward())); 00375 00376 d->sectionCombo = new KComboBox(this); 00377 d->sectionCombo->setToolTip(i18n("Select a category")); 00378 comboLayout->addWidget(d->sectionCombo); 00379 d->blockCombo = new KComboBox(this); 00380 d->blockCombo->setToolTip(i18n("Select a block to be displayed")); 00381 d->blockCombo->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); 00382 comboLayout->addWidget(d->blockCombo, 1); 00383 d->sectionCombo->addItems(s_data->sectionList()); 00384 d->blockCombo->setMinimumWidth(QFontMetrics(QWidget::font()).averageCharWidth() * 25); 00385 00386 connect(d->sectionCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(_k_sectionSelected(int))); 00387 connect(d->blockCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(_k_blockSelected(int))); 00388 00389 d->fontCombo = new KFontComboBox(this); 00390 comboLayout->addWidget(d->fontCombo); 00391 d->fontCombo->setEditable(true); 00392 d->fontCombo->resize(d->fontCombo->sizeHint()); 00393 d->fontCombo->setToolTip(i18n("Set font")); 00394 00395 d->fontSizeSpinBox = new QSpinBox(this); 00396 comboLayout->addWidget(d->fontSizeSpinBox); 00397 d->fontSizeSpinBox->setValue(QWidget::font().pointSize()); 00398 d->fontSizeSpinBox->setRange(1, 400); 00399 d->fontSizeSpinBox->setSingleStep(1); 00400 d->fontSizeSpinBox->setToolTip(i18n("Set font size")); 00401 00402 connect(d->fontCombo, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(_k_fontSelected())); 00403 connect(d->fontSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(_k_fontSelected())); 00404 00405 if ((HistoryButtons & controls) || (FontCombo & controls) || (FontSize & controls) || (BlockCombos & controls)) { 00406 mainLayout->addLayout(comboLayout); 00407 } 00408 if (!(HistoryButtons & controls)) { 00409 d->backButton->hide(); 00410 d->forwardButton->hide(); 00411 } 00412 if (!(FontCombo & controls)) { 00413 d->fontCombo->hide(); 00414 } 00415 if (!(FontSize & controls)) { 00416 d->fontSizeSpinBox->hide(); 00417 } 00418 if (!(BlockCombos & controls)) { 00419 d->sectionCombo->hide(); 00420 d->blockCombo->hide(); 00421 } 00422 00423 QSplitter *splitter = new QSplitter(this); 00424 if ((CharacterTable & controls) || (DetailBrowser & controls)) { 00425 mainLayout->addWidget(splitter); 00426 } else { 00427 splitter->hide(); 00428 } 00429 d->charTable = new KCharSelectTable(this, QFont()); 00430 if (CharacterTable & controls) { 00431 splitter->addWidget(d->charTable); 00432 d->charTable->setFocus(Qt::OtherFocusReason); 00433 } else { 00434 d->charTable->hide(); 00435 } 00436 00437 const QSize sz(200, 200); 00438 d->charTable->resize(sz); 00439 d->charTable->setMinimumSize(sz); 00440 00441 d->charTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 00442 00443 setCurrentFont(QFont()); 00444 00445 connect(d->charTable, SIGNAL(focusItemChanged(const QChar &)), this, SLOT(_k_updateCurrentChar(const QChar &))); 00446 connect(d->charTable, SIGNAL(activated(const QChar &)), this, SIGNAL(charSelected(const QChar &))); 00447 connect(d->charTable, SIGNAL(focusItemChanged(const QChar &)), 00448 this, SIGNAL(currentCharChanged(const QChar &))); 00449 00450 connect(d->charTable, SIGNAL(showCharRequested(QChar)), this, SLOT(setCurrentChar(QChar))); 00451 00452 d->detailBrowser = new KTextBrowser(this); 00453 if (DetailBrowser & controls) { 00454 splitter->addWidget(d->detailBrowser); 00455 } else { 00456 d->detailBrowser->hide(); 00457 } 00458 d->detailBrowser->setOpenLinks(false); 00459 connect(d->detailBrowser, SIGNAL(anchorClicked(QUrl)), this, SLOT(_k_linkClicked(QUrl))); 00460 00461 setFocusPolicy(Qt::StrongFocus); 00462 setFocusProxy(d->charTable); 00463 d->_k_sectionSelected(0); 00464 d->_k_blockSelected(0); 00465 setCurrentChar(0x0); 00466 00467 d->historyEnabled = true; 00468 } 00469 00470 KCharSelect::~KCharSelect() 00471 { 00472 delete d; 00473 } 00474 00475 QSize KCharSelect::sizeHint() const 00476 { 00477 return QWidget::sizeHint(); 00478 } 00479 00480 void KCharSelect::setCurrentFont(const QFont &_font) 00481 { 00482 d->fontCombo->setCurrentFont(_font); 00483 d->fontSizeSpinBox->setValue(_font.pointSize()); 00484 d->_k_fontSelected(); 00485 } 00486 00487 QChar KCharSelect::currentChar() const 00488 { 00489 return d->charTable->chr(); 00490 } 00491 00492 QFont KCharSelect::currentFont() const 00493 { 00494 return d->charTable->font(); 00495 } 00496 00497 QList<QChar> KCharSelect::displayedChars() const 00498 { 00499 return d->charTable->displayedChars(); 00500 } 00501 00502 void KCharSelect::setCurrentChar(const QChar &c) 00503 { 00504 bool oldHistoryEnabled = d->historyEnabled; 00505 d->historyEnabled = false; 00506 int block = s_data->blockIndex(c); 00507 int section = s_data->sectionIndex(block); 00508 d->sectionCombo->setCurrentIndex(section); 00509 int index = d->blockCombo->findData(block); 00510 if (index != -1) { 00511 d->blockCombo->setCurrentIndex(index); 00512 } 00513 d->historyEnabled = oldHistoryEnabled; 00514 d->charTable->setChar(c); 00515 } 00516 00517 void KCharSelect::KCharSelectPrivate::historyAdd(const QChar &c, bool fromSearch, const QString &searchString) 00518 { 00519 //kDebug() << "about to add char" << c << "fromSearch" << fromSearch << "searchString" << searchString; 00520 00521 if (!historyEnabled) { 00522 return; 00523 } 00524 00525 if (!history.isEmpty() && c == history.last().c) { 00526 //avoid duplicates 00527 return; 00528 } 00529 00530 //behave like a web browser, i.e. if user goes back from B to A then clicks C, B is forgotten 00531 while (!history.isEmpty() && inHistory != history.count() - 1) { 00532 history.removeLast(); 00533 } 00534 00535 while (history.size() >= MaxHistoryItems) { 00536 history.removeFirst(); 00537 } 00538 00539 HistoryItem item; 00540 item.c = c; 00541 item.fromSearch = fromSearch; 00542 item.searchString = searchString; 00543 history.append(item); 00544 00545 inHistory = history.count() - 1; 00546 updateBackForwardButtons(); 00547 } 00548 00549 void KCharSelect::KCharSelectPrivate::showFromHistory(int index) 00550 { 00551 Q_ASSERT(index >= 0 && index < history.count()); 00552 Q_ASSERT(index != inHistory); 00553 00554 inHistory = index; 00555 updateBackForwardButtons(); 00556 00557 const HistoryItem &item = history[index]; 00558 //kDebug() << "index" << index << "char" << item.c << "fromSearch" << item.fromSearch 00559 // << "searchString" << item.searchString; 00560 00561 //avoid adding an item from history into history again 00562 bool oldHistoryEnabled = historyEnabled; 00563 historyEnabled = false; 00564 if (item.fromSearch) { 00565 if (searchLine->text() != item.searchString) { 00566 searchLine->setText(item.searchString); 00567 _k_search(); 00568 } 00569 charTable->setChar(item.c); 00570 } else { 00571 searchLine->clear(); 00572 q->setCurrentChar(item.c); 00573 } 00574 historyEnabled = oldHistoryEnabled; 00575 } 00576 00577 void KCharSelect::KCharSelectPrivate::updateBackForwardButtons() 00578 { 00579 backButton->setEnabled(inHistory > 0); 00580 forwardButton->setEnabled(inHistory < history.count() - 1); 00581 } 00582 00583 void KCharSelect::KCharSelectPrivate::_k_activateSearchLine() 00584 { 00585 searchLine->setFocus(); 00586 searchLine->selectAll(); 00587 } 00588 00589 void KCharSelect::KCharSelectPrivate::_k_back() 00590 { 00591 Q_ASSERT(inHistory > 0); 00592 showFromHistory(inHistory - 1); 00593 } 00594 00595 void KCharSelect::KCharSelectPrivate::_k_forward() 00596 { 00597 Q_ASSERT(inHistory + 1 < history.count()); 00598 showFromHistory(inHistory + 1); 00599 } 00600 00601 void KCharSelect::KCharSelectPrivate::_k_fontSelected() 00602 { 00603 QFont font = fontCombo->currentFont(); 00604 font.setPointSize(fontSizeSpinBox->value()); 00605 charTable->setFont(font); 00606 emit q->currentFontChanged(font); 00607 } 00608 00609 void KCharSelect::KCharSelectPrivate::_k_updateCurrentChar(const QChar &c) 00610 { 00611 if (searchMode) { 00612 //we are in search mode. make the two comboboxes show the section & block for this character. 00613 //(when we are not in search mode the current character always belongs to the current section & block.) 00614 int block = s_data->blockIndex(c); 00615 int section = s_data->sectionIndex(block); 00616 sectionCombo->setCurrentIndex(section); 00617 int index = blockCombo->findData(block); 00618 if (index != -1) { 00619 blockCombo->setCurrentIndex(index); 00620 } 00621 } 00622 00623 if( searchLine) 00624 historyAdd(c, searchMode, searchLine->text()); 00625 00626 _k_slotUpdateUnicode(c); 00627 } 00628 00629 void KCharSelect::KCharSelectPrivate::_k_slotUpdateUnicode(const QChar &c) 00630 { 00631 QString html = "<p>" + i18n("Character:") + ' ' + s_data->display(c, charTable->font()) + ' ' + 00632 s_data->formatCode(c.unicode()) + "<br />"; 00633 00634 QString name = s_data->name(c); 00635 if (!name.isEmpty()) { 00636 //is name ever empty? </p> should always be there... 00637 html += i18n("Name: ") + Qt::escape(name) + "</p>"; 00638 } 00639 QStringList aliases = s_data->aliases(c); 00640 QStringList notes = s_data->notes(c); 00641 QList<QChar> seeAlso = s_data->seeAlso(c); 00642 QStringList equivalents = s_data->equivalents(c); 00643 QStringList approxEquivalents = s_data->approximateEquivalents(c); 00644 if (!(aliases.isEmpty() && notes.isEmpty() && seeAlso.isEmpty() && equivalents.isEmpty() && approxEquivalents.isEmpty())) { 00645 html += "<p><b>" + i18n("Annotations and Cross References") + "</b></p>"; 00646 } 00647 00648 if (!aliases.isEmpty()) { 00649 html += "<p style=\"margin-bottom: 0px;\">" + i18n("Alias names:") + "</p><ul style=\"margin-top: 0px;\">"; 00650 foreach(const QString &alias, aliases) { 00651 html += "<li>" + Qt::escape(alias) + "</li>"; 00652 } 00653 html += "</ul>"; 00654 } 00655 00656 if (!notes.isEmpty()) { 00657 html += "<p style=\"margin-bottom: 0px;\">" + i18n("Notes:") + "</p><ul style=\"margin-top: 0px;\">"; 00658 foreach(const QString ¬e, notes) { 00659 html += "<li>" + createLinks(Qt::escape(note)) + "</li>"; 00660 } 00661 html += "</ul>"; 00662 } 00663 00664 if (!seeAlso.isEmpty()) { 00665 html += "<p style=\"margin-bottom: 0px;\">" + i18n("See also:") + "</p><ul style=\"margin-top: 0px;\">"; 00666 foreach(const QChar &c2, seeAlso) { 00667 html += "<li><a href=\"" + QString::number(c2.unicode(), 16) + "\">"; 00668 if (s_data->isPrint(c2)) { 00669 html += "&#" + QString::number(c2.unicode()) + "; "; 00670 } 00671 html += s_data->formatCode(c2.unicode()) + ' ' + Qt::escape(s_data->name(c2)) + "</a></li>"; 00672 } 00673 html += "</ul>"; 00674 } 00675 00676 if (!equivalents.isEmpty()) { 00677 html += "<p style=\"margin-bottom: 0px;\">" + i18n("Equivalents:") + "</p><ul style=\"margin-top: 0px;\">"; 00678 foreach(const QString &equivalent, equivalents) { 00679 html += "<li>" + createLinks(Qt::escape(equivalent)) + "</li>"; 00680 } 00681 html += "</ul>"; 00682 } 00683 00684 if (!approxEquivalents.isEmpty()) { 00685 html += "<p style=\"margin-bottom: 0px;\">" + i18n("Approximate equivalents:") + "</p><ul style=\"margin-top: 0px;\">"; 00686 foreach(const QString &approxEquivalent, approxEquivalents) { 00687 html += "<li>" + createLinks(Qt::escape(approxEquivalent)) + "</li>"; 00688 } 00689 html += "</ul>"; 00690 } 00691 00692 QStringList unihan = s_data->unihanInfo(c); 00693 if (unihan.count() == 7) { 00694 html += "<p><b>" + i18n("CJK Ideograph Information") + "</b></p><p>"; 00695 bool newline = true; 00696 if (!unihan[0].isEmpty()) { 00697 html += i18n("Definition in English: ") + unihan[0]; 00698 newline = false; 00699 } 00700 if (!unihan[2].isEmpty()) { 00701 if (!newline) html += "<br>"; 00702 html += i18n("Mandarin Pronunciation: ") + unihan[2]; 00703 newline = false; 00704 } 00705 if (!unihan[1].isEmpty()) { 00706 if (!newline) html += "<br>"; 00707 html += i18n("Cantonese Pronunciation: ") + unihan[1]; 00708 newline = false; 00709 } 00710 if (!unihan[6].isEmpty()) { 00711 if (!newline) html += "<br>"; 00712 html += i18n("Japanese On Pronunciation: ") + unihan[6]; 00713 newline = false; 00714 } 00715 if (!unihan[5].isEmpty()) { 00716 if (!newline) html += "<br>"; 00717 html += i18n("Japanese Kun Pronunciation: ") + unihan[5]; 00718 newline = false; 00719 } 00720 if (!unihan[3].isEmpty()) { 00721 if (!newline) html += "<br>"; 00722 html += i18n("Tang Pronunciation: ") + unihan[3]; 00723 newline = false; 00724 } 00725 if (!unihan[4].isEmpty()) { 00726 if (!newline) html += "<br>"; 00727 html += i18n("Korean Pronunciation: ") + unihan[4]; 00728 newline = false; 00729 } 00730 html += "</p>"; 00731 } 00732 00733 html += "<p><b>" + i18n("General Character Properties") + "</b><br>"; 00734 html += i18n("Block: ") + s_data->block(c) + "<br>"; 00735 html += i18n("Unicode category: ") + s_data->categoryText(s_data->category(c)) + "</p>"; 00736 00737 QByteArray utf8 = QString(c).toUtf8(); 00738 00739 html += "<p><b>" + i18n("Various Useful Representations") + "</b><br>"; 00740 html += i18n("UTF-8:"); 00741 foreach(unsigned char c, utf8) 00742 html += ' ' + s_data->formatCode(c, 2, "0x"); 00743 html += "<br>" + i18n("UTF-16: ") + s_data->formatCode(c.unicode(), 4, "0x") + "<br>"; 00744 html += i18n("C octal escaped UTF-8: "); 00745 foreach(unsigned char c, utf8) 00746 html += s_data->formatCode(c, 3, "\\", 8); 00747 html += "<br>" + i18n("XML decimal entity:") + " &#" + QString::number(c.unicode()) + ";</p>"; 00748 00749 detailBrowser->setHtml(html); 00750 } 00751 00752 QString KCharSelect::KCharSelectPrivate::createLinks(QString s) 00753 { 00754 QRegExp rx("\\b([\\dABCDEF]{4})\\b"); 00755 00756 QStringList chars; 00757 int pos = 0; 00758 00759 while ((pos = rx.indexIn(s, pos)) != -1) { 00760 chars << rx.cap(1); 00761 pos += rx.matchedLength(); 00762 } 00763 00764 QSet<QString> chars2 = QSet<QString>::fromList(chars); 00765 foreach(const QString &c, chars2) { 00766 int unicode = c.toInt(0, 16); 00767 QString link = "<a href=\"" + c + "\">"; 00768 if (s_data->isPrint(QChar(unicode))) { 00769 link += "&#" + QString::number(unicode) + "; "; 00770 } 00771 link += "U+" + c + ' '; 00772 link += Qt::escape(s_data->name(QChar(unicode))) + "</a>"; 00773 s.replace(c, link); 00774 } 00775 return s; 00776 } 00777 00778 void KCharSelect::KCharSelectPrivate::_k_sectionSelected(int index) 00779 { 00780 blockCombo->clear(); 00781 QList<int> blocks = s_data->sectionContents(index); 00782 foreach(int block, blocks) { 00783 blockCombo->addItem(s_data->blockName(block), QVariant(block)); 00784 } 00785 blockCombo->setCurrentIndex(0); 00786 } 00787 00788 void KCharSelect::KCharSelectPrivate::_k_blockSelected(int index) 00789 { 00790 if (index == -1) { 00791 //the combo box has been cleared and is about to be filled again (because the section has changed) 00792 return; 00793 } 00794 if (searchMode) { 00795 //we are in search mode, so don't fill the table with this block. 00796 return; 00797 } 00798 00799 int block = blockCombo->itemData(index).toInt(); 00800 const QList<QChar> contents = s_data->blockContents(block); 00801 if(contents.count() <= index) { 00802 return; 00803 } 00804 charTable->setContents(contents); 00805 emit q->displayedCharsChanged(); 00806 charTable->setChar(contents[0]); 00807 } 00808 00809 void KCharSelect::KCharSelectPrivate::_k_searchEditChanged() 00810 { 00811 if (searchLine->text().isEmpty()) { 00812 sectionCombo->setEnabled(true); 00813 blockCombo->setEnabled(true); 00814 00815 //upon leaving search mode, keep the same character selected 00816 searchMode = false; 00817 QChar c = charTable->chr(); 00818 bool oldHistoryEnabled = historyEnabled; 00819 historyEnabled = false; 00820 _k_blockSelected(blockCombo->currentIndex()); 00821 historyEnabled = oldHistoryEnabled; 00822 q->setCurrentChar(c); 00823 } else { 00824 sectionCombo->setEnabled(false); 00825 blockCombo->setEnabled(false); 00826 00827 int length = searchLine->text().length(); 00828 if (length >= 3) { 00829 _k_search(); 00830 } 00831 } 00832 } 00833 00834 void KCharSelect::KCharSelectPrivate::_k_search() 00835 { 00836 if (searchLine->text().isEmpty()) { 00837 return; 00838 } 00839 searchMode = true; 00840 const QList<QChar> contents = s_data->find(searchLine->text()); 00841 charTable->setContents(contents); 00842 emit q->displayedCharsChanged(); 00843 if (!contents.isEmpty()) { 00844 charTable->setChar(contents[0]); 00845 } 00846 } 00847 00848 void KCharSelect::KCharSelectPrivate::_k_linkClicked(QUrl url) 00849 { 00850 QString hex = url.toString(); 00851 if (hex.size() > 4) { 00852 return; 00853 } 00854 int unicode = hex.toInt(0, 16); 00855 searchLine->clear(); 00856 q->setCurrentChar(QChar(unicode)); 00857 } 00858 00860 00861 QVariant KCharSelectItemModel::data(const QModelIndex &index, int role) const 00862 { 00863 int pos = m_columns * (index.row()) + index.column(); 00864 if (!index.isValid() || pos < 0 || pos >= m_chars.size() 00865 || index.row() < 0 || index.column() < 0) { 00866 if (role == Qt::BackgroundColorRole) { 00867 return QVariant(qApp->palette().color(QPalette::Button)); 00868 } 00869 return QVariant(); 00870 } 00871 00872 QChar c = m_chars[pos]; 00873 if (role == Qt::ToolTipRole) { 00874 QString result = s_data->display(c, m_font) + "<br />" + Qt::escape(s_data->name(c)) + "<br />" + 00875 i18n("Unicode code point:") + ' ' + s_data->formatCode(c.unicode()) + "<br />" + 00876 i18nc("Character", "In decimal:") + ' ' + QString::number(c.unicode()); 00877 return QVariant(result); 00878 } else if (role == Qt::TextAlignmentRole) 00879 return QVariant(Qt::AlignHCenter | Qt::AlignVCenter); 00880 else if (role == Qt::DisplayRole) { 00881 if (s_data->isPrint(c)) 00882 return QVariant(c); 00883 return QVariant(); 00884 } else if (role == Qt::BackgroundColorRole) { 00885 QFontMetrics fm = QFontMetrics(m_font); 00886 if (fm.inFont(c) && s_data->isPrint(c)) 00887 return QVariant(qApp->palette().color(QPalette::Base)); 00888 else 00889 return QVariant(qApp->palette().color(QPalette::Button)); 00890 } else if (role == Qt::FontRole) 00891 return QVariant(m_font); 00892 else if (role == CharacterRole) { 00893 return QVariant(c); 00894 } 00895 return QVariant(); 00896 } 00897 00898 #include "kcharselect.moc" 00899 #include "kcharselect_p.moc"
KDE 4.7 API Reference