Mega Code Archive

 
Categories / C++ / Qt
 

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(); }