Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_font_family_combo_box.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 *
3 * SPDX-FileCopyrightText: 2017 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
9
10#include <QFontDatabase>
11#include <QFontComboBox>
12#include <QHBoxLayout>
13#include <QComboBox>
14#include <QAbstractItemView>
15#include <QScrollBar>
16#include <QCompleter>
17#include <klocalizedstring.h>
18#include <kis_debug.h>
19#include <QPainter>
20#include <kconfiggroup.h>
21#include <ksharedconfig.h>
22
23PinnedFontsSeparator::PinnedFontsSeparator(QAbstractItemDelegate *_default, QWidget *parent)
24 : QStyledItemDelegate(parent)
25 , m_separatorIndex(0)
26 , m_separatorAdded(false)
27 , m_defaultDelegate(_default)
28{
29}
30
31void PinnedFontsSeparator::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
32{
33 if (index.row() == m_separatorIndex && m_separatorAdded) {
34 QRect viewRect = option.rect;
35 painter->setPen(Qt::gray);
36 painter->drawLine((viewRect.topLeft() + viewRect.bottomLeft()) / 2 + QPoint(5, 0),
37 (viewRect.topRight() + viewRect.bottomRight()) / 2 - QPoint(5, 0));
38 } else {
39 m_defaultDelegate->paint(painter, option, index);
40 }
41}
42
43QSize PinnedFontsSeparator::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
44{
45 return QStyledItemDelegate::sizeHint(option, index) * 1.25;
46}
47
52
57
59 : QComboBox(parent)
60 , m_initialized(false)
61 , m_initializeFromConfig(false)
62{
63 setEditable(true);
64 completer()->setCompletionMode(QCompleter::InlineCompletion);
65 completer()->setCaseSensitivity(Qt::CaseInsensitive);
66 // The following are all helper fonts for LaTeX that no one but LaTeX would use
67 // but because many people use LaTeX, they do show up on quite a few systems.
68 m_blacklistedFonts << "bbold10" << "cmbsy10" << "cmmib10"
69 << "cmss10" << "cmex10" << "cmmi10"
70 << "cmr10" << "cmsy10" << "eufb10"
71 << "eufm10" << "eurb10" << "eurm10"
72 << "esint10" << "eufm10" << "eusb10"
73 << "eusm10" << "lasy10" << "lasyb10"
74 << "msam10" << "msbm10" << "rsfs10"
75 << "stmary10" << "wasy10" << "wasyb10";
77 QFontComboBox *temp = new QFontComboBox(this);
78 m_fontSeparator = new PinnedFontsSeparator(temp->itemDelegate(), this);
79 temp->setEnabled(true);
80 temp->hide();
82
83 KConfigGroup cfg(KSharedConfig::openConfig(), "");
84 m_pinnedFonts = cfg.readEntry<QStringList>("PinnedFonts", QStringList());
85
86 connect(this, SIGNAL(currentTextChanged(QString)), this, SLOT(slotTextChanged(QString)));
87}
88
90{
91#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
92 QFontDatabase fonts = QFontDatabase();
93#endif
94 int maxWidth = 0;
95 this->clear();
96
97 QStringList duplicateFonts;
98 QStringList filteredFonts;
99
100 if (writingSystems.isEmpty()) {
101 writingSystems.append(QFontDatabase::Any);
102 }
103
104 for (int i = 0; i < writingSystems.size(); i++) {
105#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
106 Q_FOREACH (QString family, fonts.families(writingSystems.at(i))) {
107 // if it's a private family it shouldn't be added.
108 bool addFont = !fonts.isPrivateFamily(family);
109#else
110 Q_FOREACH (QString family, QFontDatabase::families(writingSystems.at(i))) {
111 // if it's a private family it shouldn't be added.
112 bool addFont = !QFontDatabase::isPrivateFamily(family);
113#endif
114
115 if (addFont && filteredFonts.contains(family)) {
116 addFont = false;
117 }
118 if (addFont && duplicateFonts.contains(family)) {
119 addFont = false;
120 }
121 if (addFont && m_blacklistedFonts.contains(family)) {
122 addFont = false;
123 }
124#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
125 if (addFont && !fonts.isSmoothlyScalable(family)) {
126#else
127 if (addFont && !QFontDatabase::isSmoothlyScalable(family)) {
128#endif
129 addFont = false;
130 }
131
132 if (addFont) {
133 // now, check for all possible familyname+style name combinations, so we can avoid those.
134#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
135 Q_FOREACH (const QString style, fonts.styles(family)) {
136#else
137 Q_FOREACH (const QString style, QFontDatabase::styles(family)) {
138#endif
139 duplicateFonts.append(family + " " + style);
140 duplicateFonts.append(family + "_" + style);
141 }
142 filteredFonts.append(family);
143 int width = 1.5 * view()->fontMetrics()
144 .horizontalAdvance(family + " " + QFontDatabase::writingSystemSample(QFontDatabase::Any));
145 if (width > maxWidth) {
146 maxWidth = width;
147 }
148 }
149 }
150 }
151 this->addItems(filteredFonts);
152 KisFontFamilyValidator *familyValidator = new KisFontFamilyValidator(filteredFonts, this);
153 this->setValidator(familyValidator);
154 if (this->count() > this->maxVisibleItems()) {
155 maxWidth += view()->style()->pixelMetric(QStyle::PixelMetric::PM_ScrollBarExtent);
156 }
157 view()->setMinimumWidth(maxWidth);
158} // KisFontFamilyComboBox::refillComboBox
159
160void KisFontFamilyComboBox::setTopFont(const QString &family)
161{
162 if (family.isEmpty() || !m_initialized || m_pinnedFonts.contains(family)) {
163 return;
164 }
165
166 if (m_pinnedFonts.count() > 4) {
167 this->removeItem(4);
168 m_pinnedFonts.pop_back();
170 }
171
172 if (m_pinnedFonts.isEmpty()) {
173 this->insertSeparator(0);
175 }
176
177 m_pinnedFonts.push_front(family);
178 this->insertItem(0, family);
181 KConfigGroup cfg(KSharedConfig::openConfig(), "");
182
183 cfg.writeEntry("PinnedFonts", m_pinnedFonts);
184}
185
187{
188 if(m_initialized)
189 return;
190
191 m_initialized = true;
192
193 for(int i=m_pinnedFonts.count()-1; i>=0; i--){
194 this->insertItem(0, m_pinnedFonts[i]);
196 }
197
198 if(m_pinnedFonts.count() > 0){
199 this->insertSeparator(m_separatorIndex);
202 }
203
204 this->setItemDelegate(m_fontSeparator);
205}
206
207void KisFontFamilyComboBox::slotTextChanged(const QString &input) {
208 QString text = input;
209 int pos = text.size();
210 this->validator()->fixup(text);
211 if (this->validator()->validate(text, pos) == QValidator::Acceptable) {
212 setCurrentText(text);
213 Q_EMIT activated(currentIndex());
214 }
215}
216
218 : QWidget(parent)
219{
220 QHBoxLayout *layout = new QHBoxLayout(this);
221 layout->setContentsMargins(0, 0, 0, 0);
222
224 m_family->setMinimumWidth(100);
225 m_family->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
226 layout->addWidget(m_family);
227
228 m_styles = new QComboBox();
229 m_styles->setObjectName("stylesComboBox");
230 layout->addWidget(m_styles);
232 m_family->setToolTip(i18n("Font Family"));
233 m_styles->setToolTip(i18n("Font Style"));
234 connect(m_family, SIGNAL(activated(int)), this, SLOT(fontFamilyChanged()));
235 connect(m_family, SIGNAL(activated(int)), this, SLOT(fontChange()));
236 connect(m_styles, SIGNAL(activated(int)), this, SLOT(fontChange()));
237}
238
240{
241 setCurrentFamily(font.family());
242#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
243 setCurrentStyle(QFontDatabase().styleString(font));
244#else
245 setCurrentStyle(QFontDatabase::styleString(font));
246#endif
247}
248
249void KisFontComboBoxes::setCurrentFamily(const QString family)
250{
251 m_family->setCurrentText(family);
253}
254
256{
257 int index = m_styles->findText(style, Qt::MatchFixedString);
258
259 if (index < 0) {
260 index = m_styles->findText(style, Qt::MatchContains);
261 }
262
263 if (index < 0) {
264 index = m_styles->findText("regular", Qt::MatchContains);
265 }
266
267 if (index >= 0) {
268 m_styles->setCurrentIndex(index);
269 }
270}
271
273{
274 return m_family->currentText();
275}
276
278{
279 return m_styles->currentText();
280}
281
282QFont KisFontComboBoxes::currentFont(int pointSize) const
283{
284#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
285 return QFontDatabase().font(m_family->currentText(), m_styles->currentText(), pointSize);
286#else
287 return QFontDatabase::font(m_family->currentText(), m_styles->currentText(), pointSize);
288#endif
289}
290
292{
293 KisFontFamilyComboBox *cmb = qobject_cast<KisFontFamilyComboBox *>(m_family);
294 cmb->refillComboBox(writingSystems);
295}
296
298{
299 QString currentText = m_styles->currentText();
300#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
301 QFontDatabase fonts;
302#endif
303 const QString family = m_family->currentText();
304 int maxWidth = 0;
305 m_styles->clear();
306 QStringList styles;
307
308 KisFontFamilyComboBox *cmb = qobject_cast<KisFontFamilyComboBox *>(m_family);
309 cmb->setTopFont(family);
310
311#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
312 if (fonts.styles(family).isEmpty()) {
313#else
314 if (QFontDatabase::styles(family).isEmpty()) {
315#endif
316 styles.append("Normal");
317 }
318
319#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
320 Q_FOREACH (const QString style, fonts.styles(family)) {
321 int b = fonts.weight(family, style);
322#else
323 Q_FOREACH (const QString style, QFontDatabase::styles(family)) {
324 int b = QFontDatabase::weight(family, style);
325#endif
326 int bindex = 0;
327 for (int i = 0; i < styles.size(); i++) {
328#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
329 if (b > fonts.weight(family, styles.at(i))) {
330#else
331 if (b > QFontDatabase::weight(family, styles.at(i))) {
332#endif
333 bindex = i;
334 }
335 }
336 if (!styles.contains(style)) {
337 styles.insert(bindex, style);
338 maxWidth = qMax(m_styles->view()->fontMetrics().horizontalAdvance(style + " "), maxWidth);
339 }
340 }
341 m_styles->addItems(styles);
342 if (m_styles->count() > m_styles->maxVisibleItems()) {
343 maxWidth += m_styles->view()->style()->pixelMetric(QStyle::PixelMetric::PM_ScrollBarExtent);
344 }
345 m_styles->view()->setMinimumWidth(maxWidth);
346 if (styles.contains(currentText)) {
347 m_styles->setCurrentText(currentText);
348 }
349} // KisFontComboBoxes::fontFamilyChanged
350
352{
353 Q_EMIT fontChanged(currentFont(10).toString());
354}
355
357{
358 KisFontFamilyComboBox *cmb = qobject_cast<KisFontFamilyComboBox *>(m_family);
359 cmb->setInitialized();
360}
QList< QString > QStringList
void refillComboBox(QVector< QFontDatabase::WritingSystem > writingSystems=QVector< QFontDatabase::WritingSystem >())
KisFontComboBoxes(QWidget *parent=0)
void setCurrentFamily(const QString family)
QFont currentFont(int pointSize=10) const
currentFont the current QFont from both family and style combinations
void fontChanged(QString)
void setCurrentFont(QFont font)
setCurrentFont sets the style and font comboboxes appropriately.
void setCurrentStyle(QString style)
The KisFontFamilyComboBox class A QCombobox that limits the amount of fonts it contains....
void setTopFont(const QString &family)
KisFontFamilyComboBox(QWidget *parent=0)
void slotTextChanged(const QString &input)
PinnedFontsSeparator * m_fontSeparator
void refillComboBox(QVector< QFontDatabase::WritingSystem > writingSystems=QVector< QFontDatabase::WritingSystem >())
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
QAbstractItemDelegate * m_defaultDelegate
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
PinnedFontsSeparator(QAbstractItemDelegate *_default, QWidget *parent=nullptr)