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

KDEUI

  • sources
  • kde-4.14
  • kdelibs
  • kdeui
  • widgets
kcharselect.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2 
3  Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "kcharselect.h"
22 
23 #include "kcharselect_p.h"
24 
25 #include <QtGui/QActionEvent>
26 #include <QtGui/QDoubleSpinBox>
27 #include <QtGui/QHeaderView>
28 #include <QtGui/QBoxLayout>
29 #include <QtGui/QShortcut>
30 #include <QtGui/QSplitter>
31 #include <QtGui/QPushButton>
32 #include <QtGui/QToolButton>
33 
34 #include <kcombobox.h>
35 #include <kdebug.h>
36 #include <kdialog.h>
37 #include <klocale.h>
38 #include <klineedit.h>
39 #include <ktextbrowser.h>
40 #include <kfontcombobox.h>
41 #include <kactioncollection.h>
42 #include <kstandardaction.h>
43 
44 K_GLOBAL_STATIC(KCharSelectData, s_data)
45 
46 class KCharSelectTablePrivate
47 {
48 public:
49  KCharSelectTablePrivate(KCharSelectTable *q): q(q), model(0)
50  {}
51 
52  KCharSelectTable *q;
53 
54  QFont font;
55  KCharSelectItemModel *model;
56  QList<QChar> chars;
57  QChar chr;
58 
59  void _k_resizeCells();
60  void _k_doubleClicked(const QModelIndex & index);
61  void _k_slotSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected);
62 };
63 
64 class KCharSelect::KCharSelectPrivate
65 {
66 public:
67  struct HistoryItem
68  {
69  QChar c;
70  bool fromSearch;
71  QString searchString;
72  };
73 
74  enum { MaxHistoryItems = 100 };
75 
76  KCharSelectPrivate(KCharSelect *q)
77  : q(q)
78  ,searchLine(0)
79  ,searchMode(false)
80  ,historyEnabled(false)
81  ,inHistory(0)
82  ,actions(NULL)
83  {
84  }
85 
86  KCharSelect *q;
87 
88  QToolButton *backButton;
89  QToolButton *forwardButton;
90  KLineEdit* searchLine;
91  KFontComboBox *fontCombo;
92  QSpinBox *fontSizeSpinBox;
93  QComboBox *sectionCombo;
94  QComboBox *blockCombo;
95  KCharSelectTable *charTable;
96  KTextBrowser *detailBrowser;
97 
98  bool searchMode; //a search is active
99  bool historyEnabled;
100  int inHistory; //index of current char in history
101  QList<HistoryItem> history;
102  KActionCollection* actions;
103 
104  QString createLinks(QString s);
105  void historyAdd(const QChar &c, bool fromSearch, const QString &searchString);
106  void showFromHistory(int index);
107  void updateBackForwardButtons();
108  void _k_activateSearchLine();
109  void _k_back();
110  void _k_forward();
111  void _k_fontSelected();
112  void _k_updateCurrentChar(const QChar &c);
113  void _k_slotUpdateUnicode(const QChar &c);
114  void _k_sectionSelected(int index);
115  void _k_blockSelected(int index);
116  void _k_searchEditChanged();
117  void _k_search();
118  void _k_linkClicked(QUrl url);
119 };
120 
121 /******************************************************************/
122 /* Class: KCharSelectTable */
123 /******************************************************************/
124 
125 KCharSelectTable::KCharSelectTable(QWidget *parent, const QFont &_font)
126  : QTableView(parent), d(new KCharSelectTablePrivate(this))
127 {
128  d->font = _font;
129 
130  setTabKeyNavigation(false);
131  setSelectionMode(QAbstractItemView::SingleSelection);
132  QPalette _palette;
133  _palette.setColor(backgroundRole(), palette().color(QPalette::Base));
134  setPalette(_palette);
135  verticalHeader()->setVisible(false);
136  verticalHeader()->setResizeMode(QHeaderView::Custom);
137  horizontalHeader()->setVisible(false);
138  horizontalHeader()->setResizeMode(QHeaderView::Custom);
139 
140  setFocusPolicy(Qt::StrongFocus);
141  setDragEnabled(true);
142  setAcceptDrops(true);
143  setDropIndicatorShown(false);
144  setDragDropMode(QAbstractItemView::DragDrop);
145 
146  connect(this, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(_k_doubleClicked(QModelIndex)));
147 
148  d->_k_resizeCells();
149 }
150 
151 KCharSelectTable::~KCharSelectTable()
152 {
153  delete d;
154 }
155 
156 void KCharSelectTable::setFont(const QFont &_font)
157 {
158  QTableView::setFont(_font);
159  d->font = _font;
160  if (d->model) d->model->setFont(_font);
161  d->_k_resizeCells();
162 }
163 
164 QChar KCharSelectTable::chr()
165 {
166  return d->chr;
167 }
168 
169 QFont KCharSelectTable::font() const
170 {
171  return d->font;
172 }
173 
174 QList<QChar> KCharSelectTable::displayedChars() const
175 {
176  return d->chars;
177 }
178 
179 void KCharSelectTable::setChar(const QChar &c)
180 {
181  int pos = d->chars.indexOf(c);
182  if (pos != -1) {
183  const int columnCount = model()->columnCount();
184  setCurrentIndex(model()->index(pos / columnCount, pos % columnCount));
185  }
186 }
187 
188 void KCharSelectTable::setContents(QList<QChar> chars)
189 {
190  d->chars = chars;
191 
192  KCharSelectItemModel *m = d->model;
193  d->model = new KCharSelectItemModel(chars, d->font, this);
194  setModel(d->model);
195  d->_k_resizeCells();
196  QItemSelectionModel *selectionModel = new QItemSelectionModel(d->model);
197  setSelectionModel(selectionModel);
198  setSelectionBehavior(QAbstractItemView::SelectItems);
199  setSelectionMode(QAbstractItemView::SingleSelection);
200  connect(selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(_k_slotSelectionChanged(QItemSelection,QItemSelection)));
201  connect(d->model, SIGNAL(showCharRequested(QChar)), this, SIGNAL(showCharRequested(QChar)));
202  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)
203 }
204 
205 void KCharSelectTable::scrollTo(const QModelIndex & index, ScrollHint hint)
206 {
207  // this prevents horizontal scrolling when selecting a character in the last column
208  if (index.isValid() && index.column() != 0) {
209  QTableView::scrollTo(d->model->index(index.row(), 0), hint);
210  } else {
211  QTableView::scrollTo(index, hint);
212  }
213 }
214 
215 void KCharSelectTablePrivate::_k_slotSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected)
216 {
217  Q_UNUSED(deselected);
218  if (!model || selected.indexes().isEmpty())
219  return;
220  QVariant temp = model->data(selected.indexes().at(0), KCharSelectItemModel::CharacterRole);
221  if (temp.type() != QVariant::Char)
222  return;
223  QChar c = temp.toChar();
224  chr = c;
225  emit q->focusItemChanged(c);
226 }
227 
228 void KCharSelectTable::resizeEvent(QResizeEvent * e)
229 {
230  QTableView::resizeEvent(e);
231  if (e->size().width() != e->oldSize().width()) {
232  d->_k_resizeCells();
233  }
234 }
235 
236 void KCharSelectTablePrivate::_k_resizeCells()
237 {
238  KCharSelectItemModel *model = static_cast<KCharSelectItemModel*>(q->model());
239  if (!model) return;
240 
241  const int viewportWidth = q->viewport()->size().width();
242 
243  QFontMetrics fontMetrics(font);
244 
245  // Determine the max width of the displayed characters
246  // fontMetrics.maxWidth() doesn't help because of font fallbacks
247  // (testcase: Malayalam characters)
248  int maxCharWidth = 0;
249  const QList<QChar> chars = model->chars();
250  for (int i = 0 ; i < chars.size(); ++i) {
251  maxCharWidth = qMax(maxCharWidth, fontMetrics.width(chars.at(i)));
252  }
253  // Avoid too narrow cells
254  maxCharWidth = qMax(maxCharWidth, 2 * fontMetrics.xHeight());
255  maxCharWidth = qMax(maxCharWidth, fontMetrics.height());
256  // Add the necessary padding, trying to match the delegate
257  const int textMargin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, q) + 1;
258  maxCharWidth += 2 * textMargin;
259 
260  const int columns = qMax(1, viewportWidth / maxCharWidth);
261  model->setColumnCount(columns);
262 
263  const QChar oldChar = q->chr();
264 
265  const int new_w = viewportWidth / columns;
266  const int rows = model->rowCount();
267  q->setUpdatesEnabled(false);
268  QHeaderView *hHeader = q->horizontalHeader();
269  const int spaceLeft = viewportWidth - new_w * columns;
270  for (int i = 0 ; i <= columns; i++ ) {
271  if (i < spaceLeft) {
272  hHeader->resizeSection(i, new_w + 1);
273  } else {
274  hHeader->resizeSection(i, new_w);
275  }
276  }
277 
278  QHeaderView *vHeader = q->verticalHeader();
279 #ifdef Q_WS_WIN
280  int new_h = fontMetrics.lineSpacing() + 1;
281 #else
282  int new_h = fontMetrics.xHeight() * 3;
283 #endif
284  const int fontHeight = fontMetrics.height();
285  if (new_h < 5 || new_h < 4 + fontHeight) {
286  new_h = qMax(5, 4 + fontHeight);
287  }
288  for (int i = 0;i < rows;i++) {
289  vHeader->resizeSection(i, new_h);
290  }
291 
292  q->setUpdatesEnabled(true);
293  q->setChar(oldChar);
294 }
295 
296 void KCharSelectTablePrivate::_k_doubleClicked(const QModelIndex & index)
297 {
298  QChar c = model->data(index, KCharSelectItemModel::CharacterRole).toChar();
299  if (s_data->isPrint(c)) {
300  emit q->activated(c);
301  }
302 }
303 
304 void KCharSelectTable::keyPressEvent(QKeyEvent *e)
305 {
306  if (d->model)
307  switch (e->key()) {
308  case Qt::Key_Space:
309  emit activated(' ');
310  return;
311  break;
312  case Qt::Key_Enter: case Qt::Key_Return: {
313  if (!currentIndex().isValid()) return;
314  QChar c = d->model->data(currentIndex(), KCharSelectItemModel::CharacterRole).toChar();
315  if (s_data->isPrint(c)) {
316  emit activated(c);
317  }
318  }
319  return;
320  break;
321  }
322  QTableView::keyPressEvent(e);
323 }
324 
325 
326 /******************************************************************/
327 /* Class: KCharSelect */
328 /******************************************************************/
329 
330 #ifndef KDE_NO_DEPRECATED
331 KCharSelect::KCharSelect(QWidget *parent, const Controls controls)
332  : QWidget(parent), d(new KCharSelectPrivate(this))
333 {
334  init(controls, NULL);
335 }
336 #endif
337 
338 KCharSelect::KCharSelect(
339  QWidget *parent
340  ,KActionCollection *collection
341  ,const Controls controls)
342  : QWidget(parent), d(new KCharSelectPrivate(this))
343 {
344  init(controls, collection);
345 }
346 
347 void KCharSelect::init(const Controls controls, KActionCollection *collection)
348 {
349  if (collection==NULL) {
350  d->actions = new KActionCollection(this);
351  d->actions->addAssociatedWidget(this);
352  } else {
353  d->actions = collection;
354  }
355 
356  QVBoxLayout *mainLayout = new QVBoxLayout(this);
357  mainLayout->setMargin(0);
358  if (SearchLine & controls) {
359  QHBoxLayout *searchLayout = new QHBoxLayout();
360  mainLayout->addLayout(searchLayout);
361  d->searchLine = new KLineEdit(this);
362  searchLayout->addWidget(d->searchLine);
363  d->searchLine->setClickMessage(i18n("Enter a search term or character here"));
364  d->searchLine->setClearButtonShown(true);
365  d->searchLine->setToolTip(i18n("Enter a search term or character here"));
366  KStandardAction::find(this, SLOT(_k_activateSearchLine()), d->actions);
367  connect(d->searchLine, SIGNAL(textChanged(QString)), this, SLOT(_k_searchEditChanged()));
368  connect(d->searchLine, SIGNAL(returnPressed()), this, SLOT(_k_search()));
369  }
370 
371  if ((SearchLine & controls) && ((FontCombo & controls) || (FontSize & controls) || (BlockCombos & controls))) {
372  QFrame* line = new QFrame(this);
373  line->setFrameShape(QFrame::HLine);
374  line->setFrameShadow(QFrame::Sunken);
375  mainLayout->addWidget(line);
376  }
377 
378  QHBoxLayout *comboLayout = new QHBoxLayout();
379 
380  d->backButton = new QToolButton(this);
381  comboLayout->addWidget(d->backButton);
382  d->backButton->setEnabled(false);
383  d->backButton->setText(i18nc("Goes to previous character", "Previous in History"));
384  d->backButton->setIcon(KIcon("go-previous"));
385  d->backButton->setToolTip(i18n("Previous Character in History"));
386 
387  d->forwardButton = new QToolButton(this);
388  comboLayout->addWidget(d->forwardButton);
389  d->forwardButton->setEnabled(false);
390  d->forwardButton->setText(i18nc("Goes to next character", "Next in History"));
391  d->forwardButton->setIcon(KIcon("go-next"));
392  d->forwardButton->setToolTip(i18n("Next Character in History"));
393 
394  KStandardAction::back(d->backButton, SLOT(animateClick()), d->actions);
395  KStandardAction::forward(d->forwardButton, SLOT(animateClick()), d->actions);
396  connect(d->backButton, SIGNAL(clicked()), this, SLOT(_k_back()));
397  connect(d->forwardButton, SIGNAL(clicked()), this, SLOT(_k_forward()));
398 
399  d->sectionCombo = new KComboBox(this);
400  d->sectionCombo->setToolTip(i18n("Select a category"));
401  comboLayout->addWidget(d->sectionCombo);
402  d->blockCombo = new KComboBox(this);
403  d->blockCombo->setToolTip(i18n("Select a block to be displayed"));
404  d->blockCombo->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
405  comboLayout->addWidget(d->blockCombo, 1);
406  d->sectionCombo->addItems(s_data->sectionList());
407  d->blockCombo->setMinimumWidth(QFontMetrics(QWidget::font()).averageCharWidth() * 25);
408 
409  connect(d->sectionCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(_k_sectionSelected(int)));
410  connect(d->blockCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(_k_blockSelected(int)));
411 
412  d->fontCombo = new KFontComboBox(this);
413  comboLayout->addWidget(d->fontCombo);
414  d->fontCombo->setEditable(true);
415  d->fontCombo->resize(d->fontCombo->sizeHint());
416  d->fontCombo->setToolTip(i18n("Set font"));
417 
418  d->fontSizeSpinBox = new QSpinBox(this);
419  comboLayout->addWidget(d->fontSizeSpinBox);
420  d->fontSizeSpinBox->setValue(QWidget::font().pointSize());
421  d->fontSizeSpinBox->setRange(1, 400);
422  d->fontSizeSpinBox->setSingleStep(1);
423  d->fontSizeSpinBox->setToolTip(i18n("Set font size"));
424 
425  connect(d->fontCombo, SIGNAL(currentIndexChanged(QString)), this, SLOT(_k_fontSelected()));
426  connect(d->fontSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(_k_fontSelected()));
427 
428  if ((HistoryButtons & controls) || (FontCombo & controls) || (FontSize & controls) || (BlockCombos & controls)) {
429  mainLayout->addLayout(comboLayout);
430  }
431  if (!(HistoryButtons & controls)) {
432  d->backButton->hide();
433  d->forwardButton->hide();
434  }
435  if (!(FontCombo & controls)) {
436  d->fontCombo->hide();
437  }
438  if (!(FontSize & controls)) {
439  d->fontSizeSpinBox->hide();
440  }
441  if (!(BlockCombos & controls)) {
442  d->sectionCombo->hide();
443  d->blockCombo->hide();
444  }
445 
446  QSplitter *splitter = new QSplitter(this);
447  if ((CharacterTable & controls) || (DetailBrowser & controls)) {
448  mainLayout->addWidget(splitter);
449  } else {
450  splitter->hide();
451  }
452  d->charTable = new KCharSelectTable(this, QFont());
453  if (CharacterTable & controls) {
454  splitter->addWidget(d->charTable);
455  d->charTable->setFocus(Qt::OtherFocusReason);
456  } else {
457  d->charTable->hide();
458  }
459 
460  const QSize sz(200, 200);
461  d->charTable->resize(sz);
462  d->charTable->setMinimumSize(sz);
463 
464  d->charTable->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
465 
466  setCurrentFont(QFont());
467 
468  connect(d->charTable, SIGNAL(focusItemChanged(QChar)), this, SLOT(_k_updateCurrentChar(QChar)));
469  connect(d->charTable, SIGNAL(activated(QChar)), this, SIGNAL(charSelected(QChar)));
470  connect(d->charTable, SIGNAL(focusItemChanged(QChar)),
471  this, SIGNAL(currentCharChanged(QChar)));
472 
473  connect(d->charTable, SIGNAL(showCharRequested(QChar)), this, SLOT(setCurrentChar(QChar)));
474 
475  d->detailBrowser = new KTextBrowser(this);
476  if (DetailBrowser & controls) {
477  splitter->addWidget(d->detailBrowser);
478  } else {
479  d->detailBrowser->hide();
480  }
481  d->detailBrowser->setOpenLinks(false);
482  connect(d->detailBrowser, SIGNAL(anchorClicked(QUrl)), this, SLOT(_k_linkClicked(QUrl)));
483 
484  setFocusPolicy(Qt::StrongFocus);
485  setFocusProxy(d->charTable);
486  d->_k_sectionSelected(0);
487  d->_k_blockSelected(0);
488  setCurrentChar(0x0);
489 
490  d->historyEnabled = true;
491 }
492 
493 KCharSelect::~KCharSelect()
494 {
495  delete d;
496 }
497 
498 QSize KCharSelect::sizeHint() const
499 {
500  return QWidget::sizeHint();
501 }
502 
503 void KCharSelect::setCurrentFont(const QFont &_font)
504 {
505  d->fontCombo->setCurrentFont(_font);
506  d->fontSizeSpinBox->setValue(_font.pointSize());
507  d->_k_fontSelected();
508 }
509 
510 QChar KCharSelect::currentChar() const
511 {
512  return d->charTable->chr();
513 }
514 
515 QFont KCharSelect::currentFont() const
516 {
517  return d->charTable->font();
518 }
519 
520 QList<QChar> KCharSelect::displayedChars() const
521 {
522  return d->charTable->displayedChars();
523 }
524 
525 void KCharSelect::setCurrentChar(const QChar &c)
526 {
527  bool oldHistoryEnabled = d->historyEnabled;
528  d->historyEnabled = false;
529  int block = s_data->blockIndex(c);
530  int section = s_data->sectionIndex(block);
531  d->sectionCombo->setCurrentIndex(section);
532  int index = d->blockCombo->findData(block);
533  if (index != -1) {
534  d->blockCombo->setCurrentIndex(index);
535  }
536  d->historyEnabled = oldHistoryEnabled;
537  d->charTable->setChar(c);
538 }
539 
540 void KCharSelect::KCharSelectPrivate::historyAdd(const QChar &c, bool fromSearch, const QString &searchString)
541 {
542  //kDebug() << "about to add char" << c << "fromSearch" << fromSearch << "searchString" << searchString;
543 
544  if (!historyEnabled) {
545  return;
546  }
547 
548  if (!history.isEmpty() && c == history.last().c) {
549  //avoid duplicates
550  return;
551  }
552 
553  //behave like a web browser, i.e. if user goes back from B to A then clicks C, B is forgotten
554  while (!history.isEmpty() && inHistory != history.count() - 1) {
555  history.removeLast();
556  }
557 
558  while (history.size() >= MaxHistoryItems) {
559  history.removeFirst();
560  }
561 
562  HistoryItem item;
563  item.c = c;
564  item.fromSearch = fromSearch;
565  item.searchString = searchString;
566  history.append(item);
567 
568  inHistory = history.count() - 1;
569  updateBackForwardButtons();
570 }
571 
572 void KCharSelect::KCharSelectPrivate::showFromHistory(int index)
573 {
574  Q_ASSERT(index >= 0 && index < history.count());
575  Q_ASSERT(index != inHistory);
576 
577  inHistory = index;
578  updateBackForwardButtons();
579 
580  const HistoryItem &item = history[index];
581  //kDebug() << "index" << index << "char" << item.c << "fromSearch" << item.fromSearch
582  // << "searchString" << item.searchString;
583 
584  //avoid adding an item from history into history again
585  bool oldHistoryEnabled = historyEnabled;
586  historyEnabled = false;
587  if (item.fromSearch) {
588  if (searchLine->text() != item.searchString) {
589  searchLine->setText(item.searchString);
590  _k_search();
591  }
592  charTable->setChar(item.c);
593  } else {
594  searchLine->clear();
595  q->setCurrentChar(item.c);
596  }
597  historyEnabled = oldHistoryEnabled;
598 }
599 
600 void KCharSelect::KCharSelectPrivate::updateBackForwardButtons()
601 {
602  backButton->setEnabled(inHistory > 0);
603  forwardButton->setEnabled(inHistory < history.count() - 1);
604 }
605 
606 void KCharSelect::KCharSelectPrivate::_k_activateSearchLine()
607 {
608  searchLine->setFocus();
609  searchLine->selectAll();
610 }
611 
612 void KCharSelect::KCharSelectPrivate::_k_back()
613 {
614  Q_ASSERT(inHistory > 0);
615  showFromHistory(inHistory - 1);
616 }
617 
618 void KCharSelect::KCharSelectPrivate::_k_forward()
619 {
620  Q_ASSERT(inHistory + 1 < history.count());
621  showFromHistory(inHistory + 1);
622 }
623 
624 void KCharSelect::KCharSelectPrivate::_k_fontSelected()
625 {
626  QFont font = fontCombo->currentFont();
627  font.setPointSize(fontSizeSpinBox->value());
628  charTable->setFont(font);
629  emit q->currentFontChanged(font);
630 }
631 
632 void KCharSelect::KCharSelectPrivate::_k_updateCurrentChar(const QChar &c)
633 {
634  if (searchMode) {
635  //we are in search mode. make the two comboboxes show the section & block for this character.
636  //(when we are not in search mode the current character always belongs to the current section & block.)
637  int block = s_data->blockIndex(c);
638  int section = s_data->sectionIndex(block);
639  sectionCombo->setCurrentIndex(section);
640  int index = blockCombo->findData(block);
641  if (index != -1) {
642  blockCombo->setCurrentIndex(index);
643  }
644  }
645 
646  if( searchLine)
647  historyAdd(c, searchMode, searchLine->text());
648 
649  _k_slotUpdateUnicode(c);
650 }
651 
652 void KCharSelect::KCharSelectPrivate::_k_slotUpdateUnicode(const QChar &c)
653 {
654  QString html = "<p>" + i18n("Character:") + ' ' + s_data->display(c, charTable->font()) + ' ' +
655  s_data->formatCode(c.unicode()) + "<br />";
656 
657  QString name = s_data->name(c);
658  if (!name.isEmpty()) {
659  //is name ever empty? </p> should always be there...
660  html += i18n("Name: ") + Qt::escape(name) + "</p>";
661  }
662  QStringList aliases = s_data->aliases(c);
663  QStringList notes = s_data->notes(c);
664  QList<QChar> seeAlso = s_data->seeAlso(c);
665  QStringList equivalents = s_data->equivalents(c);
666  QStringList approxEquivalents = s_data->approximateEquivalents(c);
667  if (!(aliases.isEmpty() && notes.isEmpty() && seeAlso.isEmpty() && equivalents.isEmpty() && approxEquivalents.isEmpty())) {
668  html += "<p><b>" + i18n("Annotations and Cross References") + "</b></p>";
669  }
670 
671  if (!aliases.isEmpty()) {
672  html += "<p style=\"margin-bottom: 0px;\">" + i18n("Alias names:") + "</p><ul style=\"margin-top: 0px;\">";
673  foreach(const QString &alias, aliases) {
674  html += "<li>" + Qt::escape(alias) + "</li>";
675  }
676  html += "</ul>";
677  }
678 
679  if (!notes.isEmpty()) {
680  html += "<p style=\"margin-bottom: 0px;\">" + i18n("Notes:") + "</p><ul style=\"margin-top: 0px;\">";
681  foreach(const QString &note, notes) {
682  html += "<li>" + createLinks(Qt::escape(note)) + "</li>";
683  }
684  html += "</ul>";
685  }
686 
687  if (!seeAlso.isEmpty()) {
688  html += "<p style=\"margin-bottom: 0px;\">" + i18n("See also:") + "</p><ul style=\"margin-top: 0px;\">";
689  foreach(const QChar &c2, seeAlso) {
690  html += "<li><a href=\"" + QString::number(c2.unicode(), 16) + "\">";
691  if (s_data->isPrint(c2)) {
692  html += "&#" + QString::number(c2.unicode()) + "; ";
693  }
694  html += s_data->formatCode(c2.unicode()) + ' ' + Qt::escape(s_data->name(c2)) + "</a></li>";
695  }
696  html += "</ul>";
697  }
698 
699  if (!equivalents.isEmpty()) {
700  html += "<p style=\"margin-bottom: 0px;\">" + i18n("Equivalents:") + "</p><ul style=\"margin-top: 0px;\">";
701  foreach(const QString &equivalent, equivalents) {
702  html += "<li>" + createLinks(Qt::escape(equivalent)) + "</li>";
703  }
704  html += "</ul>";
705  }
706 
707  if (!approxEquivalents.isEmpty()) {
708  html += "<p style=\"margin-bottom: 0px;\">" + i18n("Approximate equivalents:") + "</p><ul style=\"margin-top: 0px;\">";
709  foreach(const QString &approxEquivalent, approxEquivalents) {
710  html += "<li>" + createLinks(Qt::escape(approxEquivalent)) + "</li>";
711  }
712  html += "</ul>";
713  }
714 
715  QStringList unihan = s_data->unihanInfo(c);
716  if (unihan.count() == 7) {
717  html += "<p><b>" + i18n("CJK Ideograph Information") + "</b></p><p>";
718  bool newline = true;
719  if (!unihan[0].isEmpty()) {
720  html += i18n("Definition in English: ") + unihan[0];
721  newline = false;
722  }
723  if (!unihan[2].isEmpty()) {
724  if (!newline) html += "<br>";
725  html += i18n("Mandarin Pronunciation: ") + unihan[2];
726  newline = false;
727  }
728  if (!unihan[1].isEmpty()) {
729  if (!newline) html += "<br>";
730  html += i18n("Cantonese Pronunciation: ") + unihan[1];
731  newline = false;
732  }
733  if (!unihan[6].isEmpty()) {
734  if (!newline) html += "<br>";
735  html += i18n("Japanese On Pronunciation: ") + unihan[6];
736  newline = false;
737  }
738  if (!unihan[5].isEmpty()) {
739  if (!newline) html += "<br>";
740  html += i18n("Japanese Kun Pronunciation: ") + unihan[5];
741  newline = false;
742  }
743  if (!unihan[3].isEmpty()) {
744  if (!newline) html += "<br>";
745  html += i18n("Tang Pronunciation: ") + unihan[3];
746  newline = false;
747  }
748  if (!unihan[4].isEmpty()) {
749  if (!newline) html += "<br>";
750  html += i18n("Korean Pronunciation: ") + unihan[4];
751  newline = false;
752  }
753  html += "</p>";
754  }
755 
756  html += "<p><b>" + i18n("General Character Properties") + "</b><br>";
757  html += i18n("Block: ") + s_data->block(c) + "<br>";
758  html += i18n("Unicode category: ") + s_data->categoryText(s_data->category(c)) + "</p>";
759 
760  QByteArray utf8 = QString(c).toUtf8();
761 
762  html += "<p><b>" + i18n("Various Useful Representations") + "</b><br>";
763  html += i18n("UTF-8:");
764  foreach(unsigned char c, utf8)
765  html += ' ' + s_data->formatCode(c, 2, "0x");
766  html += "<br>" + i18n("UTF-16: ") + s_data->formatCode(c.unicode(), 4, "0x") + "<br>";
767  html += i18n("C octal escaped UTF-8: ");
768  foreach(unsigned char c, utf8)
769  html += s_data->formatCode(c, 3, "\\", 8);
770  html += "<br>" + i18n("XML decimal entity:") + " &amp;#" + QString::number(c.unicode()) + ";</p>";
771 
772  detailBrowser->setHtml(html);
773 }
774 
775 QString KCharSelect::KCharSelectPrivate::createLinks(QString s)
776 {
777  QRegExp rx("\\b([\\dABCDEF]{4})\\b");
778 
779  QStringList chars;
780  int pos = 0;
781 
782  while ((pos = rx.indexIn(s, pos)) != -1) {
783  chars << rx.cap(1);
784  pos += rx.matchedLength();
785  }
786 
787  QSet<QString> chars2 = QSet<QString>::fromList(chars);
788  foreach(const QString &c, chars2) {
789  int unicode = c.toInt(0, 16);
790  QString link = "<a href=\"" + c + "\">";
791  if (s_data->isPrint(QChar(unicode))) {
792  link += "&#" + QString::number(unicode) + ";&nbsp;";
793  }
794  link += "U+" + c + ' ';
795  link += Qt::escape(s_data->name(QChar(unicode))) + "</a>";
796  s.replace(c, link);
797  }
798  return s;
799 }
800 
801 void KCharSelect::KCharSelectPrivate::_k_sectionSelected(int index)
802 {
803  blockCombo->clear();
804  QList<int> blocks = s_data->sectionContents(index);
805  foreach(int block, blocks) {
806  blockCombo->addItem(s_data->blockName(block), QVariant(block));
807  }
808  blockCombo->setCurrentIndex(0);
809 }
810 
811 void KCharSelect::KCharSelectPrivate::_k_blockSelected(int index)
812 {
813  if (index == -1) {
814  //the combo box has been cleared and is about to be filled again (because the section has changed)
815  return;
816  }
817  if (searchMode) {
818  //we are in search mode, so don't fill the table with this block.
819  return;
820  }
821 
822  int block = blockCombo->itemData(index).toInt();
823  const QList<QChar> contents = s_data->blockContents(block);
824  if(contents.count() <= index) {
825  return;
826  }
827  charTable->setContents(contents);
828  emit q->displayedCharsChanged();
829  charTable->setChar(contents[0]);
830 }
831 
832 void KCharSelect::KCharSelectPrivate::_k_searchEditChanged()
833 {
834  if (searchLine->text().isEmpty()) {
835  sectionCombo->setEnabled(true);
836  blockCombo->setEnabled(true);
837 
838  //upon leaving search mode, keep the same character selected
839  searchMode = false;
840  QChar c = charTable->chr();
841  bool oldHistoryEnabled = historyEnabled;
842  historyEnabled = false;
843  _k_blockSelected(blockCombo->currentIndex());
844  historyEnabled = oldHistoryEnabled;
845  q->setCurrentChar(c);
846  } else {
847  sectionCombo->setEnabled(false);
848  blockCombo->setEnabled(false);
849 
850  int length = searchLine->text().length();
851  if (length >= 3) {
852  _k_search();
853  }
854  }
855 }
856 
857 void KCharSelect::KCharSelectPrivate::_k_search()
858 {
859  if (searchLine->text().isEmpty()) {
860  return;
861  }
862  searchMode = true;
863  const QList<QChar> contents = s_data->find(searchLine->text());
864  charTable->setContents(contents);
865  emit q->displayedCharsChanged();
866  if (!contents.isEmpty()) {
867  charTable->setChar(contents[0]);
868  }
869 }
870 
871 void KCharSelect::KCharSelectPrivate::_k_linkClicked(QUrl url)
872 {
873  QString hex = url.toString();
874  if (hex.size() > 4) {
875  return;
876  }
877  int unicode = hex.toInt(0, 16);
878  searchLine->clear();
879  q->setCurrentChar(QChar(unicode));
880 }
881 
883 
884 QVariant KCharSelectItemModel::data(const QModelIndex &index, int role) const
885 {
886  int pos = m_columns * (index.row()) + index.column();
887  if (!index.isValid() || pos < 0 || pos >= m_chars.size()
888  || index.row() < 0 || index.column() < 0) {
889  if (role == Qt::BackgroundColorRole) {
890  return QVariant(qApp->palette().color(QPalette::Button));
891  }
892  return QVariant();
893  }
894 
895  QChar c = m_chars[pos];
896  if (role == Qt::ToolTipRole) {
897  QString result = s_data->display(c, m_font) + "<br />" + Qt::escape(s_data->name(c)) + "<br />" +
898  i18n("Unicode code point:") + ' ' + s_data->formatCode(c.unicode()) + "<br />" +
899  i18nc("Character", "In decimal:") + ' ' + QString::number(c.unicode());
900  return QVariant(result);
901  } else if (role == Qt::TextAlignmentRole)
902  return QVariant(Qt::AlignHCenter | Qt::AlignVCenter);
903  else if (role == Qt::DisplayRole) {
904  if (s_data->isPrint(c))
905  return QVariant(c);
906  return QVariant();
907  } else if (role == Qt::BackgroundColorRole) {
908  QFontMetrics fm = QFontMetrics(m_font);
909  if (fm.inFont(c) && s_data->isPrint(c))
910  return QVariant(qApp->palette().color(QPalette::Base));
911  else
912  return QVariant(qApp->palette().color(QPalette::Button));
913  } else if (role == Qt::FontRole)
914  return QVariant(m_font);
915  else if (role == CharacterRole) {
916  return QVariant(c);
917  }
918  return QVariant();
919 }
920 
921 bool KCharSelectItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
922 {
923  Q_UNUSED(row)
924  Q_UNUSED(parent)
925  if (action == Qt::IgnoreAction) {
926  return true;
927  }
928 
929  if (!data->hasText()) {
930  return false;
931  }
932 
933  if (column > 0) {
934  return false;
935  }
936  QString text = data->text();
937  if (text.isEmpty()) {
938  return false;
939  }
940  emit showCharRequested(text[0]);
941  return true;
942 }
943 
944 void KCharSelectItemModel::setColumnCount(int columns)
945 {
946  emit layoutAboutToBeChanged();
947  m_columns = columns;
948  emit layoutChanged();
949 }
950 
951 QList<QChar> KCharSelectItemModel::chars() const
952 {
953  return m_chars;
954 }
955 
956 
957 #include "kcharselect.moc"
958 #include "kcharselect_p.moc"
QItemSelection::indexes
QModelIndexList indexes() const
kdialog.h
i18n
QString i18n(const char *text)
ktextbrowser.h
QModelIndex
kcombobox.h
QResizeEvent
QWidget
KActionCollection
A container for a set of QAction objects.
Definition: kactioncollection.h:56
QFont::setPointSize
void setPointSize(int pointSize)
QString::append
QString & append(QChar ch)
QSize::width
int width() const
kdebug.h
KStandardAction::back
KAction * back(const QObject *recvr, const char *slot, QObject *parent)
Move back (web style menu).
Definition: kstandardaction.cpp:394
QPalette::setColor
void setColor(ColorGroup group, ColorRole role, const QColor &color)
QByteArray
KFontComboBox
A lightweight font selection widget.
Definition: kfontcombobox.h:49
QFrame::setFrameShape
void setFrameShape(Shape)
QWidget::setFocusPolicy
void setFocusPolicy(Qt::FocusPolicy policy)
QChar
kactioncollection.h
QFont
K_GLOBAL_STATIC
#define K_GLOBAL_STATIC(TYPE, NAME)
KCharSelect::FontSize
Shows the font size spin box.
Definition: kcharselect.h:84
QList::at
const T & at(int i) const
QString::size
int size() const
KStandardAction::name
const char * name(StandardAction id)
This will return the internal name of a given standard action.
Definition: kstandardaction.cpp:223
QHBoxLayout
QAbstractItemView::resizeEvent
virtual void resizeEvent(QResizeEvent *event)
KCharSelect::SearchLine
Shows the search widgets.
Definition: kcharselect.h:76
KStandardAction::find
KAction * find(const QObject *recvr, const char *slot, QObject *parent)
Initiate a 'find' request in the current document.
Definition: kstandardaction.cpp:329
QFontMetrics
QMimeData::hasText
bool hasText() const
KCharSelect::DetailBrowser
Shows the detail browser.
Definition: kcharselect.h:96
klocale.h
QUrl::toString
QString toString(QFlags< QUrl::FormattingOption > options) const
QMimeData
i18nc
QString i18nc(const char *ctxt, const char *text)
QList::size
int size() const
QSplitter::addWidget
void addWidget(QWidget *widget)
QList::indexOf
int indexOf(const T &value, int from) const
KCharSelect::BlockCombos
Shows the category/block selection combo boxes.
Definition: kcharselect.h:88
QHeaderView::resizeSection
void resizeSection(int logicalIndex, int size)
QAbstractItemView::scrollTo
virtual void scrollTo(const QModelIndex &index, ScrollHint hint)=0
QString::clear
void clear()
QRegExp
QModelIndex::isValid
bool isValid() const
QBoxLayout::addWidget
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
QString::number
QString number(int n, int base)
QList::count
int count(const T &value) const
KCharSelect::currentChar
QChar currentChar() const
Returns the currently selected character.
kfontcombobox.h
QMimeData::text
QString text() const
KCharSelect::charSelected
void charSelected(const QChar &c)
A character is selected to be inserted somewhere.
KCharSelect::HistoryButtons
Shows the Back/Forward buttons.
Definition: kcharselect.h:100
QResizeEvent::oldSize
const QSize & oldSize() const
QString::toInt
int toInt(bool *ok, int base) const
KCharSelect::CharacterTable
Shows the actual table.
Definition: kcharselect.h:92
QList::isEmpty
bool isEmpty() const
QWidget::setFocusProxy
void setFocusProxy(QWidget *w)
QString::isEmpty
bool isEmpty() const
QModelIndex::row
int row() const
KCharSelect::displayedChars
QList< QChar > displayedChars() const
Returns a list of currently displayed characters.
QFontMetrics::inFont
bool inFont(QChar ch) const
KIcon
A wrapper around QIcon that provides KDE icon features.
Definition: kicon.h:40
QVBoxLayout
KCharSelect::setCurrentChar
void setCurrentChar(const QChar &c)
Highlights the character c.
Definition: kcharselect.cpp:525
QSet< QString >
QString
kstandardaction.h
QList< QChar >
QWidget::hide
void hide()
QChar::unicode
ushort unicode() const
QLayout::setMargin
void setMargin(int margin)
KCharSelect::FontCombo
Shows the font combo box.
Definition: kcharselect.h:80
QStringList
KCharSelect::currentCharChanged
void currentCharChanged(const QChar &c)
The current character is changed.
QSpinBox
QToolButton
QKeyEvent::key
int key() const
QTableView
KCharSelect::setCurrentFont
void setCurrentFont(const QFont &font)
Sets the font which is displayed to font.
Definition: kcharselect.cpp:503
QResizeEvent::size
const QSize & size() const
QSize
QUrl
KStandardAction::forward
KAction * forward(const QObject *recvr, const char *slot, QObject *parent)
Move forward (web style menu).
Definition: kstandardaction.cpp:399
QWidget::setFont
void setFont(const QFont &)
QFrame
QWidget::sizeHint
virtual QSize sizeHint() const
KTextBrowser
Extended QTextBrowser.
Definition: ktextbrowser.h:51
KCharSelect::~KCharSelect
~KCharSelect()
Definition: kcharselect.cpp:493
QFrame::setFrameShadow
void setFrameShadow(Shadow)
KCharSelect
Character selection widget.
Definition: kcharselect.h:61
QItemSelection
QString::replace
QString & replace(int position, int n, QChar after)
QKeyEvent
QSplitter
KLineEdit
An enhanced QLineEdit widget for inputting text.
Definition: klineedit.h:149
Qt::escape
QString escape(const QString &plain)
QString::count
int count() const
KCharSelect::KCharSelect
KCharSelect(QWidget *parent, KActionCollection *collection, const Controls controls=AllGuiElements)
Constructor.
Definition: kcharselect.cpp:331
QSet::fromList
QSet< T > fromList(const QList< T > &list)
KComboBox
An enhanced combo box.
Definition: kcombobox.h:148
QModelIndex::column
int column() const
klineedit.h
QAbstractItemView::keyPressEvent
virtual void keyPressEvent(QKeyEvent *event)
QHeaderView
kcharselect.h
QVariant::type
Type type() const
QItemSelectionModel
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QWidget::actions
QList< QAction * > actions() const
QList::find
iterator find(const T &t)
KCharSelect::currentFont
QFont currentFont() const
Returns the currently displayed font.
QVariant::toChar
QChar toChar() const
QPalette
QFont::pointSize
int pointSize() const
QWidget::height
height
QBoxLayout::addLayout
void addLayout(QLayout *layout, int stretch)
QVariant
KCharSelect::sizeHint
virtual QSize sizeHint() const
Reimplemented.
Definition: kcharselect.cpp:498
QString::toUtf8
QByteArray toUtf8() const
QComboBox
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:23:58 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

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 API Reference

Skip menu "kdelibs API Reference"
  • 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

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal