QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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
66void 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
74void CharacterWidget::setFontSize( double fontSize )
75{
76 mDisplayFont.setPointSizeF( fontSize );
77 mSquareSize = std::max( 34, QFontMetrics( mDisplayFont ).xHeight() * 3 );
78 adjustSize();
79 update();
80}
81
82void 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
104{
105 if ( mColumns == columns || columns < 1 )
106 return;
107 mColumns = columns;
108 adjustSize();
109 update();
110}
111
112void 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
142void 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
210void 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
223void 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
236void 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
282void 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