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