Character Map Example | Qt Widgets 5.13.0

Qt 5.13 | Qt Widgets | Character Map Example

Qt 5.13.0 Reference Documentation

# Character Map Example

      /****************************************************************************
      **
      ** Copyright (C) 2016 The Qt Company Ltd.
      ** Contact: https://www.qt.io/licensing/
      **
      ** This file is part of the examples of the Qt Toolkit.
      **
      ** $QT_BEGIN_LICENSE:BSD$
      ** Commercial License Usage
      ** Licensees holding valid commercial Qt licenses may use this file in
      ** accordance with the commercial license agreement provided with the
      ** Software or, alternatively, in accordance with the terms contained in
      ** a written agreement between you and The Qt Company. For licensing terms
      ** and conditions see https://www.qt.io/terms-conditions. For further
      ** information use the contact form at https://www.qt.io/contact-us.
      **
      ** BSD License Usage
      ** Alternatively, you may use this file under the terms of the BSD license
      ** as follows:
      **
      ** "Redistribution and use in source and binary forms, with or without
      ** modification, are permitted provided that the following conditions are
      ** met:
      **   * Redistributions of source code must retain the above copyright
      **     notice, this list of conditions and the following disclaimer.
      **   * Redistributions in binary form must reproduce the above copyright
      **     notice, this list of conditions and the following disclaimer in
      **     the documentation and/or other materials provided with the
      **     distribution.
      **   * Neither the name of The Qt Company Ltd nor the names of its
      **     contributors may be used to endorse or promote products derived
      **     from this software without specific prior written permission.
      **
      **
      ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
      **
      ** $QT_END_LICENSE$
      **
      ****************************************************************************/

      #include <QtWidgets>

      #include "characterwidget.h"
      #include "mainwindow.h"

      Q_DECLARE_METATYPE(QFontComboBox::FontFilter)

      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent)
      {
          QMenu *fileMenu = menuBar()->addMenu(tr("File"));
          fileMenu->addAction(tr("Quit"), this, &QWidget::close);
          QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
          helpMenu->addAction(tr("Show Font Info"), this, &MainWindow::showInfo);
          helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);

          QWidget *centralWidget = new QWidget;

          QLabel *filterLabel = new QLabel(tr("Filter:"));
          filterCombo = new QComboBox;
          filterCombo->addItem(tr("All"), QVariant::fromValue(QFontComboBox::AllFonts));
          filterCombo->addItem(tr("Scalable"), QVariant::fromValue(QFontComboBox::ScalableFonts));
          filterCombo->addItem(tr("Monospaced"), QVariant::fromValue(QFontComboBox::MonospacedFonts));
          filterCombo->addItem(tr("Proportional"), QVariant::fromValue(QFontComboBox::ProportionalFonts));
          filterCombo->setCurrentIndex(0);
          connect(filterCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
                  this, &MainWindow::filterChanged);

          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;
          lineEdit->setClearButtonEnabled(true);
      #ifndef QT_NO_CLIPBOARD
          QPushButton *clipboardButton = new QPushButton(tr("&To clipboard"));

      #endif

          connect(fontCombo, &QFontComboBox::currentFontChanged,
                  this, &MainWindow::findStyles);
          connect(fontCombo, &QFontComboBox::currentFontChanged,
                  this, &MainWindow::findSizes);
          connect(fontCombo, &QFontComboBox::currentFontChanged,
                  characterWidget, &CharacterWidget::updateFont);
          connect(sizeCombo, QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
                  characterWidget, &CharacterWidget::updateSize);
          connect(styleCombo, QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
                  characterWidget, &CharacterWidget::updateStyle);
          connect(characterWidget, &CharacterWidget::characterSelected,
                  this, &MainWindow::insertCharacter);

      #ifndef QT_NO_CLIPBOARD
          connect(clipboardButton, &QAbstractButton::clicked, this, &MainWindow::updateClipboard);
      #endif
          connect(fontMerging, &QAbstractButton::toggled, characterWidget, &CharacterWidget::updateFontMerging);

          QHBoxLayout *controlsLayout = new QHBoxLayout;
          controlsLayout->addWidget(filterLabel);
          controlsLayout->addWidget(filterCombo, 1);
          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);
      #ifndef QT_NO_CLIPBOARD
          lineLayout->addWidget(clipboardButton);
      #endif

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

          const QStringList styles = fontDatabase.styles(font.family());
          for (const QString &style : styles)
              styleCombo->addItem(style);

          int styleIndex = styleCombo->findText(currentItem);

          if (styleIndex == -1)
              styleCombo->setCurrentIndex(0);
          else
              styleCombo->setCurrentIndex(styleIndex);
      }

      void MainWindow::filterChanged(int f)
      {
          const QFontComboBox::FontFilter filter =
              filterCombo->itemData(f).value<QFontComboBox::FontFilter>();
          fontCombo->setFontFilters(filter);
          statusBar()->showMessage(tr("%n font(s) found", nullptr, fontCombo->count()));
      }

      void MainWindow::findSizes(const QFont &font)
      {
          QFontDatabase fontDatabase;
          QString currentSize = sizeCombo->currentText();

          {
              const QSignalBlocker blocker(sizeCombo);
              // sizeCombo signals are now blocked until end of scope
              sizeCombo->clear();

              if (fontDatabase.isSmoothlyScalable(font.family(), fontDatabase.styleString(font))) {
                  const QList<int> sizes = QFontDatabase::standardSizes();
                  for (const int size : sizes) {
                      sizeCombo->addItem(QVariant(size).toString());
                      sizeCombo->setEditable(true);
                  }

              } else {
                  const QList<int> sizes = fontDatabase.smoothSizes(font.family(), fontDatabase.styleString(font));
                  for (const int size : sizes ) {
                      sizeCombo->addItem(QVariant(size).toString());
                      sizeCombo->setEditable(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);
      }

      #ifndef QT_NO_CLIPBOARD
      void MainWindow::updateClipboard()
      {
          QGuiApplication::clipboard()->setText(lineEdit->text(), QClipboard::Clipboard);
          QGuiApplication::clipboard()->setText(lineEdit->text(), QClipboard::Selection);
      }
      #endif

      class FontInfoDialog : public QDialog
      {
      public:
          explicit FontInfoDialog(QWidget *parent = nullptr);

      private:
          QString text() const;
      };

      FontInfoDialog::FontInfoDialog(QWidget *parent) : QDialog(parent)
      {
          setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
          QVBoxLayout *mainLayout = new QVBoxLayout(this);
          QPlainTextEdit *textEdit = new QPlainTextEdit(text(), this);
          textEdit->setReadOnly(true);
          textEdit->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
          mainLayout->addWidget(textEdit);
          QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, this);
          connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
          mainLayout->addWidget(buttonBox);
      }

      QString FontInfoDialog::text() const
      {
          QString text;
          QTextStream str(&text);
          const QFont defaultFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
          const QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
          const QFont titleFont = QFontDatabase::systemFont(QFontDatabase::TitleFont);
          const QFont smallestReadableFont = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont);

          str << "Qt " << QT_VERSION_STR << " on " << QGuiApplication::platformName()
              << ", " << logicalDpiX() << "DPI";
          if (!qFuzzyCompare(devicePixelRatioF(), qreal(1)))
              str  << ", device pixel ratio: " << devicePixelRatioF();
          str << "\n\nDefault font : " << defaultFont.family() << ", " << defaultFont.pointSizeF() << "pt\n"
              << "Fixed font   : " << fixedFont.family() << ", " << fixedFont.pointSizeF() << "pt\n"
              << "Title font   : " << titleFont.family() << ", " << titleFont.pointSizeF() << "pt\n"
              << "Smallest font: " << smallestReadableFont.family() << ", " << smallestReadableFont.pointSizeF() << "pt\n";

          return text;
      }

      void MainWindow::showInfo()
      {
          const QRect screenGeometry = QApplication::desktop()->screenGeometry(this);
          FontInfoDialog *dialog = new FontInfoDialog(this);
          dialog->setWindowTitle(tr("Fonts"));
          dialog->setAttribute(Qt::WA_DeleteOnClose);
          dialog->resize(screenGeometry.width() / 4, screenGeometry.height() / 4);
          dialog->show();
      }