OSDN Git Service

remove redundant QFontInfo class
[kde/Katie.git] / src / gui / widgets / qfontcombobox.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Copyright (C) 2016 Ivailo Monev
5 **
6 ** This file is part of the QtGui module of the Katie Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 **
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.
17 **
18 ** $QT_END_LICENSE$
19 **
20 ****************************************************************************/
21
22 #include "qfontcombobox.h"
23
24 #ifndef QT_NO_FONTCOMBOBOX
25
26 #include "qstringlistmodel.h"
27 #include "qitemdelegate.h"
28 #include "qlistview.h"
29 #include "qpainter.h"
30 #include "qevent.h"
31 #include "qapplication.h"
32 #include "qfontdatabase.h"
33 #include "qcombobox_p.h"
34 #include "qdebug.h"
35
36 QT_BEGIN_NAMESPACE
37
38 class QFontFamilyDelegate : public QAbstractItemDelegate
39 {
40     Q_OBJECT
41 public:
42     explicit QFontFamilyDelegate(QObject *parent);
43
44     // painting
45     void paint(QPainter *painter,
46                const QStyleOptionViewItem &option,
47                const QModelIndex &index) const;
48
49     QSize sizeHint(const QStyleOptionViewItem &option,
50                    const QModelIndex &index) const;
51
52     QIcon truetype;
53     QIcon bitmap;
54     QFontDatabase fdb;
55 };
56
57 QFontFamilyDelegate::QFontFamilyDelegate(QObject *parent)
58     : QAbstractItemDelegate(parent)
59 {
60     truetype = QIcon::fromTheme(QLatin1String("application-x-font-ttf"));
61     bitmap = QIcon::fromTheme(QLatin1String("application-x-font-bdf"));
62 }
63
64 void QFontFamilyDelegate::paint(QPainter *painter,
65                                 const QStyleOptionViewItem &option,
66                                 const QModelIndex &index) const
67 {
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);
72     font.setFamily(text);
73
74     QRect r = option.rect;
75
76     if (option.state & QStyle::State_Selected) {
77         painter->save();
78         painter->setBrush(option.palette.highlight());
79         painter->setPen(Qt::NoPen);
80         painter->drawRect(option.rect);
81         painter->setPen(QPen(option.palette.highlightedText(), 0));
82     }
83
84     const QIcon *icon = &bitmap;
85     if (fdb.isScalable(text)) {
86         icon = &truetype;
87     }
88     QSize actualSize = icon->actualSize(r.size());
89
90     icon->paint(painter, r, Qt::AlignLeft|Qt::AlignVCenter);
91     if (option.direction == Qt::RightToLeft)
92         r.setRight(r.right() - actualSize.width() - 4);
93     else
94         r.setLeft(r.left() + actualSize.width() + 4);
95
96     QFont old = painter->font();
97     painter->setFont(font);
98
99     painter->drawText(r, Qt::AlignVCenter|Qt::AlignLeft|Qt::TextSingleLine, text);
100
101     painter->setFont(old);
102
103     if (option.state & QStyle::State_Selected)
104         painter->restore();
105
106 }
107
108 QSize QFontFamilyDelegate::sizeHint(const QStyleOptionViewItem &option,
109                                     const QModelIndex &index) const
110 {
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());
118 }
119
120
121 class QFontComboBoxPrivate : public QComboBoxPrivate
122 {
123 public:
124     inline QFontComboBoxPrivate() { filters = QFontComboBox::AllFonts; }
125
126     QFontComboBox::FontFilters filters;
127     QFont currentFont;
128
129     void _q_updateModel();
130     void _q_currentChanged(const QString &);
131
132     Q_DECLARE_PUBLIC(QFontComboBox)
133 };
134
135
136 void QFontComboBoxPrivate::_q_updateModel()
137 {
138     Q_Q(QFontComboBox);
139     const int scalableMask = (QFontComboBox::ScalableFonts | QFontComboBox::NonScalableFonts);
140     const int spacingMask = (QFontComboBox::ProportionalFonts | QFontComboBox::MonospacedFonts);
141
142     QStringListModel *m = qobject_cast<QStringListModel *>(q->model());
143     if (!m)
144         return;
145
146     QFontDatabase fdb;
147     QStringList list = fdb.families();
148     QStringList result;
149
150     int offset = 0;
151     QFont sf = fdb.font(currentFont.family(), currentFont.styleName(), currentFont.pointSize());
152
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)))
156                 continue;
157         }
158         if ((filters & spacingMask) && (filters & spacingMask) != spacingMask) {
159             if (bool(filters & QFontComboBox::MonospacedFonts) != fdb.isFixedPitch(list.at(i)))
160                 continue;
161         }
162         result += list.at(i);
163         if (list.at(i) == sf.family() || list.at(i).startsWith(sf.family() + QLatin1String(" [")))
164             offset = result.count() - 1;
165     }
166     list = result;
167
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);
175
176     if (list.isEmpty()) {
177         if (currentFont != QFont()) {
178             currentFont = QFont();
179             emit q->currentFontChanged(currentFont);
180         }
181     } else {
182         q->setCurrentIndex(offset);
183     }
184 }
185
186
187 void QFontComboBoxPrivate::_q_currentChanged(const QString &text)
188 {
189     Q_Q(QFontComboBox);
190     if (currentFont.family() != text) {
191         currentFont.setFamily(text);
192         emit q->currentFontChanged(currentFont);
193     }
194 }
195
196 /*!
197     \class QFontComboBox
198     \brief The QFontComboBox widget is a combobox that lets the user
199     select a font family.
200
201     \since 4.2
202     \ingroup basicwidgets
203
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
209     family name.
210
211     QFontComboBox is often used in toolbars, in conjunction with a
212     QComboBox for controlling the font size and two \l{QToolButton}s
213     for bold and italic.
214
215     When the user selects a new font, the currentFontChanged() signal
216     is emitted in addition to currentIndexChanged().
217
218     Call setFontFilters() to filter out certain types of fonts as e.g.
219     non scalable fonts or monospaced fonts.
220
221     \image windowsxp-fontcombobox.png Screenshot of QFontComboBox on Windows XP
222
223     \sa QComboBox, QFont, QFontMetrics, QFontDatabase, {Character Map Example}
224 */
225
226 /*!
227     \fn void QFontComboBox::setCurrentFont(const QFont &font);
228 */
229
230 /*!
231     Constructs a font combobox with the given \a parent.
232 */
233 QFontComboBox::QFontComboBox(QWidget *parent)
234     : QComboBox(*new QFontComboBoxPrivate, parent)
235 {
236     Q_D(QFontComboBox);
237     d->currentFont = font();
238     setEditable(true);
239
240     QStringListModel *m = new QStringListModel(this);
241     setModel(m);
242     setItemDelegate(new QFontFamilyDelegate(this));
243     QListView *lview = qobject_cast<QListView*>(view());
244     if (lview)
245         lview->setUniformItemSizes(true);
246
247     connect(this, SIGNAL(currentIndexChanged(QString)),
248             this, SLOT(_q_currentChanged(QString)));
249
250     d->_q_updateModel();
251 }
252
253
254 /*!
255     Destroys the combobox.
256 */
257 QFontComboBox::~QFontComboBox()
258 {
259 }
260
261 /*!
262   \enum QFontComboBox::FontFilter
263
264   This enum can be used to only show certain types of fonts in the font combo box.
265
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
271 */
272
273 /*!
274     \property QFontComboBox::fontFilters
275     \brief the filter for the combobox
276
277     By default, all fonts are listed.
278 */
279 void QFontComboBox::setFontFilters(FontFilters filters)
280 {
281     Q_D(QFontComboBox);
282     d->filters = filters;
283     d->_q_updateModel();
284 }
285
286 QFontComboBox::FontFilters QFontComboBox::fontFilters() const
287 {
288     Q_D(const QFontComboBox);
289     return d->filters;
290 }
291
292 /*!
293     \property QFontComboBox::currentFont
294     \brief the currently selected font
295
296     \sa currentFontChanged(), currentIndex, currentText
297 */
298 QFont QFontComboBox::currentFont() const
299 {
300     Q_D(const QFontComboBox);
301     return d->currentFont;
302 }
303
304 void QFontComboBox::setCurrentFont(const QFont &font)
305 {
306     Q_D(QFontComboBox);
307     if (font != d->currentFont) {
308         d->currentFont = font;
309         d->_q_updateModel();
310         if (d->currentFont == font) { //else the signal has already be emitted by _q_updateModel
311             emit currentFontChanged(d->currentFont);
312         }
313     }
314 }
315
316 /*!
317     \fn QFontComboBox::currentFontChanged(const QFont &font)
318
319     This signal is emitted whenever the current font changes, with
320     the new \a font.
321
322     \sa currentFont
323 */
324
325 /*!
326     \reimp
327 */
328 bool QFontComboBox::event(QEvent *e)
329 {
330     if (e->type() == QEvent::Resize) {
331         QListView *lview = qobject_cast<QListView*>(view());
332         if (lview)
333             lview->window()->setFixedWidth(width() * 5 / 3);
334     }
335     return QComboBox::event(e);
336 }
337
338 /*!
339     \reimp
340 */
341 QSize QFontComboBox::sizeHint() const
342 {
343     QSize sz = QComboBox::sizeHint();
344     QFontMetrics fm(font());
345     sz.setWidth(fm.width(QLatin1Char('m'))*14);
346     return sz;
347 }
348
349 QT_END_NAMESPACE
350
351 #include "moc_qfontcombobox.h"
352 #include "moc_qfontcombobox.cpp"
353
354 #endif // QT_NO_FONTCOMBOBOX