character painter widget
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CHARACTERWIDGET_H
#define CHARACTERWIDGET_H
#include <QFont>
#include <QPoint>
#include <QSize>
#include <QString>
#include <QWidget>
QT_BEGIN_NAMESPACE
class QMouseEvent;
class QPaintEvent;
QT_END_NAMESPACE
class CharacterWidget : public QWidget
{
Q_OBJECT
public:
CharacterWidget(QWidget *parent = 0);
QSize sizeHint() const;
public slots:
void updateFont(const QFont &font);
void updateSize(const QString &fontSize);
void updateStyle(const QString &fontStyle);
void updateFontMerging(bool enable);
signals:
void characterSelected(const QString &character);
protected:
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void paintEvent(QPaintEvent *event);
private:
QFont displayFont;
int columns;
int lastKey;
int squareSize;
};
#endif
#include <QtGui>
#include "characterwidget.h"
CharacterWidget::CharacterWidget(QWidget *parent)
: QWidget(parent)
{
squareSize = 24;
columns = 16;
lastKey = -1;
setMouseTracking(true);
}
void CharacterWidget::updateFont(const QFont &font)
{
displayFont.setFamily(font.family());
squareSize = qMax(24, QFontMetrics(displayFont).xHeight() * 3);
adjustSize();
update();
}
void CharacterWidget::updateSize(const QString &fontSize)
{
displayFont.setPointSize(fontSize.toInt());
squareSize = qMax(24, QFontMetrics(displayFont).xHeight() * 3);
adjustSize();
update();
}
void CharacterWidget::updateStyle(const QString &fontStyle)
{
QFontDatabase fontDatabase;
const QFont::StyleStrategy oldStrategy = displayFont.styleStrategy();
displayFont = fontDatabase.font(displayFont.family(), fontStyle, displayFont.pointSize());
displayFont.setStyleStrategy(oldStrategy);
squareSize = qMax(24, QFontMetrics(displayFont).xHeight() * 3);
adjustSize();
update();
}
void CharacterWidget::updateFontMerging(bool enable)
{
if (enable)
displayFont.setStyleStrategy(QFont::PreferDefault);
else
displayFont.setStyleStrategy(QFont::NoFontMerging);
adjustSize();
update();
}
QSize CharacterWidget::sizeHint() const
{
return QSize(columns*squareSize, (65536/columns)*squareSize);
}
void CharacterWidget::mouseMoveEvent(QMouseEvent *event)
{
QPoint widgetPosition = mapFromGlobal(event->globalPos());
uint key = (widgetPosition.y()/squareSize)*columns + widgetPosition.x()/squareSize;
QString text = QString::fromLatin1("<p>Character: <span style=\"font-size: 24pt; font-family: %1\">").arg(displayFont.family())
+ QChar(key)
+ QString::fromLatin1("</span><p>Value: 0x")
+ QString::number(key, 16);
QToolTip::showText(event->globalPos(), text, this);
}
void CharacterWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
lastKey = (event->y()/squareSize)*columns + event->x()/squareSize;
if (QChar(lastKey).category() != QChar::NoCategory)
emit characterSelected(QString(QChar(lastKey)));
update();
}
else
QWidget::mousePressEvent(event);
}
void CharacterWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.fillRect(event->rect(), QBrush(Qt::white));
painter.setFont(displayFont);
QRect redrawRect = event->rect();
int beginRow = redrawRect.top()/squareSize;
int endRow = redrawRect.bottom()/squareSize;
int beginColumn = redrawRect.left()/squareSize;
int endColumn = redrawRect.right()/squareSize;
painter.setPen(QPen(Qt::gray));
for (int row = beginRow; row <= endRow; ++row) {
for (int column = beginColumn; column <= endColumn; ++column) {
painter.drawRect(column*squareSize, row*squareSize, squareSize, squareSize);
}
}
QFontMetrics fontMetrics(displayFont);
painter.setPen(QPen(Qt::black));
for (int row = beginRow; row <= endRow; ++row) {
for (int column = beginColumn; column <= endColumn; ++column) {
int key = row*columns + column;
painter.setClipRect(column*squareSize, row*squareSize, squareSize, squareSize);
if (key == lastKey)
painter.fillRect(column*squareSize + 1, row*squareSize + 1, squareSize, squareSize, QBrush(Qt::red));
painter.drawText(column*squareSize + (squareSize / 2) - fontMetrics.width(QChar(key))/2,
row*squareSize + 4 + fontMetrics.ascent(),
QString(QChar(key)));
}
}
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QString>
QT_BEGIN_NAMESPACE
class QClipboard;
class QComboBox;
class QFontComboBox;
class QLineEdit;
class QScrollArea;
class QCheckBox;
QT_END_NAMESPACE
class CharacterWidget;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
public slots:
void findStyles(const QFont &font);
void findSizes(const QFont &font);
void insertCharacter(const QString &character);
void updateClipboard();
private:
CharacterWidget *characterWidget;
QClipboard *clipboard;
QComboBox *styleCombo;
QComboBox *sizeCombo;
QFontComboBox *fontCombo;
QLineEdit *lineEdit;
QScrollArea *scrollArea;
QCheckBox *fontMerging;
};
#endif
#include <QtGui>
#include "characterwidget.h"
#include "mainwindow.h"
MainWindow::MainWindow()
{
QWidget *centralWidget = new QWidget;
QLabel *fontLabel = new QLabel(tr("Font:"));
fontCombo = new QFontComboBox;
QLabel *sizeLabel = new QLabel(tr("Size:"));
sizeCombo = new QComboBox;
QLabel *styleLabel = new QLabel(tr("Style:"));
styleCombo = new QComboBox;
QLabel *fontMergingLabel = new QLabel(tr("Automatic Font Merging:"));
fontMerging = new QCheckBox;
fontMerging->setChecked(true);
scrollArea = new QScrollArea;
characterWidget = new CharacterWidget;
scrollArea->setWidget(characterWidget);
findStyles(fontCombo->currentFont());
findSizes(fontCombo->currentFont());
lineEdit = new QLineEdit;
QPushButton *clipboardButton = new QPushButton(tr("&To clipboard"));
clipboard = QApplication::clipboard();
connect(fontCombo, SIGNAL(currentFontChanged(const QFont &)),
this, SLOT(findStyles(const QFont &)));
connect(fontCombo, SIGNAL(currentFontChanged(const QFont &)),
this, SLOT(findSizes(const QFont &)));
connect(fontCombo, SIGNAL(currentFontChanged(const QFont &)),
characterWidget, SLOT(updateFont(const QFont &)));
connect(sizeCombo, SIGNAL(currentIndexChanged(const QString &)),
characterWidget, SLOT(updateSize(const QString &)));
connect(styleCombo, SIGNAL(currentIndexChanged(const QString &)),
characterWidget, SLOT(updateStyle(const QString &)));
connect(characterWidget, SIGNAL(characterSelected(const QString &)),
this, SLOT(insertCharacter(const QString &)));
connect(clipboardButton, SIGNAL(clicked()), this, SLOT(updateClipboard()));
connect(fontMerging, SIGNAL(toggled(bool)), characterWidget, SLOT(updateFontMerging(bool)));
QHBoxLayout *controlsLayout = new QHBoxLayout;
controlsLayout->addWidget(fontLabel);
controlsLayout->addWidget(fontCombo, 1);
controlsLayout->addWidget(sizeLabel);
controlsLayout->addWidget(sizeCombo, 1);
controlsLayout->addWidget(styleLabel);
controlsLayout->addWidget(styleCombo, 1);
controlsLayout->addWidget(fontMergingLabel);
controlsLayout->addWidget(fontMerging, 1);
controlsLayout->addStretch(1);
QHBoxLayout *lineLayout = new QHBoxLayout;
lineLayout->addWidget(lineEdit, 1);
lineLayout->addSpacing(12);
lineLayout->addWidget(clipboardButton);
QVBoxLayout *centralLayout = new QVBoxLayout;
centralLayout->addLayout(controlsLayout);
centralLayout->addWidget(scrollArea, 1);
centralLayout->addSpacing(4);
centralLayout->addLayout(lineLayout);
centralWidget->setLayout(centralLayout);
setCentralWidget(centralWidget);
setWindowTitle(tr("Character Map"));
}
void MainWindow::findStyles(const QFont &font)
{
QFontDatabase fontDatabase;
QString currentItem = styleCombo->currentText();
styleCombo->clear();
QString style;
foreach (style, fontDatabase.styles(font.family()))
styleCombo->addItem(style);
int styleIndex = styleCombo->findText(currentItem);
if (styleIndex == -1)
styleCombo->setCurrentIndex(0);
else
styleCombo->setCurrentIndex(styleIndex);
}
void MainWindow::findSizes(const QFont &font)
{
QFontDatabase fontDatabase;
QString currentSize = sizeCombo->currentText();
sizeCombo->blockSignals(true);
sizeCombo->clear();
int size;
if(fontDatabase.isSmoothlyScalable(font.family(), fontDatabase.styleString(font))) {
foreach(size, QFontDatabase::standardSizes()) {
sizeCombo->addItem(QVariant(size).toString());
sizeCombo->setEditable(true);
}
} else {
foreach(size, fontDatabase.smoothSizes(font.family(), fontDatabase.styleString(font))) {
sizeCombo->addItem(QVariant(size).toString());
sizeCombo->setEditable(false);
}
}
sizeCombo->blockSignals(false);
int sizeIndex = sizeCombo->findText(currentSize);
if(sizeIndex == -1)
sizeCombo->setCurrentIndex(qMax(0, sizeCombo->count() / 3));
else
sizeCombo->setCurrentIndex(sizeIndex);
}
void MainWindow::insertCharacter(const QString &character)
{
lineEdit->insert(character);
}
void MainWindow::updateClipboard()
{
clipboard->setText(lineEdit->text(), QClipboard::Clipboard);
clipboard->setText(lineEdit->text(), QClipboard::Selection);
}
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}
Related examples in the same category