QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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#include "qgsfontutils.h"
49
50#include <QFontDatabase>
51#include <QMouseEvent>
52#include <QPaintEvent>
53#include <QPainter>
54#include <QPen>
55#include <QPoint>
56#include <QScrollArea>
57#include <QScrollBar>
58#include <QToolTip>
59
61 : QWidget( parent )
62{
63 setMouseTracking( true );
64 setFocusPolicy( Qt::StrongFocus );
65}
66
67void CharacterWidget::setFont( const QFont &font )
68{
69 QgsFontUtils::setFontFamily( mDisplayFont, font.family() );
70 mSquareSize = std::max( 34, QFontMetrics( mDisplayFont ).xHeight() * 3 );
71 adjustSize();
72 update();
73}
74
75void CharacterWidget::setFontSize( double fontSize )
76{
77 mDisplayFont.setPointSizeF( fontSize );
78 mSquareSize = std::max( 34, QFontMetrics( mDisplayFont ).xHeight() * 3 );
79 adjustSize();
80 update();
81}
82
83void CharacterWidget::setFontStyle( const QString &fontStyle )
84{
85 const QFontDatabase fontDatabase;
86 const QFont::StyleStrategy oldStrategy = mDisplayFont.styleStrategy();
87 mDisplayFont = fontDatabase.font( mDisplayFont.family(), fontStyle, mDisplayFont.pointSize() );
88 mDisplayFont.setStyleStrategy( oldStrategy );
89 mSquareSize = std::max( 34, QFontMetrics( mDisplayFont ).xHeight() * 3 );
90 adjustSize();
91 update();
92}
93
95{
96 if ( enable )
97 mDisplayFont.setStyleStrategy( QFont::PreferDefault );
98 else
99 mDisplayFont.setStyleStrategy( QFont::NoFontMerging );
100 adjustSize();
101 update();
102}
103
105{
106 if ( mColumns == columns || columns < 1 )
107 return;
108 mColumns = columns;
109 adjustSize();
110 update();
111}
112
113void CharacterWidget::setCharacter( QChar character )
114{
115 const bool changed = character.unicode() != mLastKey;
116 mLastKey = character.isNull() ? -1 : character.unicode();
117 QWidget *widget = parentWidget();
118 if ( widget )
119 {
120 QScrollArea *scrollArea = qobject_cast< QScrollArea *>( widget->parent() );
121 if ( scrollArea && mLastKey < 65536 )
122 {
123 scrollArea->ensureVisible( 0, mLastKey / mColumns * mSquareSize );
124 }
125 }
126 if ( changed )
127 emit characterSelected( mLastKey >= 0 ? QChar( mLastKey ) : QChar() );
128
129 update();
130}
131
133{
134 mLastKey = -1;
135 update();
136}
137
139{
140 return QSize( mColumns * mSquareSize, ( 65536 / mColumns ) * mSquareSize );
141}
142
143void CharacterWidget::keyPressEvent( QKeyEvent *event )
144{
145 const QFontMetrics fm( mDisplayFont );
146
147 if ( event->key() == Qt::Key_Right )
148 {
149 int next = std::min( mLastKey + 1, 0xfffc );
150 while ( next < 0xfffc && !fm.inFont( QChar( next ) ) )
151 {
152 next++;
153 }
154 setCharacter( QChar( next ) );
155 }
156 else if ( event->key() == Qt::Key_Left )
157 {
158 int next = mLastKey - 1;
159 while ( next > 0 && !fm.inFont( QChar( next ) ) )
160 {
161 next--;
162 }
163 setCharacter( QChar( next ) );
164 }
165 else if ( event->key() == Qt::Key_Down )
166 {
167 int next = std::min( mLastKey + mColumns, 0xfffc );
168 while ( next < 0xfffc && !fm.inFont( QChar( next ) ) )
169 {
170 next = std::min( next + mColumns, 0xfffc );
171 }
172 setCharacter( QChar( next ) );
173 }
174 else if ( event->key() == Qt::Key_Up )
175 {
176 int next = std::max( 0, mLastKey - mColumns );
177 while ( next > 0 && !fm.inFont( QChar( next ) ) )
178 {
179 next = std::max( 0, next - mColumns );
180 }
181 setCharacter( QChar( next ) );
182 }
183 else if ( event->key() == Qt::Key_Home )
184 {
185 int next = 0;
186 while ( next < 0xfffc && !fm.inFont( QChar( next ) ) )
187 {
188 next++;
189 }
190 setCharacter( QChar( next ) );
191 }
192 else if ( event->key() == Qt::Key_End )
193 {
194 int next = 0xfffc;
195 while ( next > 0 && !fm.inFont( QChar( next ) ) )
196 {
197 next--;
198 }
199 setCharacter( QChar( next ) );
200 }
201 else if ( !event->text().isEmpty() )
202 {
203 QChar chr = event->text().at( 0 );
204 if ( chr.unicode() != mLastKey )
205 {
206 setCharacter( chr );
207 }
208 }
209}
210
211void CharacterWidget::mouseMoveEvent( QMouseEvent *event )
212{
213 const QPoint widgetPosition = mapFromGlobal( event->globalPos() );
214 const uint key = ( widgetPosition.y() / mSquareSize ) * mColumns + widgetPosition.x() / mSquareSize;
215
216 const QString text = QStringLiteral( "<p style=\"text-align: center; font-size: 24pt; font-family: %1\">%2</p><p><table><tr><td>%3</td><td>%2</td></tr><tr><td>%4</td><td>%5</td></tr><tr><td>%6</td><td>0x%7</td></tr></table>" )
217 .arg( mDisplayFont.family() )
218 .arg( QChar( key ) )
219 .arg( tr( "Character" ),
220 tr( "Decimal" ) )
221 .arg( key )
222 .arg( tr( "Hex" ),
223 QString::number( key, 16 ) );
224 QToolTip::showText( event->globalPos(), text, this );
225}
226
227void CharacterWidget::mousePressEvent( QMouseEvent *event )
228{
229 if ( event->button() == Qt::LeftButton )
230 {
231 mLastKey = ( event->y() / mSquareSize ) * mColumns + event->x() / mSquareSize;
232 if ( QChar( mLastKey ).category() != QChar::Other_NotAssigned )
233 emit characterSelected( QChar( mLastKey ) );
234 update();
235 }
236 else
237 QWidget::mousePressEvent( event );
238}
239
240void CharacterWidget::paintEvent( QPaintEvent *event )
241{
242 QPainter painter( this );
243 painter.setFont( mDisplayFont );
244
245 const QFontMetrics fontMetrics( mDisplayFont );
246
247 const QRect redrawRect = event->rect();
248 const int beginRow = redrawRect.top() / mSquareSize;
249 const int endRow = redrawRect.bottom() / mSquareSize;
250 const int beginColumn = redrawRect.left() / mSquareSize;
251 const int endColumn = std::min( mColumns - 1, redrawRect.right() / mSquareSize );
252
253 const QPalette palette = qApp->palette();
254 painter.setPen( QPen( palette.color( QPalette::Mid ) ) );
255 for ( int row = beginRow; row <= endRow; ++row )
256 {
257 for ( int column = beginColumn; column <= endColumn; ++column )
258 {
259 const int key = row * mColumns + column;
260 painter.setBrush( fontMetrics.inFont( QChar( key ) ) ? QBrush( palette.color( QPalette::Base ) ) : Qt::NoBrush );
261 painter.drawRect( column * mSquareSize, row * mSquareSize, mSquareSize, mSquareSize );
262 }
263 }
264
265 for ( int row = beginRow; row <= endRow; ++row )
266 {
267 for ( int column = beginColumn; column <= endColumn; ++column )
268 {
269 const int key = row * mColumns + column;
270 painter.setClipRect( column * mSquareSize, row * mSquareSize, mSquareSize, mSquareSize );
271 painter.setPen( QPen( palette.color( key == mLastKey ? QPalette::HighlightedText : QPalette::WindowText ) ) );
272
273 if ( key == mLastKey )
274 painter.fillRect( column * mSquareSize + 1, row * mSquareSize + 1, mSquareSize, mSquareSize, QBrush( palette.color( QPalette::Highlight ) ) );
275
276 if ( fontMetrics.inFont( QChar( key ) ) )
277 {
278 painter.drawText( column * mSquareSize + ( mSquareSize / 2 ) - fontMetrics.boundingRect( QChar( key ) ).width() / 2,
279 row * mSquareSize + 4 + fontMetrics.ascent(),
280 QString( QChar( key ) ) );
281 }
282 }
283 }
284}
285
286void CharacterWidget::resizeEvent( QResizeEvent *event )
287{
288 mColumns = event->size().width() / mSquareSize;
289 QWidget::resizeEvent( event );
290}
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
static void setFontFamily(QFont &font, const QString &family)
Sets the family for a font object.