/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** 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. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "fontpanel.h" #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE FontPanel::FontPanel(QWidget *parentWidget) : QGroupBox(parentWidget), m_previewLineEdit(new QLineEdit), m_writingSystemComboBox(new QComboBox), m_familyComboBox(new QFontComboBox), m_styleComboBox(new QComboBox), m_pointSizeComboBox(new QComboBox), m_previewFontUpdateTimer(0) { setTitle(tr("Font")); QFormLayout *formLayout = new QFormLayout(this); // writing systems m_writingSystemComboBox->setEditable(false); auto writingSystems = m_fontDatabase.writingSystems(); writingSystems.push_front(QFontDatabase::Any); for (QFontDatabase::WritingSystem ws : qAsConst(writingSystems)) m_writingSystemComboBox->addItem(QFontDatabase::writingSystemName(ws), QVariant(ws)); connect(m_writingSystemComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &FontPanel::slotWritingSystemChanged); formLayout->addRow(tr("&Writing system"), m_writingSystemComboBox); connect(m_familyComboBox, &QFontComboBox::currentFontChanged, this, &FontPanel::slotFamilyChanged); formLayout->addRow(tr("&Family"), m_familyComboBox); m_styleComboBox->setEditable(false); connect(m_styleComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &FontPanel::slotStyleChanged); formLayout->addRow(tr("&Style"), m_styleComboBox); m_pointSizeComboBox->setEditable(false); connect(m_pointSizeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &FontPanel::slotPointSizeChanged); formLayout->addRow(tr("&Point size"), m_pointSizeComboBox); m_previewLineEdit->setReadOnly(true); formLayout->addRow(m_previewLineEdit); setWritingSystem(QFontDatabase::Any); } QFont FontPanel::selectedFont() const { QFont rc = m_familyComboBox->currentFont(); const QString family = rc.family(); rc.setPointSize(pointSize()); const QString styleDescription = styleString(); if (styleDescription.contains(QLatin1String("Italic"))) rc.setStyle(QFont::StyleItalic); else if (styleDescription.contains(QLatin1String("Oblique"))) rc.setStyle(QFont::StyleOblique); else rc.setStyle(QFont::StyleNormal); rc.setBold(m_fontDatabase.bold(family, styleDescription)); // Weight < 0 asserts... const int weight = m_fontDatabase.weight(family, styleDescription); if (weight >= 0) rc.setWeight(weight); return rc; } void FontPanel::setSelectedFont(const QFont &f) { m_familyComboBox->setCurrentFont(f); if (m_familyComboBox->currentIndex() < 0) { // family not in writing system - find the corresponding one? QList familyWritingSystems = m_fontDatabase.writingSystems(f.family()); if (familyWritingSystems.isEmpty()) return; setWritingSystem(familyWritingSystems.constFirst()); m_familyComboBox->setCurrentFont(f); } updateFamily(family()); const int pointSizeIndex = closestPointSizeIndex(f.pointSize()); m_pointSizeComboBox->setCurrentIndex( pointSizeIndex); const QString styleString = m_fontDatabase.styleString(f); const int styleIndex = m_styleComboBox->findText(styleString); m_styleComboBox->setCurrentIndex(styleIndex); slotUpdatePreviewFont(); } QFontDatabase::WritingSystem FontPanel::writingSystem() const { const int currentIndex = m_writingSystemComboBox->currentIndex(); if ( currentIndex == -1) return QFontDatabase::Latin; return static_cast(m_writingSystemComboBox->itemData(currentIndex).toInt()); } QString FontPanel::family() const { const int currentIndex = m_familyComboBox->currentIndex(); return currentIndex != -1 ? m_familyComboBox->currentFont().family() : QString(); } int FontPanel::pointSize() const { const int currentIndex = m_pointSizeComboBox->currentIndex(); return currentIndex != -1 ? m_pointSizeComboBox->itemData(currentIndex).toInt() : 9; } QString FontPanel::styleString() const { const int currentIndex = m_styleComboBox->currentIndex(); return currentIndex != -1 ? m_styleComboBox->itemText(currentIndex) : QString(); } void FontPanel::setWritingSystem(QFontDatabase::WritingSystem ws) { m_writingSystemComboBox->setCurrentIndex(m_writingSystemComboBox->findData(QVariant(ws))); updateWritingSystem(ws); } void FontPanel::slotWritingSystemChanged(int) { updateWritingSystem(writingSystem()); delayedPreviewFontUpdate(); } void FontPanel::slotFamilyChanged(const QFont &) { updateFamily(family()); delayedPreviewFontUpdate(); } void FontPanel::slotStyleChanged(int) { updatePointSizes(family(), styleString()); delayedPreviewFontUpdate(); } void FontPanel::slotPointSizeChanged(int) { delayedPreviewFontUpdate(); } void FontPanel::updateWritingSystem(QFontDatabase::WritingSystem ws) { m_previewLineEdit->setText(QFontDatabase::writingSystemSample(ws)); m_familyComboBox->setWritingSystem (ws); // Current font not in WS ... set index 0. if (m_familyComboBox->currentIndex() < 0) { m_familyComboBox->setCurrentIndex(0); updateFamily(family()); } } void FontPanel::updateFamily(const QString &family) { // Update styles and trigger update of point sizes. // Try to maintain selection or select normal const QString &oldStyleString = styleString(); const QStringList &styles = m_fontDatabase.styles(family); const bool hasStyles = !styles.isEmpty(); m_styleComboBox->setCurrentIndex(-1); m_styleComboBox->clear(); m_styleComboBox->setEnabled(hasStyles); int normalIndex = -1; const QString normalStyle = QLatin1String("Normal"); if (hasStyles) { for (const QString &style : styles) { // try to maintain selection or select 'normal' preferably const int newIndex = m_styleComboBox->count(); m_styleComboBox->addItem(style); if (oldStyleString == style) { m_styleComboBox->setCurrentIndex(newIndex); } else { if (oldStyleString == normalStyle) normalIndex = newIndex; } } if (m_styleComboBox->currentIndex() == -1 && normalIndex != -1) m_styleComboBox->setCurrentIndex(normalIndex); } updatePointSizes(family, styleString()); } int FontPanel::closestPointSizeIndex(int desiredPointSize) const { // try to maintain selection or select closest. int closestIndex = -1; int closestAbsError = 0xFFFF; const int pointSizeCount = m_pointSizeComboBox->count(); for (int i = 0; i < pointSizeCount; i++) { const int itemPointSize = m_pointSizeComboBox->itemData(i).toInt(); const int absError = qAbs(desiredPointSize - itemPointSize); if (absError < closestAbsError) { closestIndex = i; closestAbsError = absError; if (closestAbsError == 0) break; } else { // past optimum if (absError > closestAbsError) { break; } } } return closestIndex; } void FontPanel::updatePointSizes(const QString &family, const QString &styleString) { const int oldPointSize = pointSize(); auto pointSizes = m_fontDatabase.pointSizes(family, styleString); if (pointSizes.isEmpty()) pointSizes = QFontDatabase::standardSizes(); const bool hasSizes = !pointSizes.isEmpty(); m_pointSizeComboBox->clear(); m_pointSizeComboBox->setEnabled(hasSizes); m_pointSizeComboBox->setCurrentIndex(-1); // try to maintain selection or select closest. if (hasSizes) { QString n; for (int pointSize : qAsConst(pointSizes)) m_pointSizeComboBox->addItem(n.setNum(pointSize), QVariant(pointSize)); const int closestIndex = closestPointSizeIndex(oldPointSize); if (closestIndex != -1) m_pointSizeComboBox->setCurrentIndex(closestIndex); } } void FontPanel::slotUpdatePreviewFont() { m_previewLineEdit->setFont(selectedFont()); } void FontPanel::delayedPreviewFontUpdate() { if (!m_previewFontUpdateTimer) { m_previewFontUpdateTimer = new QTimer(this); connect(m_previewFontUpdateTimer, &QTimer::timeout, this, &FontPanel::slotUpdatePreviewFont); m_previewFontUpdateTimer->setInterval(0); m_previewFontUpdateTimer->setSingleShot(true); } if (m_previewFontUpdateTimer->isActive()) return; m_previewFontUpdateTimer->start(); } QT_END_NAMESPACE