File indexing completed on 2025-04-27 03:58:23

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-12-23
0007  * Description : a widget to change font properties.
0008  *
0009  * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText:      1996 by Bernd Johannes Wuebben  <wuebben at kde dot org>
0011  * SPDX-FileCopyrightText:      1999 by Preston Brown <pbrown at kde dot org>
0012  * SPDX-FileCopyrightText:      1999 by Mario Weilguni <mweilguni at kde dot org>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "dfontproperties.h"
0019 
0020 // C++ includes
0021 
0022 #include <cmath>
0023 
0024 // Qt includes
0025 
0026 #include <QCheckBox>
0027 #include <QDoubleSpinBox>
0028 #include <QGuiApplication>
0029 #include <QLabel>
0030 #include <QLayout>
0031 #include <QLocale>
0032 #include <QSplitter>
0033 #include <QScrollBar>
0034 #include <QFontDatabase>
0035 #include <QGroupBox>
0036 #include <QListWidget>
0037 #include <QCoreApplication>
0038 #include <QString>
0039 #include <QHash>
0040 
0041 // KDE includes
0042 
0043 #include <klocalizedstring.h>
0044 
0045 #include "dtextedit.h"
0046 
0047 namespace Digikam
0048 {
0049 
0050 static bool localeLessThan(const QString& a, const QString& b)
0051 {
0052     return (QString::localeAwareCompare(a, b) < 0);
0053 }
0054 
0055 static int minimumListWidth(const QListWidget* list)
0056 {
0057     int w = 0;
0058 
0059     for (int i = 0 ; i < list->count() ; ++i)
0060     {
0061         int itemWidth = list->visualItemRect(list->item(i)).width();
0062 
0063         // ...and add a space on both sides for not too tight look.
0064 
0065         itemWidth    += list->fontMetrics().horizontalAdvance(QLatin1Char(' ')) * 2;
0066 
0067         w             = qMax(w, itemWidth);
0068     }
0069 
0070     if (w == 0)
0071     {
0072         w = 40;
0073     }
0074 
0075     w += list->frameWidth() * 2;
0076     w += list->verticalScrollBar()->sizeHint().width();
0077 
0078     return w;
0079 }
0080 
0081 static int minimumListHeight(const QListWidget* list, int numVisibleEntry)
0082 {
0083     int w = (list->count() > 0) ? list->visualItemRect(list->item(0)).height()
0084                                 : list->fontMetrics().lineSpacing();
0085 
0086     if (w < 0)
0087     {
0088         w = 10;
0089     }
0090 
0091     if (numVisibleEntry <= 0)
0092     {
0093         numVisibleEntry = 4;
0094     }
0095 
0096     return (w * numVisibleEntry + 2 * list->frameWidth());
0097 }
0098 
0099 static QString formatFontSize(qreal size)
0100 {
0101     return QLocale::system().toString(size, 'f', (size == floor(size)) ? 0 : 1);
0102 }
0103 
0104 // -----------------------------------------------------------------------------------
0105 
0106 class Q_DECL_HIDDEN DFontProperties::Private
0107 {
0108 public:
0109 
0110     explicit Private(DFontProperties* const qq)
0111         : q                     (qq),
0112           sizeOfFont            (nullptr),
0113           sampleEdit            (nullptr),
0114           familyLabel           (nullptr),
0115           styleLabel            (nullptr),
0116           familyCheckbox        (nullptr),
0117           styleCheckbox         (nullptr),
0118           sizeCheckbox          (nullptr),
0119           sizeLabel             (nullptr),
0120           familyListBox         (nullptr),
0121           styleListBox          (nullptr),
0122           sizeListBox           (nullptr),
0123           sizeIsRelativeCheckBox(nullptr),
0124           selectedSize          (-1),
0125           customSizeRow         (-1),
0126           signalsAllowed        (true),
0127           usingFixed            (true)
0128     {
0129         palette.setColor(QPalette::Active, QPalette::Text, Qt::black);
0130         palette.setColor(QPalette::Active, QPalette::Base, Qt::white);
0131     }
0132 
0133     void    setFamilyBoxItems(const QStringList& fonts);
0134     void    fillFamilyListBox(bool onlyFixedFonts = false);
0135     int     nearestSizeRow(qreal val, bool customize);
0136     qreal   fillSizeList(const QList<qreal>& sizes = QList<qreal>());
0137     qreal   setupSizeListBox(const QString& family, const QString& style);
0138     void    setupDisplay();
0139     QString styleIdentifier(const QFont& font);
0140 
0141     /**
0142      * Split the compound raw font name into family and foundry.
0143      *
0144      * @param name the raw font name reported by Qt
0145      * @param family the storage for family name
0146      * @param foundry the storage for foundry name
0147      */
0148     void splitFontString(const QString& name, QString* family, QString* foundry = nullptr);
0149 
0150     /**
0151      * Translate the font name for the user.
0152      * Primarily for generic fonts like Serif, Sans-Serif, etc.
0153      *
0154      * @param name the raw font name reported by Qt
0155      * @return translated font name
0156      */
0157     QString translateFontName(const QString& name);
0158 
0159     /**
0160      * Compose locale-aware sorted list of translated font names,
0161      * with generic fonts handled in a special way.
0162      * The mapping of translated to raw names can be reported too if required.
0163      *
0164      * @param names raw font names as reported by Qt
0165      * @param trToRawNames storage for mapping of translated to raw names
0166      * @return sorted list of translated font names
0167      */
0168     QStringList translateFontNameList(const QStringList& names, QHash<QString, QString>* trToRawNames = nullptr);
0169 
0170     void _d_toggled_checkbox();
0171     void _d_family_chosen_slot(const QString&);
0172     void _d_size_chosen_slot(const QString&);
0173     void _d_style_chosen_slot(const QString&);
0174     void _d_displaySample(const QFont& font);
0175     void _d_size_value_slot(double);
0176 
0177 public:
0178 
0179     DFontProperties*        q;
0180 
0181     QPalette                palette;
0182     QDoubleSpinBox*         sizeOfFont;
0183     DTextEdit*              sampleEdit;
0184 
0185     QLabel*                 familyLabel;
0186     QLabel*                 styleLabel;
0187     QCheckBox*              familyCheckbox;
0188     QCheckBox*              styleCheckbox;
0189     QCheckBox*              sizeCheckbox;
0190     QLabel*                 sizeLabel;
0191     QListWidget*            familyListBox;
0192     QListWidget*            styleListBox;
0193     QListWidget*            sizeListBox;
0194     QCheckBox*              sizeIsRelativeCheckBox;
0195 
0196     QFont                   selFont;
0197 
0198     QString                 selectedStyle;
0199     qreal                   selectedSize;
0200 
0201     QString                 standardSizeAtCustom;
0202     int                     customSizeRow;
0203 
0204     bool                    signalsAllowed;
0205     bool                    usingFixed;
0206 
0207     /**
0208      * Mappings of translated to Qt originated family and style strings.
0209      */
0210     QHash<QString, QString> qtFamilies;
0211     QHash<QString, QString> qtStyles;
0212 
0213     /**
0214      * Mapping of translated style strings to internal style identifiers.
0215      */
0216     QHash<QString, QString> styleIDs;
0217 };
0218 
0219 DFontProperties::DFontProperties(QWidget* const parent,
0220                                  const DisplayFlags& flags,
0221                                  const QStringList& fontList,
0222                                  int visibleListSize,
0223                                  Qt::CheckState* const sizeIsRelativeState)
0224     : QWidget(parent),
0225       d      (new DFontProperties::Private(this))
0226 {
0227     d->usingFixed = flags & FixedFontsOnly;
0228     setWhatsThis(i18nc("@title: font properties", "Here you can choose the font to be used."));
0229 
0230     // The top layout is divided vertically into a splitter with font
0231     // attribute widgets and preview on the top, and XLFD data at the bottom.
0232 
0233     QVBoxLayout* const topLayout = new QVBoxLayout(this);
0234     topLayout->setContentsMargins(QMargins());
0235     const int spacingHint = qMin(style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing),
0236                                  style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing));
0237     int checkBoxGap              = spacingHint / 2;
0238 
0239     // The splitter contains font attribute widgets in the top part,
0240     // and the font preview in the bottom part.
0241     // The splitter is there to allow the user to resize the font preview.
0242 
0243     QSplitter* const splitter    = new QSplitter(Qt::Vertical, this);
0244     splitter->setChildrenCollapsible(false);
0245     topLayout->addWidget(splitter);
0246 
0247     // Build the grid of font attribute widgets for the upper splitter part.
0248 
0249     QWidget* page           = nullptr;
0250     QGridLayout* gridLayout = nullptr;
0251     int row                 = 0;
0252 
0253     if (flags & DisplayFrame)
0254     {
0255         page       = new QGroupBox(i18nc("@title: font properties", "Requested Font"), this);
0256         splitter->addWidget(page);
0257         gridLayout = new QGridLayout(page);
0258         row        = 1;
0259     }
0260     else
0261     {
0262         page       = new QWidget(this);
0263         splitter->addWidget(page);
0264         gridLayout = new QGridLayout(page);
0265         gridLayout->setContentsMargins(QMargins());
0266     }
0267 
0268     // first, create the labels across the top
0269 
0270     QHBoxLayout* const familyLayout = new QHBoxLayout();
0271     familyLayout->addSpacing(checkBoxGap);
0272 
0273     if (flags & ShowDifferences)
0274     {
0275         d->familyCheckbox = new QCheckBox(i18nc("@title: font properties", "Font"), page);
0276 
0277         connect(d->familyCheckbox, SIGNAL(toggled(bool)),
0278                 this, SLOT(_d_toggled_checkbox()));
0279 
0280         familyLayout->addWidget(d->familyCheckbox, 0, Qt::AlignLeft);
0281         d->familyCheckbox->setWhatsThis(i18nc("@info: font properties", "Enable this checkbox to change the font family settings."));
0282         d->familyCheckbox->setToolTip(i18nc("@info: font properties", "Change font family?"));
0283         d->familyLabel = nullptr;
0284     }
0285     else
0286     {
0287         d->familyCheckbox = nullptr;
0288         d->familyLabel    = new QLabel(i18nc("@label: font properties", "Font:"), page);
0289         familyLayout->addWidget(d->familyLabel, 1, Qt::AlignLeft);
0290     }
0291 
0292     gridLayout->addLayout(familyLayout, row, 0);
0293 
0294     QHBoxLayout* const styleLayout = new QHBoxLayout();
0295 
0296     if (flags & ShowDifferences)
0297     {
0298         d->styleCheckbox = new QCheckBox(i18nc("@title: font properties", "Font style"), page);
0299 
0300         connect(d->styleCheckbox, SIGNAL(toggled(bool)),
0301                 this, SLOT(_d_toggled_checkbox()));
0302 
0303         styleLayout->addWidget(d->styleCheckbox, 0, Qt::AlignLeft);
0304         d->styleCheckbox->setWhatsThis(i18nc("@info: font properties", "Enable this checkbox to change the font style settings."));
0305         d->styleCheckbox->setToolTip(i18nc("@info: font properties", "Change font style?"));
0306         d->styleLabel = nullptr;
0307     }
0308     else
0309     {
0310         d->styleCheckbox = nullptr;
0311         d->styleLabel    = new QLabel(i18nc("@label: font properties", "Font style:"), page);
0312         styleLayout->addWidget(d->styleLabel, 1, Qt::AlignLeft);
0313     }
0314 
0315     styleLayout->addSpacing(checkBoxGap);
0316     gridLayout->addLayout(styleLayout, row, 1);
0317 
0318     QHBoxLayout* const sizeLayout = new QHBoxLayout();
0319 
0320     if (flags & ShowDifferences)
0321     {
0322         d->sizeCheckbox = new QCheckBox(i18nc("@title: font properties", "Size"), page);
0323 
0324         connect(d->sizeCheckbox, SIGNAL(toggled(bool)),
0325                 this, SLOT(_d_toggled_checkbox()));
0326 
0327         sizeLayout->addWidget(d->sizeCheckbox, 0, Qt::AlignLeft);
0328         d->sizeCheckbox->setWhatsThis(i18nc("@info: font properties", "Enable this checkbox to change the font size settings."));
0329         d->sizeCheckbox->setToolTip(i18nc("@info: font properties", "Change font size?"));
0330         d->sizeLabel = nullptr;
0331     }
0332     else
0333     {
0334         d->sizeCheckbox = nullptr;
0335         d->sizeLabel    = new QLabel(i18nc("@label:listbox Font size", "Size:"), page);
0336         sizeLayout->addWidget(d->sizeLabel, 1, Qt::AlignLeft);
0337     }
0338 
0339     sizeLayout->addSpacing(checkBoxGap);
0340     sizeLayout->addSpacing(checkBoxGap);        // prevent label from eating border
0341     gridLayout->addLayout(sizeLayout, row, 2);
0342 
0343     row ++;
0344 
0345     // now create the actual boxes that hold the info
0346 
0347     d->familyListBox = new QListWidget(page);
0348     d->familyListBox->setEnabled(flags ^ ShowDifferences);
0349     gridLayout->addWidget(d->familyListBox, row, 0);
0350     QString fontFamilyWhatsThisText(i18nc("@info: font properties", "Here you can choose the font family to be used."));
0351     d->familyListBox->setWhatsThis(fontFamilyWhatsThisText);
0352 
0353     if (flags & ShowDifferences)
0354     {
0355         d->familyCheckbox->setWhatsThis(fontFamilyWhatsThisText);
0356     }
0357     else
0358     {
0359         d->familyLabel->setWhatsThis(fontFamilyWhatsThisText);
0360     }
0361 
0362     connect(d->familyListBox, SIGNAL(currentTextChanged(QString)),
0363             this, SLOT(_d_family_chosen_slot(QString)));
0364 
0365     if (!fontList.isEmpty())
0366     {
0367         d->setFamilyBoxItems(fontList);
0368     }
0369     else
0370     {
0371         d->fillFamilyListBox(flags & FixedFontsOnly);
0372     }
0373 
0374     d->familyListBox->setMinimumWidth(minimumListWidth(d->familyListBox));
0375     d->familyListBox->setMinimumHeight(minimumListHeight(d->familyListBox, visibleListSize));
0376 
0377     d->styleListBox = new QListWidget(page);
0378     d->styleListBox->setEnabled(flags ^ ShowDifferences);
0379     gridLayout->addWidget(d->styleListBox, row, 1);
0380     d->styleListBox->setWhatsThis(i18nc("@info: font properties", "Here you can choose the font style to be used."));
0381 
0382     if (flags & ShowDifferences)
0383     {
0384         ((QWidget *)d->styleCheckbox)->setWhatsThis(fontFamilyWhatsThisText);
0385     }
0386     else
0387     {
0388         ((QWidget *)d->styleLabel)->setWhatsThis(fontFamilyWhatsThisText);
0389     }
0390 
0391     // Populate usual styles, to determine minimum list width;
0392     // will be replaced later with correct styles.
0393 
0394     d->styleListBox->addItem(i18nc("@item: font style", "Normal"));
0395     d->styleListBox->addItem(i18nc("@item: font style", "Italic"));
0396     d->styleListBox->addItem(i18nc("@item: font style", "Oblique"));
0397     d->styleListBox->addItem(i18nc("@item: font style", "Bold"));
0398     d->styleListBox->addItem(i18nc("@item: font style", "Bold Italic"));
0399     d->styleListBox->setMinimumWidth(minimumListWidth(d->styleListBox));
0400     d->styleListBox->setMinimumHeight(minimumListHeight(d->styleListBox, visibleListSize));
0401 
0402     connect(d->styleListBox, SIGNAL(currentTextChanged(QString)),
0403             this, SLOT(_d_style_chosen_slot(QString)));
0404 
0405     d->sizeListBox = new QListWidget(page);
0406     d->sizeOfFont  = new QDoubleSpinBox(page);
0407     d->sizeOfFont->setMinimum(4);
0408     d->sizeOfFont->setMaximum(999);
0409     d->sizeOfFont->setDecimals(1);
0410     d->sizeOfFont->setSingleStep(1);
0411 
0412     d->sizeListBox->setEnabled(flags ^ ShowDifferences);
0413     d->sizeOfFont->setEnabled(flags ^ ShowDifferences);
0414 
0415     if (sizeIsRelativeState)
0416     {
0417         QString sizeIsRelativeCBText          = i18nc("@item: font size", "Relative");
0418         QString sizeIsRelativeCBToolTipText   = i18nc("@info: font properties",
0419                                                       "Font size \"fixed\" or \"relative\" to environment");
0420         QString sizeIsRelativeCBWhatsThisText = i18nc("@info: font properties", "Here you can switch between fixed font size and font size "
0421                                                       "to be calculated dynamically and adjusted to changing "
0422                                                       "environment (e.g. widget dimensions, paper size).");
0423         d->sizeIsRelativeCheckBox             = new QCheckBox(sizeIsRelativeCBText, page);
0424         d->sizeIsRelativeCheckBox->setTristate(flags & ShowDifferences);
0425         QGridLayout* const sizeLayout2        = new QGridLayout();
0426         sizeLayout2->setSpacing(spacingHint / 2);
0427         gridLayout->addLayout(sizeLayout2, row, 2);
0428         sizeLayout2->setColumnStretch(1, 1);                    // to prevent text from eating the right border
0429         sizeLayout2->addWidget(d->sizeOfFont,  0, 0, 1, 2);
0430         sizeLayout2->addWidget(d->sizeListBox, 1, 0, 1, 2);
0431         sizeLayout2->addWidget(d->sizeIsRelativeCheckBox, 2, 0, Qt::AlignLeft);
0432         d->sizeIsRelativeCheckBox->setWhatsThis(sizeIsRelativeCBWhatsThisText);
0433         d->sizeIsRelativeCheckBox->setToolTip(sizeIsRelativeCBToolTipText);
0434     }
0435     else
0436     {
0437         d->sizeIsRelativeCheckBox      = nullptr;
0438         QGridLayout* const sizeLayout2 = new QGridLayout();
0439         sizeLayout2->setSpacing(spacingHint / 2);
0440         gridLayout->addLayout(sizeLayout2, row, 2);
0441         sizeLayout2->addWidget(d->sizeOfFont,  0, 0);
0442         sizeLayout2->addWidget(d->sizeListBox, 1, 0);
0443     }
0444 
0445     QString fontSizeWhatsThisText = i18nc("@info: font properties", "Here you can choose the font size to be used.");
0446     d->sizeListBox->setWhatsThis(fontSizeWhatsThisText);
0447 
0448     if (flags & ShowDifferences)
0449     {
0450         ((QWidget*)d->sizeCheckbox)->setWhatsThis(fontSizeWhatsThisText);
0451     }
0452     else
0453     {
0454         ((QWidget*)d->sizeLabel)->setWhatsThis(fontSizeWhatsThisText);
0455     }
0456 
0457     // Populate with usual sizes, to determine minimum list width;
0458     // will be replaced later with correct sizes.
0459 
0460     d->fillSizeList();
0461     d->sizeListBox->setMinimumWidth(minimumListWidth(d->sizeListBox) + d->sizeListBox->fontMetrics().maxWidth());
0462     d->sizeListBox->setMinimumHeight(minimumListHeight(d->sizeListBox, visibleListSize));
0463 
0464     connect(d->sizeOfFont, SIGNAL(valueChanged(double)),
0465             this, SLOT(_d_size_value_slot(double)));
0466 
0467     connect(d->sizeListBox, SIGNAL(currentTextChanged(QString)),
0468             this, SLOT(_d_size_chosen_slot(QString)));
0469 
0470     row ++;
0471 
0472     // Completed the font attribute grid.
0473     // Add the font preview into the lower part of the splitter.
0474 
0475     d->sampleEdit = new DTextEdit(0, page);
0476     d->sampleEdit->setAcceptRichText(false);
0477     QFont tmpFont(font().family(), 64, QFont::Black);
0478     d->sampleEdit->setFont(tmpFont);
0479     d->sampleEdit->setMinimumHeight(d->sampleEdit->fontMetrics().lineSpacing());
0480 
0481     // tr: A classical test phrase, with all letters of the English alphabet.
0482     // Replace it with a sample text in your language, such that it is
0483     // representative of language's writing system.
0484     // If you wish, you can input several lines of text separated by \n.
0485 
0486     setSampleText(i18nc("@info: font properties", "The Quick Brown Fox Jumps Over The Lazy Dog"));
0487     d->sampleEdit->setTextCursor(QTextCursor(d->sampleEdit->document()));
0488     QString sampleEditWhatsThisText = i18nc("@info: font properties", "This sample text illustrates the current settings. "
0489                                             "You may edit it to test special characters.");
0490     d->sampleEdit->setWhatsThis(sampleEditWhatsThisText);
0491 
0492     connect(this, SIGNAL(fontSelected(QFont)),
0493             this, SLOT(_d_displaySample(QFont)));
0494 
0495     splitter->addWidget(d->sampleEdit);
0496 
0497     // Finished setting up the splitter.
0498     // Finished setting up the chooser layout.
0499     // lets initialize the display if possible
0500 
0501     if (d->usingFixed)
0502     {
0503         setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont), d->usingFixed);
0504     }
0505     else
0506     {
0507         setFont(QGuiApplication::font(), d->usingFixed);
0508     }
0509 
0510     // check or uncheck or gray out the "relative" checkbox
0511 
0512     if (sizeIsRelativeState && d->sizeIsRelativeCheckBox)
0513     {
0514         setSizeIsRelative(*sizeIsRelativeState);
0515     }
0516 
0517     // Set focus to the size list as this is the most commonly changed property
0518 
0519     d->sizeListBox->setFocus();
0520 }
0521 
0522 DFontProperties::~DFontProperties()
0523 {
0524     delete d;
0525 }
0526 
0527 void DFontProperties::setColor(const QColor& col)
0528 {
0529     d->palette.setColor(QPalette::Active, QPalette::Text, col);
0530     QPalette pal       = d->sampleEdit->palette();
0531     pal.setColor(QPalette::Active, QPalette::Text, col);
0532     d->sampleEdit->setPalette(pal);
0533     QTextCursor cursor = d->sampleEdit->textCursor();
0534     d->sampleEdit->selectAll();
0535     d->sampleEdit->setTextColor(col);
0536     d->sampleEdit->setTextCursor(cursor);
0537 }
0538 
0539 QColor DFontProperties::color() const
0540 {
0541     return d->palette.color(QPalette::Active, QPalette::Text);
0542 }
0543 
0544 void DFontProperties::setBackgroundColor(const QColor& col)
0545 {
0546     d->palette.setColor(QPalette::Active, QPalette::Base, col);
0547     QPalette pal = d->sampleEdit->palette();
0548     pal.setColor(QPalette::Active, QPalette::Base, col);
0549     d->sampleEdit->setPalette(pal);
0550 }
0551 
0552 QColor DFontProperties::backgroundColor() const
0553 {
0554     return d->palette.color(QPalette::Active, QPalette::Base);
0555 }
0556 
0557 void DFontProperties::setSizeIsRelative(Qt::CheckState relative)
0558 {
0559     // check or uncheck or gray out the "relative" checkbox
0560 
0561     if (d->sizeIsRelativeCheckBox)
0562     {
0563         if (Qt::PartiallyChecked == relative)
0564         {
0565             d->sizeIsRelativeCheckBox->setCheckState(Qt::PartiallyChecked);
0566         }
0567         else
0568         {
0569             d->sizeIsRelativeCheckBox->setCheckState((Qt::Checked == relative) ? Qt::Checked : Qt::Unchecked);
0570         }
0571     }
0572 }
0573 
0574 Qt::CheckState DFontProperties::sizeIsRelative() const
0575 {
0576     return d->sizeIsRelativeCheckBox ? d->sizeIsRelativeCheckBox->checkState()
0577                                      : Qt::PartiallyChecked;
0578 }
0579 
0580 QString DFontProperties::sampleText() const
0581 {
0582     return d->sampleEdit->toPlainText();
0583 }
0584 
0585 void DFontProperties::setSampleText(const QString& text)
0586 {
0587     d->sampleEdit->setPlainText(text);
0588 }
0589 
0590 void DFontProperties::setSampleBoxVisible(bool visible)
0591 {
0592     d->sampleEdit->setVisible(visible);
0593 }
0594 
0595 QSize DFontProperties::sizeHint(void) const
0596 {
0597     return minimumSizeHint();
0598 }
0599 
0600 void DFontProperties::enableColumn(int column, bool state)
0601 {
0602     if (column & FamilyList)
0603     {
0604         d->familyListBox->setEnabled(state);
0605     }
0606 
0607     if (column & StyleList)
0608     {
0609         d->styleListBox->setEnabled(state);
0610     }
0611 
0612     if (column & SizeList)
0613     {
0614         d->sizeListBox->setEnabled(state);
0615         d->sizeOfFont->setEnabled(state);
0616     }
0617 }
0618 
0619 void DFontProperties::makeColumnVisible(int column, bool state)
0620 {
0621     if (column & FamilyList)
0622     {
0623         d->familyListBox->setVisible(state);
0624         d->familyLabel->setVisible(state);
0625     }
0626 
0627     if (column & StyleList)
0628     {
0629         d->styleListBox->setVisible(state);
0630         d->styleLabel->setVisible(state);
0631     }
0632 
0633     if (column & SizeList)
0634     {
0635         d->sizeListBox->setVisible(state);
0636         d->sizeOfFont->setVisible(state);
0637         d->sizeLabel->setVisible(state);
0638     }
0639 
0640 }
0641 void DFontProperties::setFont(const QFont& aFont, bool onlyFixed)
0642 {
0643     d->selFont      = aFont;
0644     d->selectedSize = aFont.pointSizeF();
0645 
0646     if (d->selectedSize == -1)
0647     {
0648         d->selectedSize = QFontInfo(aFont).pointSizeF();
0649     }
0650 
0651     if (onlyFixed != d->usingFixed)
0652     {
0653         d->usingFixed = onlyFixed;
0654         d->fillFamilyListBox(d->usingFixed);
0655     }
0656 
0657     d->setupDisplay();
0658 }
0659 
0660 DFontProperties::FontDiffFlags DFontProperties::fontDiffFlags() const
0661 {
0662     FontDiffFlags diffFlags = NoFontDiffFlags;
0663 
0664     if (d->familyCheckbox && d->familyCheckbox->isChecked())
0665     {
0666         diffFlags |= FontDiffFamily;
0667     }
0668 
0669     if (d->styleCheckbox && d->styleCheckbox->isChecked())
0670     {
0671         diffFlags |= FontDiffStyle;
0672     }
0673 
0674     if (d->sizeCheckbox && d->sizeCheckbox->isChecked())
0675     {
0676         diffFlags |= FontDiffSize;
0677     }
0678 
0679     return diffFlags;
0680 }
0681 
0682 QFont DFontProperties::font() const
0683 {
0684     return d->selFont;
0685 }
0686 
0687 void DFontProperties::Private::_d_toggled_checkbox()
0688 {
0689     familyListBox->setEnabled(familyCheckbox->isChecked());
0690     styleListBox->setEnabled(styleCheckbox->isChecked());
0691     sizeListBox->setEnabled(sizeCheckbox->isChecked());
0692     sizeOfFont->setEnabled(sizeCheckbox->isChecked());
0693 }
0694 
0695 void DFontProperties::Private::_d_family_chosen_slot(const QString& family)
0696 {
0697     if (!signalsAllowed)
0698     {
0699         return;
0700     }
0701 
0702     signalsAllowed = false;
0703 
0704     QString currentFamily;
0705 
0706     if (family.isEmpty())
0707     {
0708         Q_ASSERT(familyListBox->currentItem());
0709 
0710         if (familyListBox->currentItem())
0711         {
0712             currentFamily = qtFamilies[familyListBox->currentItem()->text()];
0713         }
0714     }
0715     else
0716     {
0717         currentFamily = qtFamilies[family];
0718     }
0719 
0720     // Get the list of styles available in this family.
0721 
0722     QFontDatabase dbase;
0723     QStringList styles = dbase.styles(currentFamily);
0724 
0725     if (styles.isEmpty())
0726     {
0727         styles.append(i18nc("@info: font style", "Normal"));
0728     }
0729 
0730     // Filter style strings and add to the listbox.
0731 
0732     QString pureFamily;
0733     splitFontString(family, &pureFamily);
0734     QStringList filteredStyles;
0735     qtStyles.clear();
0736     styleIDs.clear();
0737 
0738     Q_FOREACH (const QString& style, styles)
0739     {
0740         // Sometimes the font database will report an invalid style,
0741         // that falls back to another when set.
0742         // Remove such styles, by checking set/get round-trip.
0743 
0744         QFont testFont = dbase.font(currentFamily, style, 10);
0745 
0746         if (dbase.styleString(testFont) != style)
0747         {
0748             styles.removeAll(style);
0749             continue;
0750         }
0751 
0752         QString fstyle = style;
0753 
0754         if (!filteredStyles.contains(fstyle))
0755         {
0756             filteredStyles.append(fstyle);
0757             qtStyles.insert(fstyle, style);
0758             styleIDs.insert(fstyle, styleIdentifier(testFont));
0759         }
0760     }
0761 
0762     styleListBox->clear();
0763     styleListBox->addItems(filteredStyles);
0764 
0765     // Try to set the current style in the listbox to that previous.
0766 
0767     int listPos = filteredStyles.indexOf(selectedStyle.isEmpty() ? i18nc("@info: font style", "Normal") : selectedStyle);
0768 
0769     if (listPos < 0)
0770     {
0771         // Make extra effort to have Italic selected when Oblique was chosen,
0772         // and vice versa, as that is what the user would probably want.
0773 
0774         QString styleIt = i18nc("@info: font style", "Italic");
0775         QString styleOb = i18nc("@info: font style", "Oblique");
0776 
0777         for (int i = 0 ; i < 2 ; ++i)
0778         {
0779             int pos = selectedStyle.indexOf(styleIt);
0780 
0781             if (pos >= 0)
0782             {
0783                 QString style = selectedStyle;
0784                 style.replace(pos, styleIt.length(), styleOb);
0785                 listPos       = filteredStyles.indexOf(style);
0786 
0787                 if (listPos >= 0)
0788                 {
0789                     break;
0790                 }
0791             }
0792 
0793             std::swap(styleIt, styleOb);
0794         }
0795     }
0796 
0797     styleListBox->setCurrentRow(listPos >= 0 ? listPos : 0);
0798     QString currentStyle = qtStyles[styleListBox->currentItem()->text()];
0799 
0800     // Recompute the size listbox for this family/style.
0801 
0802     qreal currentSize = setupSizeListBox(currentFamily, currentStyle);
0803     sizeOfFont->setValue(currentSize);
0804 
0805     selFont           = dbase.font(currentFamily, currentStyle, int(currentSize));
0806 
0807     if (dbase.isSmoothlyScalable(currentFamily, currentStyle) && selFont.pointSize() == floor(currentSize))
0808     {
0809         selFont.setPointSizeF(currentSize);
0810     }
0811 
0812     Q_EMIT q->fontSelected(selFont);
0813 
0814     signalsAllowed = true;
0815 }
0816 
0817 void DFontProperties::Private::_d_style_chosen_slot(const QString& style)
0818 {
0819     if (!signalsAllowed)
0820     {
0821         return;
0822     }
0823 
0824     signalsAllowed = false;
0825 
0826     QFontDatabase dbase;
0827     QString currentFamily = qtFamilies[familyListBox->currentItem()->text()];
0828     QString currentStyle;
0829 
0830     if (style.isEmpty())
0831     {
0832         currentStyle = qtStyles[styleListBox->currentItem()->text()];
0833     }
0834     else
0835     {
0836         currentStyle = qtStyles[style];
0837     }
0838 
0839     // Recompute the size listbox for this family/style.
0840 
0841     qreal currentSize = setupSizeListBox(currentFamily, currentStyle);
0842     sizeOfFont->setValue(currentSize);
0843 
0844     selFont           = dbase.font(currentFamily, currentStyle, int(currentSize));
0845 
0846     if (dbase.isSmoothlyScalable(currentFamily, currentStyle) && selFont.pointSize() == floor(currentSize))
0847     {
0848         selFont.setPointSizeF(currentSize);
0849     }
0850 
0851     Q_EMIT q->fontSelected(selFont);
0852 
0853     if (!style.isEmpty())
0854     {
0855         selectedStyle = currentStyle;
0856     }
0857 
0858     signalsAllowed = true;
0859 }
0860 
0861 void DFontProperties::Private::_d_size_chosen_slot(const QString& size)
0862 {
0863     if (!signalsAllowed)
0864     {
0865         return;
0866     }
0867 
0868     signalsAllowed = false;
0869 
0870     qreal currentSize;
0871 
0872     if (size.isEmpty())
0873     {
0874         currentSize = QLocale::system().toDouble(sizeListBox->currentItem()->text());
0875     }
0876     else
0877     {
0878         currentSize = QLocale::system().toDouble(size);
0879     }
0880 
0881     // Reset the customized size slot in the list if not needed.
0882 
0883     if (customSizeRow >= 0 && selFont.pointSizeF() != currentSize)
0884     {
0885         sizeListBox->item(customSizeRow)->setText(standardSizeAtCustom);
0886         customSizeRow = -1;
0887     }
0888 
0889     sizeOfFont->setValue(currentSize);
0890     selFont.setPointSizeF(currentSize);
0891     Q_EMIT q->fontSelected(selFont);
0892 
0893     if (!size.isEmpty())
0894     {
0895         selectedSize = currentSize;
0896     }
0897 
0898     signalsAllowed = true;
0899 }
0900 
0901 void DFontProperties::Private::_d_size_value_slot(double dval)
0902 {
0903     if (!signalsAllowed)
0904     {
0905         return;
0906     }
0907 
0908     signalsAllowed = false;
0909 
0910     // We compare with qreal, so convert for platforms where qreal != double.
0911 
0912     qreal val      = qreal(dval);
0913     QFontDatabase dbase;
0914     QString family = qtFamilies[familyListBox->currentItem()->text()];
0915     QString style  = qtStyles[styleListBox->currentItem()->text()];
0916 
0917     // Reset current size slot in list if it was customized.
0918 
0919     if ((customSizeRow >= 0) && (sizeListBox->currentRow() == customSizeRow))
0920     {
0921         sizeListBox->item(customSizeRow)->setText(standardSizeAtCustom);
0922         customSizeRow = -1;
0923     }
0924 
0925     bool canCustomize = true;
0926 
0927     // For Qt-bad-sizes workaround: skip this block unconditionally
0928 
0929     if (!dbase.isSmoothlyScalable(family, style))
0930     {
0931         // Bitmap font, allow only discrete sizes.
0932         // Determine the nearest in the direction of change.
0933 
0934         canCustomize = false;
0935         int nrows    = sizeListBox->count();
0936         int row      = sizeListBox->currentRow();
0937         int nrow;
0938 
0939         if (val - selFont.pointSizeF() > 0)
0940         {
0941             for (nrow = row + 1 ; nrow < nrows ; ++nrow)
0942             {
0943                 if (QLocale::system().toDouble(sizeListBox->item(nrow)->text()) >= val)
0944                 {
0945                     break;
0946                 }
0947             }
0948         }
0949         else
0950         {
0951             for (nrow = row - 1 ; nrow >= 0 ; --nrow)
0952             {
0953                 if (QLocale::system().toDouble(sizeListBox->item(nrow)->text()) <= val)
0954                 {
0955                     break;
0956                 }
0957             }
0958         }
0959 
0960         // Make sure the new row is not out of bounds.
0961 
0962         nrow = nrow < 0 ? 0 : nrow >= nrows ? nrows - 1 : nrow;
0963 
0964         // Get the size from the new row and set the spinbox to that size.
0965 
0966         val  = QLocale::system().toDouble(sizeListBox->item(nrow)->text());
0967         sizeOfFont->setValue(val);
0968     }
0969 
0970     // Set the current size in the size listbox.
0971 
0972     int row        = nearestSizeRow(val, canCustomize);
0973     sizeListBox->setCurrentRow(row);
0974 
0975     selectedSize   = val;
0976     selFont.setPointSizeF(val);
0977     Q_EMIT q->fontSelected(selFont);
0978 
0979     signalsAllowed = true;
0980 }
0981 
0982 void DFontProperties::Private::_d_displaySample(const QFont& font)
0983 {
0984     sampleEdit->setFont(font);
0985 }
0986 
0987 int DFontProperties::Private::nearestSizeRow(qreal val, bool customize)
0988 {
0989     qreal diff = 1000;
0990     int row    = 0;
0991 
0992     for (int r = 0 ; r < sizeListBox->count() ; ++r)
0993     {
0994         qreal cval = QLocale::system().toDouble(sizeListBox->item(r)->text());
0995 
0996         if (qAbs(cval - val) < diff)
0997         {
0998             diff = qAbs(cval - val);
0999             row  = r;
1000         }
1001     }
1002 
1003     // For Qt-bad-sizes workaround: ignore value of customize, use true
1004 
1005     if (customize && diff > 0)
1006     {
1007         customSizeRow        = row;
1008         standardSizeAtCustom = sizeListBox->item(row)->text();
1009         sizeListBox->item(row)->setText(formatFontSize(val));
1010     }
1011 
1012     return row;
1013 }
1014 
1015 qreal DFontProperties::Private::fillSizeList(const QList<qreal>& sizes_)
1016 {
1017     if (!sizeListBox)
1018     {
1019         return 0;
1020     }
1021 
1022     QList<qreal> sizes = sizes_;
1023     bool canCustomize  = false;
1024 
1025     if (sizes.count() == 0)
1026     {
1027         static const int c[] =
1028         {
1029             4,  5,  6,  7,
1030             8,  9,  10, 11,
1031             12, 13, 14, 15,
1032             16, 17, 18, 19,
1033             20, 22, 24, 26,
1034             28, 32, 48, 64,
1035             72, 80, 96, 128,
1036             0
1037         };
1038 
1039         for (int i = 0 ; c[i] ; ++i)
1040         {
1041             sizes.append(c[i]);
1042         }
1043 
1044         // Since sizes were not supplied, this is a vector font,
1045         // and size slot customization is allowed.
1046 
1047         canCustomize = true;
1048     }
1049 
1050     // Insert sizes into the listbox.
1051 
1052     sizeListBox->clear();
1053 
1054     std::sort(sizes.begin(), sizes.end());
1055 
1056     Q_FOREACH (qreal size, sizes)
1057     {
1058         sizeListBox->addItem(formatFontSize(size));
1059     }
1060 
1061     // Return the nearest to selected size.
1062     // If the font is vector, the nearest size is always same as selected,
1063     // thus size slot customization is allowed.
1064     // If the font is bitmap, the nearest size need not be same as selected,
1065     // thus size slot customization is not allowed.
1066 
1067     customSizeRow = -1;
1068     int row       = nearestSizeRow(selectedSize, canCustomize);
1069 
1070     return QLocale::system().toDouble(sizeListBox->item(row)->text());
1071 }
1072 
1073 qreal DFontProperties::Private::setupSizeListBox(const QString& family, const QString& style)
1074 {
1075     QFontDatabase dbase;
1076     QList<qreal>  sizes;
1077 
1078     if (dbase.isSmoothlyScalable(family, style))
1079     {
1080         // A vector font.
1081         //sampleEdit->setPaletteBackgroundPixmap( VectorPixmap ); // TODO
1082     }
1083     else
1084     {
1085         // A bitmap font.
1086         //sampleEdit->setPaletteBackgroundPixmap( BitmapPixmap ); // TODO
1087 
1088         QList<int> smoothSizes = dbase.smoothSizes(family, style);
1089 
1090         Q_FOREACH (int size, smoothSizes)
1091         {
1092             sizes.append(size);
1093         }
1094     }
1095 
1096     // Fill the listbox (uses default list of sizes if the given is empty).
1097     // Collect the best fitting size to selected size, to use if not smooth.
1098 
1099     qreal bestFitSize = fillSizeList(sizes);
1100 
1101     // Set the best fit size as current in the listbox if available.
1102 
1103     const QList<QListWidgetItem*> selectedSizeList = sizeListBox->findItems(formatFontSize(bestFitSize),
1104                                                                             Qt::MatchExactly);
1105     if (!selectedSizeList.isEmpty())
1106     {
1107         sizeListBox->setCurrentItem(selectedSizeList.first());
1108     }
1109 
1110     return bestFitSize;
1111 }
1112 
1113 void DFontProperties::Private::setupDisplay()
1114 {
1115     QFontDatabase dbase;
1116     QString family  = selFont.family().toLower();
1117     QString styleID = styleIdentifier(selFont);
1118     qreal size      = selFont.pointSizeF();
1119 
1120     if (size == -1)
1121     {
1122         size = QFontInfo(selFont).pointSizeF();
1123     }
1124 
1125     int numEntries, i;
1126 
1127     // Direct family match.
1128 
1129     numEntries = familyListBox->count();
1130 
1131     for (i = 0 ; i < numEntries ; ++i)
1132     {
1133         if (family == qtFamilies[familyListBox->item(i)->text()].toLower())
1134         {
1135             familyListBox->setCurrentRow(i);
1136             break;
1137         }
1138     }
1139 
1140     // 1st family fallback.
1141 
1142     if (i == numEntries)
1143     {
1144         if (family.contains(QLatin1Char('[')))
1145         {
1146             family = family.left(family.indexOf(QLatin1Char('['))).trimmed();
1147 
1148             for (i = 0 ; i < numEntries ; ++i)
1149             {
1150                 if (family == qtFamilies[familyListBox->item(i)->text()].toLower())
1151                 {
1152                     familyListBox->setCurrentRow(i);
1153                     break;
1154                 }
1155             }
1156         }
1157     }
1158 
1159     // 2nd family fallback.
1160 
1161     if (i == numEntries)
1162     {
1163         QString fallback = family + QLatin1String(" [");
1164 
1165         for (i = 0 ; i < numEntries ; ++i)
1166         {
1167             if (qtFamilies[familyListBox->item(i)->text()].toLower().startsWith(fallback))
1168             {
1169                 familyListBox->setCurrentRow(i);
1170                 break;
1171             }
1172         }
1173     }
1174 
1175     // 3rd family fallback.
1176 
1177     if (i == numEntries)
1178     {
1179         for (i = 0 ; i < numEntries ; ++i)
1180         {
1181             if (qtFamilies[familyListBox->item(i)->text()].toLower().startsWith(family))
1182             {
1183                 familyListBox->setCurrentRow(i);
1184                 break;
1185             }
1186         }
1187     }
1188 
1189     // Family fallback in case nothing matched. Otherwise, diff doesn't work
1190 
1191     if (i == numEntries)
1192     {
1193         familyListBox->setCurrentRow(0);
1194     }
1195 
1196     // By setting the current item in the family box, the available
1197     // styles and sizes for that family have been collected.
1198     // Try now to set the current items in the style and size boxes.
1199 
1200     // Set current style in the listbox.
1201 
1202     numEntries = styleListBox->count();
1203 
1204     for (i = 0 ; i < numEntries ; ++i)
1205     {
1206         if (styleID == styleIDs[styleListBox->item(i)->text()])
1207         {
1208             styleListBox->setCurrentRow(i);
1209             break;
1210         }
1211     }
1212 
1213     if (i == numEntries)
1214     {
1215         // Style not found, fallback.
1216 
1217         styleListBox->setCurrentRow(0);
1218     }
1219 
1220     // Set current size in the listbox.
1221     // If smoothly scalable, allow customizing one of the standard size slots,
1222     // otherwise just select the nearest available size.
1223 
1224     QString currentFamily = qtFamilies[familyListBox->currentItem()->text()];
1225     QString currentStyle  = qtStyles[styleListBox->currentItem()->text()];
1226     bool canCustomize     = dbase.isSmoothlyScalable(currentFamily, currentStyle);
1227     sizeListBox->setCurrentRow(nearestSizeRow(size, canCustomize));
1228 
1229     // Set current size in the spinbox.
1230 
1231     sizeOfFont->setValue(QLocale::system().toDouble(sizeListBox->currentItem()->text()));
1232 }
1233 
1234 void DFontProperties::getFontList(QStringList& list, uint fontListCriteria)
1235 {
1236     QFontDatabase dbase;
1237     QStringList lstSys(dbase.families());
1238 
1239     // if we have criteria; then check fonts before adding
1240 
1241     if (fontListCriteria)
1242     {
1243         QStringList lstFonts;
1244 
1245         for (QStringList::const_iterator it = lstSys.constBegin() ; it != lstSys.constEnd() ; ++it)
1246         {
1247             if ((fontListCriteria & FixedWidthFonts) > 0 && !dbase.isFixedPitch(*it))
1248             {
1249                 continue;
1250             }
1251 
1252             if (((fontListCriteria & (SmoothScalableFonts | ScalableFonts)) == ScalableFonts) &&
1253                  !dbase.isBitmapScalable(*it))
1254             {
1255                 continue;
1256             }
1257 
1258             if (((fontListCriteria & SmoothScalableFonts) > 0) && !dbase.isSmoothlyScalable(*it))
1259             {
1260                 continue;
1261             }
1262 
1263             lstFonts.append(*it);
1264         }
1265 
1266         if ((fontListCriteria & FixedWidthFonts) > 0)
1267         {
1268             // Fallback.. if there are no fixed fonts found, it's probably a
1269             // bug in the font server or Qt.  In this case, just use 'fixed'
1270 
1271             if (lstFonts.count() == 0)
1272             {
1273                 lstFonts.append(QLatin1String("fixed"));
1274             }
1275         }
1276 
1277         lstSys = lstFonts;
1278     }
1279 
1280     lstSys.sort();
1281 
1282     list = lstSys;
1283 }
1284 
1285 void DFontProperties::Private::setFamilyBoxItems(const QStringList& fonts)
1286 {
1287     signalsAllowed      = false;
1288     QStringList trfonts = translateFontNameList(fonts, &qtFamilies);
1289     familyListBox->clear();
1290     familyListBox->addItems(trfonts);
1291 
1292     signalsAllowed      = true;
1293 }
1294 
1295 void DFontProperties::Private::fillFamilyListBox(bool onlyFixedFonts)
1296 {
1297     QStringList fontList;
1298     getFontList(fontList, onlyFixedFonts ? FixedWidthFonts : 0);
1299     setFamilyBoxItems(fontList);
1300 }
1301 
1302 /**
1303  * Human-readable style identifiers returned by QFontDatabase::styleString()
1304  * do not always survive round trip of QFont serialization/deserialization,
1305  * causing wrong style in the style box to be highlighted when
1306  * the chooser dialog is opened. This will cause the style to be changed
1307  * when the dialog is closed and the user did not touch the style box.
1308  * Hence, construct custom style identifiers sufficient for the purpose.
1309  */
1310 QString DFontProperties::Private::styleIdentifier(const QFont& font)
1311 {
1312     const QChar comma(QLatin1Char(','));
1313 
1314     return (
1315             QString::number(font.weight())     + comma +
1316             QString::number((int)font.style()) + comma +
1317             QString::number(font.stretch())
1318            );
1319 }
1320 
1321 void DFontProperties::Private::splitFontString(const QString& name, QString* family, QString* foundry)
1322 {
1323     int p1 = name.indexOf(QLatin1Char('['));
1324 
1325     if (p1 < 0)
1326     {
1327         if (family)
1328         {
1329             *family = name.trimmed();
1330         }
1331 
1332         if (foundry)
1333         {
1334             foundry->clear();
1335         }
1336     }
1337     else
1338     {
1339         int p2 = name.indexOf(QLatin1Char(']'), p1);
1340         p2     = (p2 > p1) ? p2 : name.length();
1341 
1342         if (family)
1343         {
1344             *family = name.left(p1).trimmed();
1345         }
1346 
1347         if (foundry)
1348         {
1349             *foundry = name.mid(p1 + 1, p2 - p1 - 1).trimmed();
1350         }
1351     }
1352 }
1353 
1354 QString DFontProperties::Private::translateFontName(const QString& name)
1355 {
1356     QString family, foundry;
1357     splitFontString(name, &family, &foundry);
1358 
1359     // Obtain any regular translations for the family and foundry.
1360 
1361     QString trFamily  = QCoreApplication::translate("FontHelpers",
1362                                                     family.toUtf8().constData(),
1363                                                     "@item Font name");
1364     QString trFoundry = foundry;
1365 
1366     if (!foundry.isEmpty())
1367     {
1368         trFoundry = QCoreApplication::translate("FontHelpers",
1369                                                 foundry.toUtf8().constData(),
1370                                                 "@item Font foundry");
1371     }
1372 
1373     // Assemble full translation.
1374 
1375     QString trfont;
1376 
1377     if (foundry.isEmpty())
1378     {
1379         // i18n: Filter by which the translators can translate, or otherwise
1380         // operate on the font names not put up for regular translation.
1381 
1382         trfont = QCoreApplication::translate("FontHelpers", "%1", "@item Font name").arg(trFamily);
1383     }
1384     else
1385     {
1386         // i18n: Filter by which the translators can translate, or otherwise
1387         // operate on the font names not put up for regular translation.
1388 
1389         trfont = QCoreApplication::translate("FontHelpers", "%1 [%2]", "@item Font name [foundry]")
1390                  .arg(trFamily).arg(trFoundry);
1391     }
1392 
1393     return trfont;
1394 }
1395 
1396 QStringList DFontProperties::Private::translateFontNameList(const QStringList& names,
1397                                                             QHash<QString, QString>* trToRawNames)
1398 {
1399     // Generic fonts, in the inverse of desired order.
1400 
1401     QStringList genericNames;
1402     genericNames.append(QLatin1String("Monospace"));
1403     genericNames.append(QLatin1String("Serif"));
1404     genericNames.append(QLatin1String("Sans Serif"));
1405 
1406     // Translate fonts, but do not add generics to the list right away.
1407 
1408     QStringList             trNames;
1409     QHash<QString, QString> trMap;
1410 
1411     Q_FOREACH (const QString& name, names)
1412     {
1413         QString trName = translateFontName(name);
1414 
1415         if (!genericNames.contains(name))
1416         {
1417             trNames.append(trName);
1418         }
1419 
1420         trMap.insert(trName, name);
1421     }
1422 
1423     // Sort real fonts alphabetically.
1424 
1425     std::sort(trNames.begin(), trNames.end(), localeLessThan);
1426 
1427     // Prepend generic fonts, in the predefined order.
1428 
1429     Q_FOREACH (const QString& genericName, genericNames)
1430     {
1431         QString trGenericName = translateFontName(genericName);
1432 
1433         if (trMap.contains(trGenericName))
1434         {
1435             trNames.prepend(trGenericName);
1436         }
1437     }
1438 
1439     if (trToRawNames)
1440     {
1441         *trToRawNames = trMap;
1442     }
1443 
1444     return trNames;
1445 }
1446 
1447 } // namespace Digikam
1448 
1449 #include "moc_dfontproperties.cpp"