QGIS API Documentation  3.23.0-Master (dd0cd13a00)
characterwidget.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation ([email protected])
6 **
7 ** This library/program is free software; you can redistribute it
8 ** and/or modify it under the terms of the GNU Library General Public
9 ** License as published by the Free Software Foundation; either
10 ** version 2 of the License, or ( at your option ) any later version.
11 **
12 ** This file is part of the examples of the Qt Toolkit.
13 **
14 ** $QT_BEGIN_LICENSE:LGPL$
15 ** Commercial Usage
16 ** Licensees holding valid Qt Commercial licenses may use this file in
17 ** accordance with the Qt Commercial License Agreement provided with the
18 ** Software or, alternatively, in accordance with the terms contained in
19 ** a written agreement between you and Nokia.
20 **
21 ** GNU Lesser General Public License Usage
22 ** Alternatively, this file may be used under the terms of the
23 ** GNU Lesser General Public License version 2.1 as published by the Free Software
24 ** Foundation and appearing in the file LICENSE.LGPL included in the
25 ** packaging of this file. Please review the following information to
26 ** ensure the GNU Lesser General Public License version 2.1 requirements
27 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
28 ** In addition, as a special exception, Nokia gives you certain additional
29 ** rights. These rights are described in the Nokia Qt LGPL Exception
30 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
31 **
32 ** GNU General Public License Usage
33 ** Alternatively, this file may be used under the terms of the GNU
34 ** General Public License version 3.0 as published by the Free Software
35 ** Foundation and appearing in the file LICENSE.GPL included in the
36 ** packaging of this file. Please review the following information to
37 ** ensure the GNU General Public License version 3.0 requirements will be
38 ** met: http://www.gnu.org/copyleft/gpl.html.
39 **
40 ** If you have questions regarding the use of this file, please contact
41 ** Nokia at [email protected]
42 ** $QT_END_LICENSE$
43 **
44 ****************************************************************************/
45 
46 #include "characterwidget.h"
47 #include "qgsapplication.h"
48 
49 #include <QFontDatabase>
50 #include <QMouseEvent>
51 #include <QPaintEvent>
52 #include <QPainter>
53 #include <QPen>
54 #include <QPoint>
55 #include <QScrollArea>
56 #include <QScrollBar>
57 #include <QToolTip>
58 
60  : QWidget( parent )
61 {
62  setMouseTracking( true );
63  setFocusPolicy( Qt::StrongFocus );
64 }
65 
66 void CharacterWidget::setFont( const QFont &font )
67 {
68  mDisplayFont.setFamily( font.family() );
69  mSquareSize = std::max( 34, QFontMetrics( mDisplayFont ).xHeight() * 3 );
70  adjustSize();
71  update();
72 }
73 
74 void CharacterWidget::setFontSize( double fontSize )
75 {
76  mDisplayFont.setPointSizeF( fontSize );
77  mSquareSize = std::max( 34, QFontMetrics( mDisplayFont ).xHeight() * 3 );
78  adjustSize();
79  update();
80 }
81 
82 void CharacterWidget::setFontStyle( const QString &fontStyle )
83 {
84  const QFontDatabase fontDatabase;
85  const QFont::StyleStrategy oldStrategy = mDisplayFont.styleStrategy();
86  mDisplayFont = fontDatabase.font( mDisplayFont.family(), fontStyle, mDisplayFont.pointSize() );
87  mDisplayFont.setStyleStrategy( oldStrategy );
88  mSquareSize = std::max( 34, QFontMetrics( mDisplayFont ).xHeight() * 3 );
89  adjustSize();
90  update();
91 }
92 
94 {
95  if ( enable )
96  mDisplayFont.setStyleStrategy( QFont::PreferDefault );
97  else
98  mDisplayFont.setStyleStrategy( QFont::NoFontMerging );
99  adjustSize();
100  update();
101 }
102 
103 void CharacterWidget::setColumns( int columns )
104 {
105  if ( mColumns == columns || columns < 1 )
106  return;
107  mColumns = columns;
108  adjustSize();
109  update();
110 }
111 
112 void CharacterWidget::setCharacter( QChar character )
113 {
114  const bool changed = character.unicode() != mLastKey;
115  mLastKey = character.isNull() ? -1 : character.unicode();
116  QWidget *widget = parentWidget();
117  if ( widget )
118  {
119  QScrollArea *scrollArea = qobject_cast< QScrollArea *>( widget->parent() );
120  if ( scrollArea && mLastKey < 65536 )
121  {
122  scrollArea->ensureVisible( 0, mLastKey / mColumns * mSquareSize );
123  }
124  }
125  if ( changed )
126  emit characterSelected( mLastKey >= 0 ? QChar( mLastKey ) : QChar() );
127 
128  update();
129 }
130 
132 {
133  mLastKey = -1;
134  update();
135 }
136 
138 {
139  return QSize( mColumns * mSquareSize, ( 65536 / mColumns ) * mSquareSize );
140 }
141 
142 void CharacterWidget::keyPressEvent( QKeyEvent *event )
143 {
144  const QFontMetrics fm( mDisplayFont );
145 
146  if ( event->key() == Qt::Key_Right )
147  {
148  int next = std::min( mLastKey + 1, 0xfffc );
149  while ( next < 0xfffc && !fm.inFont( QChar( next ) ) )
150  {
151  next++;
152  }
153  setCharacter( QChar( next ) );
154  }
155  else if ( event->key() == Qt::Key_Left )
156  {
157  int next = mLastKey - 1;
158  while ( next > 0 && !fm.inFont( QChar( next ) ) )
159  {
160  next--;
161  }
162  setCharacter( QChar( next ) );
163  }
164  else if ( event->key() == Qt::Key_Down )
165  {
166  int next = std::min( mLastKey + mColumns, 0xfffc );
167  while ( next < 0xfffc && !fm.inFont( QChar( next ) ) )
168  {
169  next = std::min( next + mColumns, 0xfffc );
170  }
171  setCharacter( QChar( next ) );
172  }
173  else if ( event->key() == Qt::Key_Up )
174  {
175  int next = std::max( 0, mLastKey - mColumns );
176  while ( next > 0 && !fm.inFont( QChar( next ) ) )
177  {
178  next = std::max( 0, next - mColumns );
179  }
180  setCharacter( QChar( next ) );
181  }
182  else if ( event->key() == Qt::Key_Home )
183  {
184  int next = 0;
185  while ( next < 0xfffc && !fm.inFont( QChar( next ) ) )
186  {
187  next++;
188  }
189  setCharacter( QChar( next ) );
190  }
191  else if ( event->key() == Qt::Key_End )
192  {
193  int next = 0xfffc;
194  while ( next > 0 && !fm.inFont( QChar( next ) ) )
195  {
196  next--;
197  }
198  setCharacter( QChar( next ) );
199  }
200  else if ( !event->text().isEmpty() )
201  {
202  QChar chr = event->text().at( 0 );
203  if ( chr.unicode() != mLastKey )
204  {
205  setCharacter( chr );
206  }
207  }
208 }
209 
210 void CharacterWidget::mouseMoveEvent( QMouseEvent *event )
211 {
212  const QPoint widgetPosition = mapFromGlobal( event->globalPos() );
213  const uint key = ( widgetPosition.y() / mSquareSize ) * mColumns + widgetPosition.x() / mSquareSize;
214 
215  const QString text = tr( "<p>Character: <span style=\"font-size: 24pt; font-family: %1\">%2</span><p>Decimal: %3<p>Hex: 0x%4" )
216  .arg( mDisplayFont.family() )
217  .arg( QChar( key ) )
218  .arg( key )
219  .arg( QString::number( key, 16 ) );
220  QToolTip::showText( event->globalPos(), text, this );
221 }
222 
223 void CharacterWidget::mousePressEvent( QMouseEvent *event )
224 {
225  if ( event->button() == Qt::LeftButton )
226  {
227  mLastKey = ( event->y() / mSquareSize ) * mColumns + event->x() / mSquareSize;
228  if ( QChar( mLastKey ).category() != QChar::Other_NotAssigned )
229  emit characterSelected( QChar( mLastKey ) );
230  update();
231  }
232  else
233  QWidget::mousePressEvent( event );
234 }
235 
236 void CharacterWidget::paintEvent( QPaintEvent *event )
237 {
238  QPainter painter( this );
239  painter.setFont( mDisplayFont );
240 
241  const QFontMetrics fontMetrics( mDisplayFont );
242 
243  const QRect redrawRect = event->rect();
244  const int beginRow = redrawRect.top() / mSquareSize;
245  const int endRow = redrawRect.bottom() / mSquareSize;
246  const int beginColumn = redrawRect.left() / mSquareSize;
247  const int endColumn = std::min( mColumns - 1, redrawRect.right() / mSquareSize );
248 
249  const QPalette palette = qApp->palette();
250  painter.setPen( QPen( palette.color( QPalette::Mid ) ) );
251  for ( int row = beginRow; row <= endRow; ++row )
252  {
253  for ( int column = beginColumn; column <= endColumn; ++column )
254  {
255  const int key = row * mColumns + column;
256  painter.setBrush( fontMetrics.inFont( QChar( key ) ) ? QBrush( palette.color( QPalette::Base ) ) : Qt::NoBrush );
257  painter.drawRect( column * mSquareSize, row * mSquareSize, mSquareSize, mSquareSize );
258  }
259  }
260 
261  for ( int row = beginRow; row <= endRow; ++row )
262  {
263  for ( int column = beginColumn; column <= endColumn; ++column )
264  {
265  const int key = row * mColumns + column;
266  painter.setClipRect( column * mSquareSize, row * mSquareSize, mSquareSize, mSquareSize );
267  painter.setPen( QPen( palette.color( key == mLastKey ? QPalette::HighlightedText : QPalette::WindowText ) ) );
268 
269  if ( key == mLastKey )
270  painter.fillRect( column * mSquareSize + 1, row * mSquareSize + 1, mSquareSize, mSquareSize, QBrush( palette.color( QPalette::Highlight ) ) );
271 
272  if ( fontMetrics.inFont( QChar( key ) ) )
273  {
274  painter.drawText( column * mSquareSize + ( mSquareSize / 2 ) - fontMetrics.boundingRect( QChar( key ) ).width() / 2,
275  row * mSquareSize + 4 + fontMetrics.ascent(),
276  QString( QChar( key ) ) );
277  }
278  }
279  }
280 }
281 
282 void CharacterWidget::resizeEvent( QResizeEvent *event )
283 {
284  mColumns = event->size().width() / mSquareSize;
285  QWidget::resizeEvent( event );
286 }
void updateFontMerging(bool enable)
void keyPressEvent(QKeyEvent *event) override
void characterSelected(QChar character)
Emitted when a character is selected in the widget.
void setFontStyle(const QString &fontStyle)
Sets the font style to show in the widget.
void setCharacter(QChar character)
Sets the currently selected character in the widget.
void setFont(const QFont &font)
Sets the font to show in the widget.
void mousePressEvent(QMouseEvent *event) override
QSize sizeHint() const override
void paintEvent(QPaintEvent *event) override
CharacterWidget(QWidget *parent=nullptr)
Constructor for CharacterWidget.
void setFontSize(double fontSize)
Sets the font size (in points) to render in the widget.
void clearCharacter()
Clears the currently selected character in the widget.
void setColumns(int columns)
Sets the number of columns of characters to show in the widget.
void resizeEvent(QResizeEvent *event) override
void mouseMoveEvent(QMouseEvent *event) override