• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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()
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; //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(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; // 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_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 /* Class: KCharSelect                                             */
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     //kDebug() << "about to add char" << c << "fromSearch" << fromSearch << "searchString" << searchString;
00514 
00515     if (!historyEnabled) {
00516         return;
00517     }
00518 
00519     if (!history.isEmpty() && c == history.last().c) {
00520         //avoid duplicates
00521         return;
00522     }
00523 
00524     //behave like a web browser, i.e. if user goes back from B to A then clicks C, B is forgotten
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     //kDebug() << "index" << index << "char" << item.c << "fromSearch" << item.fromSearch
00553     //    << "searchString" << item.searchString;
00554 
00555     //avoid adding an item from history into history again
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         //we are in search mode. make the two comboboxes show the section & block for this character.
00607         //(when we are not in search mode the current character always belongs to the current section & block.)
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     // Qt internally uses U+FDD0 and U+FDD1 to mark the beginning and the end of frames.
00627     // They should be seen as non-printable characters, as trying to display them leads
00628     //  to a crash caused by a Qt "noBlockInString" assertion.
00629     if (c.isPrint() && c.unicode() != 0xFDD0 && c.unicode() != 0xFDD1) {
00630     // Wrap Combining Diacritical Marks in spaces to prevent them from being combined with the text around them
00631     // It still doesn't look perfect, but at least better than without the spaces
00632     QString combiningSpace;
00633     if(s_data->block(c) == i18nc("KCharselect unicode block name", "Combining Diacritical Marks")) {
00634         combiningSpace = "&nbsp;";
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 &note, 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:") + " &amp;#" + 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) + ";&nbsp;";
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         //the combo box has been cleared and is about to be filled again (because the section has changed)
00797         return;
00798     }
00799     if (searchMode) {
00800         //we are in search mode, so don't fill the table with this block.
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         //upon leaving search mode, keep the same character selected
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             // Wrap Combining Diacritical Marks in spaces
00884             // It still doesn't look perfect, but at least better than without the spaces
00885             if(s_data->block(c) == i18nc("KCharselect unicode block name", "Combining Diacritical Marks")) {
00886                 s = "&nbsp;" + s + "&nbsp;";
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"

KDEUI

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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