• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

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 &note, 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:") + " &amp;#" + 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) + ";&nbsp;";
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"

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal