QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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  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 != 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  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  QPoint widgetPosition = mapFromGlobal( event->globalPos() );
213  uint key = ( widgetPosition.y() / mSquareSize ) * mColumns + widgetPosition.x() / mSquareSize;
214 
215  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  QFontMetrics fontMetrics( mDisplayFont );
242 
243  QRect redrawRect = event->rect();
244  int beginRow = redrawRect.top() / mSquareSize;
245  int endRow = redrawRect.bottom() / mSquareSize;
246  int beginColumn = redrawRect.left() / mSquareSize;
247  int endColumn = std::min( mColumns - 1, redrawRect.right() / mSquareSize );
248 
249  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  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  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 }
CharacterWidget::setFont
void setFont(const QFont &font)
Sets the font to show in the widget.
Definition: characterwidget.cpp:66
CharacterWidget::clearCharacter
void clearCharacter()
Clears the currently selected character in the widget.
Definition: characterwidget.cpp:131
CharacterWidget::CharacterWidget
CharacterWidget(QWidget *parent=nullptr)
Constructor for CharacterWidget.
Definition: characterwidget.cpp:59
CharacterWidget::font
QFont font
Definition: characterwidget.h:74
CharacterWidget::keyPressEvent
void keyPressEvent(QKeyEvent *event) override
Definition: characterwidget.cpp:142
CharacterWidget::updateFontMerging
void updateFontMerging(bool enable)
Definition: characterwidget.cpp:93
characterwidget.h
CharacterWidget::characterSelected
void characterSelected(QChar character)
Emitted when a character is selected in the widget.
CharacterWidget::setColumns
void setColumns(int columns)
Sets the number of columns of characters to show in the widget.
Definition: characterwidget.cpp:103
qgsapplication.h
CharacterWidget::setFontStyle
void setFontStyle(const QString &fontStyle)
Sets the font style to show in the widget.
Definition: characterwidget.cpp:82
CharacterWidget::character
QChar character
Definition: characterwidget.h:72
CharacterWidget::resizeEvent
void resizeEvent(QResizeEvent *event) override
Definition: characterwidget.cpp:282
CharacterWidget::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *event) override
Definition: characterwidget.cpp:210
CharacterWidget::setCharacter
void setCharacter(QChar character)
Sets the currently selected character in the widget.
Definition: characterwidget.cpp:112
CharacterWidget::setFontSize
void setFontSize(double fontSize)
Sets the font size (in points) to render in the widget.
Definition: characterwidget.cpp:74
CharacterWidget::sizeHint
QSize sizeHint() const override
Definition: characterwidget.cpp:137
CharacterWidget::mousePressEvent
void mousePressEvent(QMouseEvent *event) override
Definition: characterwidget.cpp:223
CharacterWidget::columns
int columns
Definition: characterwidget.h:73
CharacterWidget::paintEvent
void paintEvent(QPaintEvent *event) override
Definition: characterwidget.cpp:236