1 /****************************************************************************
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Copyright (C) 2016 Ivailo Monev
6 ** This file is part of the QtGui module of the Katie Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser
12 ** General Public License version 2.1 as published by the Free Software
13 ** Foundation and appearing in the file LICENSE.LGPL included in the
14 ** packaging of this file. Please review the following information to
15 ** ensure the GNU Lesser General Public License version 2.1 requirements
16 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
20 ****************************************************************************/
22 #include "qfontcombobox.h"
24 #ifndef QT_NO_FONTCOMBOBOX
26 #include "qstringlistmodel.h"
27 #include "qitemdelegate.h"
28 #include "qlistview.h"
31 #include "qapplication.h"
32 #include "qfontdatabase.h"
33 #include "qcombobox_p.h"
38 class QFontFamilyDelegate : public QAbstractItemDelegate
42 explicit QFontFamilyDelegate(QObject *parent);
45 void paint(QPainter *painter,
46 const QStyleOptionViewItem &option,
47 const QModelIndex &index) const;
49 QSize sizeHint(const QStyleOptionViewItem &option,
50 const QModelIndex &index) const;
57 QFontFamilyDelegate::QFontFamilyDelegate(QObject *parent)
58 : QAbstractItemDelegate(parent)
60 truetype = QIcon::fromTheme(QLatin1String("application-x-font-ttf"));
61 bitmap = QIcon::fromTheme(QLatin1String("application-x-font-bdf"));
64 void QFontFamilyDelegate::paint(QPainter *painter,
65 const QStyleOptionViewItem &option,
66 const QModelIndex &index) const
68 QString text = index.data(Qt::DisplayRole).toString();
69 QFont font(option.font);
70 QFont systemfont = fdb.font(font.family(), font.styleName(), font.pointSize());
71 font.setPointSize(systemfont.pointSize() * 3 / 2);
74 QRect r = option.rect;
76 if (option.state & QStyle::State_Selected) {
78 painter->setBrush(option.palette.highlight());
79 painter->setPen(Qt::NoPen);
80 painter->drawRect(option.rect);
81 painter->setPen(QPen(option.palette.highlightedText(), 0));
84 const QIcon *icon = &bitmap;
85 if (fdb.isScalable(text)) {
88 QSize actualSize = icon->actualSize(r.size());
90 icon->paint(painter, r, Qt::AlignLeft|Qt::AlignVCenter);
91 if (option.direction == Qt::RightToLeft)
92 r.setRight(r.right() - actualSize.width() - 4);
94 r.setLeft(r.left() + actualSize.width() + 4);
96 QFont old = painter->font();
97 painter->setFont(font);
99 painter->drawText(r, Qt::AlignVCenter|Qt::AlignLeft|Qt::TextSingleLine, text);
101 painter->setFont(old);
103 if (option.state & QStyle::State_Selected)
108 QSize QFontFamilyDelegate::sizeHint(const QStyleOptionViewItem &option,
109 const QModelIndex &index) const
111 QString text = index.data(Qt::DisplayRole).toString();
112 QFont font(option.font);
113 // font.setFamily(text);
114 QFont systemfont = fdb.font(font.family(), font.styleName(), font.pointSize());
115 font.setPointSize(systemfont.pointSize() * 3/2);
116 QFontMetrics fontMetrics(font);
117 return QSize(fontMetrics.width(text), fontMetrics.height());
121 class QFontComboBoxPrivate : public QComboBoxPrivate
124 inline QFontComboBoxPrivate() { filters = QFontComboBox::AllFonts; }
126 QFontComboBox::FontFilters filters;
129 void _q_updateModel();
130 void _q_currentChanged(const QString &);
132 Q_DECLARE_PUBLIC(QFontComboBox)
136 void QFontComboBoxPrivate::_q_updateModel()
139 const int scalableMask = (QFontComboBox::ScalableFonts | QFontComboBox::NonScalableFonts);
140 const int spacingMask = (QFontComboBox::ProportionalFonts | QFontComboBox::MonospacedFonts);
142 QStringListModel *m = qobject_cast<QStringListModel *>(q->model());
147 QStringList list = fdb.families();
151 QFont sf = fdb.font(currentFont.family(), currentFont.styleName(), currentFont.pointSize());
153 for (int i = 0; i < list.size(); ++i) {
154 if ((filters & scalableMask) && (filters & scalableMask) != scalableMask) {
155 if (bool(filters & QFontComboBox::ScalableFonts) != fdb.isScalable(list.at(i)))
158 if ((filters & spacingMask) && (filters & spacingMask) != spacingMask) {
159 if (bool(filters & QFontComboBox::MonospacedFonts) != fdb.isFixedPitch(list.at(i)))
162 result += list.at(i);
163 if (list.at(i) == sf.family() || list.at(i).startsWith(sf.family() + QLatin1String(" [")))
164 offset = result.count() - 1;
168 //we need to block the signals so that the model doesn't emit reset
169 //this prevents the current index from changing
170 //it will be updated just after this
171 ///TODO: we should finda way to avoid blocking signals and have a real update of the model
172 const bool old = m->blockSignals(true);
173 m->setStringList(list);
174 m->blockSignals(old);
176 if (list.isEmpty()) {
177 if (currentFont != QFont()) {
178 currentFont = QFont();
179 emit q->currentFontChanged(currentFont);
182 q->setCurrentIndex(offset);
187 void QFontComboBoxPrivate::_q_currentChanged(const QString &text)
190 if (currentFont.family() != text) {
191 currentFont.setFamily(text);
192 emit q->currentFontChanged(currentFont);
198 \brief The QFontComboBox widget is a combobox that lets the user
199 select a font family.
202 \ingroup basicwidgets
204 The combobox is populated with an alphabetized list of font
205 family names, such as FreeMono, FreeSans and FreeSerif.
206 Family names are displayed using the actual font when possible.
207 For fonts such as Symbol, where the name is not representable in
208 the font itself, a sample of the font is displayed next to the
211 QFontComboBox is often used in toolbars, in conjunction with a
212 QComboBox for controlling the font size and two \l{QToolButton}s
215 When the user selects a new font, the currentFontChanged() signal
216 is emitted in addition to currentIndexChanged().
218 Call setFontFilters() to filter out certain types of fonts as e.g.
219 non scalable fonts or monospaced fonts.
221 \image windowsxp-fontcombobox.png Screenshot of QFontComboBox on Windows XP
223 \sa QComboBox, QFont, QFontMetrics, QFontDatabase, {Character Map Example}
227 \fn void QFontComboBox::setCurrentFont(const QFont &font);
231 Constructs a font combobox with the given \a parent.
233 QFontComboBox::QFontComboBox(QWidget *parent)
234 : QComboBox(*new QFontComboBoxPrivate, parent)
237 d->currentFont = font();
240 QStringListModel *m = new QStringListModel(this);
242 setItemDelegate(new QFontFamilyDelegate(this));
243 QListView *lview = qobject_cast<QListView*>(view());
245 lview->setUniformItemSizes(true);
247 connect(this, SIGNAL(currentIndexChanged(QString)),
248 this, SLOT(_q_currentChanged(QString)));
255 Destroys the combobox.
257 QFontComboBox::~QFontComboBox()
262 \enum QFontComboBox::FontFilter
264 This enum can be used to only show certain types of fonts in the font combo box.
266 \value AllFonts Show all fonts
267 \value ScalableFonts Show scalable fonts
268 \value NonScalableFonts Show non scalable fonts
269 \value MonospacedFonts Show monospaced fonts
270 \value ProportionalFonts Show proportional fonts
274 \property QFontComboBox::fontFilters
275 \brief the filter for the combobox
277 By default, all fonts are listed.
279 void QFontComboBox::setFontFilters(FontFilters filters)
282 d->filters = filters;
286 QFontComboBox::FontFilters QFontComboBox::fontFilters() const
288 Q_D(const QFontComboBox);
293 \property QFontComboBox::currentFont
294 \brief the currently selected font
296 \sa currentFontChanged(), currentIndex, currentText
298 QFont QFontComboBox::currentFont() const
300 Q_D(const QFontComboBox);
301 return d->currentFont;
304 void QFontComboBox::setCurrentFont(const QFont &font)
307 if (font != d->currentFont) {
308 d->currentFont = font;
310 if (d->currentFont == font) { //else the signal has already be emitted by _q_updateModel
311 emit currentFontChanged(d->currentFont);
317 \fn QFontComboBox::currentFontChanged(const QFont &font)
319 This signal is emitted whenever the current font changes, with
328 bool QFontComboBox::event(QEvent *e)
330 if (e->type() == QEvent::Resize) {
331 QListView *lview = qobject_cast<QListView*>(view());
333 lview->window()->setFixedWidth(width() * 5 / 3);
335 return QComboBox::event(e);
341 QSize QFontComboBox::sizeHint() const
343 QSize sz = QComboBox::sizeHint();
344 QFontMetrics fm(font());
345 sz.setWidth(fm.width(QLatin1Char('m'))*14);
351 #include "moc_qfontcombobox.h"
352 #include "moc_qfontcombobox.cpp"
354 #endif // QT_NO_FONTCOMBOBOX