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 QFontDatabase fonts = QFontDatabase();
92 int maxWidth = 0;
93 this->clear();
94
95 QStringList duplicateFonts;
96 QStringList filteredFonts;
97
98 if (writingSystems.isEmpty()) {
99 writingSystems.append(QFontDatabase::Any);
100 }
101
102 for (int i = 0; i < writingSystems.size(); i++) {
103 Q_FOREACH (QString family, fonts.families(writingSystems.at(i))) {
104 // if it's a private family it shouldn't be added.
105 bool addFont = !fonts.isPrivateFamily(family);
106
107 if (addFont && filteredFonts.contains(family)) {
108 addFont = false;
109 }
110 if (addFont && duplicateFonts.contains(family)) {
111 addFont = false;
112 }
113 if (addFont && m_blacklistedFonts.contains(family)) {
114 addFont = false;
115 }
116 if (addFont && !fonts.isSmoothlyScalable(family)) {
117 addFont = false;
118 }
119
120 if (addFont) {
121 // now, check for all possible familyname+style name combinations, so we can avoid those.
122 Q_FOREACH (const QString style, fonts.styles(family)) {
123 duplicateFonts.append(family + " " + style);
124 duplicateFonts.append(family + "_" + style);
125 }
126 filteredFonts.append(family);
127 int width = 1.5 * view()->fontMetrics()
128 .horizontalAdvance(family + " " + fonts.writingSystemSample(QFontDatabase::Any));
129 if (width > maxWidth) {
130 maxWidth = width;
131 }
132 }
133 }
134 }
135 this->addItems(filteredFonts);
136 KisFontFamilyValidator *familyValidator = new KisFontFamilyValidator(filteredFonts, this);
137 this->setValidator(familyValidator);
138 if (this->count() > this->maxVisibleItems()) {
139 maxWidth += view()->style()->pixelMetric(QStyle::PixelMetric::PM_ScrollBarExtent);
140 }
141 view()->setMinimumWidth(maxWidth);
142} // KisFontFamilyComboBox::refillComboBox
143
144void KisFontFamilyComboBox::setTopFont(const QString &family)
145{
146 if (family.isEmpty() || !m_initialized || m_pinnedFonts.contains(family)) {
147 return;
148 }
149
150 if (m_pinnedFonts.count() > 4) {
151 this->removeItem(4);
152 m_pinnedFonts.pop_back();
154 }
155
156 if (m_pinnedFonts.isEmpty()) {
157 this->insertSeparator(0);
159 }
160
161 m_pinnedFonts.push_front(family);
162 this->insertItem(0, family);
165 KConfigGroup cfg(KSharedConfig::openConfig(), "");
166
167 cfg.writeEntry("PinnedFonts", m_pinnedFonts);
168}
169
171{
172 if(m_initialized)
173 return;
174
175 m_initialized = true;
176
177 for(int i=m_pinnedFonts.count()-1; i>=0; i--){
178 this->insertItem(0, m_pinnedFonts[i]);
180 }
181
182 if(m_pinnedFonts.count() > 0){
183 this->insertSeparator(m_separatorIndex);
186 }
187
188 this->setItemDelegate(m_fontSeparator);
189}
190
191void KisFontFamilyComboBox::slotTextChanged(const QString &input) {
192 QString text = input;
193 int pos = text.size();
194 this->validator()->fixup(text);
195 if (this->validator()->validate(text, pos) == QValidator::Acceptable) {
196 setCurrentText(text);
197 Q_EMIT activated(currentIndex());
198 }
199}
200
202 : QWidget(parent)
203{
204 QHBoxLayout *layout = new QHBoxLayout(this);
205 layout->setContentsMargins(0, 0, 0, 0);
206
208 m_family->setMinimumWidth(100);
209 m_family->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
210 layout->addWidget(m_family);
211
212 m_styles = new QComboBox();
213 m_styles->setObjectName("stylesComboBox");
214 layout->addWidget(m_styles);
216 m_family->setToolTip(i18n("Font Family"));
217 m_styles->setToolTip(i18n("Font Style"));
218 connect(m_family, SIGNAL(activated(int)), this, SLOT(fontFamilyChanged()));
219 connect(m_family, SIGNAL(activated(int)), this, SLOT(fontChange()));
220 connect(m_styles, SIGNAL(activated(int)), this, SLOT(fontChange()));
221}
222
224{
225 setCurrentFamily(font.family());
226 setCurrentStyle(QFontDatabase().styleString(font));
227}
228
229void KisFontComboBoxes::setCurrentFamily(const QString family)
230{
231 m_family->setCurrentText(family);
233}
234
236{
237 int index = m_styles->findText(style, Qt::MatchFixedString);
238
239 if (index < 0) {
240 index = m_styles->findText(style, Qt::MatchContains);
241 }
242
243 if (index < 0) {
244 index = m_styles->findText("regular", Qt::MatchContains);
245 }
246
247 if (index >= 0) {
248 m_styles->setCurrentIndex(index);
249 }
250}
251
253{
254 return m_family->currentText();
255}
256
258{
259 return m_styles->currentText();
260}
261
262QFont KisFontComboBoxes::currentFont(int pointSize) const
263{
264 return QFontDatabase().font(m_family->currentText(), m_styles->currentText(), pointSize);
265}
266
268{
269 KisFontFamilyComboBox *cmb = qobject_cast<KisFontFamilyComboBox *>(m_family);
270 cmb->refillComboBox(writingSystems);
271}
272
274{
275 QString currentText = m_styles->currentText();
276 QFontDatabase fonts;
277 const QString family = m_family->currentText();
278 int maxWidth = 0;
279 m_styles->clear();
280 QStringList styles;
281
282 KisFontFamilyComboBox *cmb = qobject_cast<KisFontFamilyComboBox *>(m_family);
283 cmb->setTopFont(family);
284
285 if (fonts.styles(family).isEmpty()) {
286 styles.append("Normal");
287 }
288
289 Q_FOREACH (const QString style, fonts.styles(family)) {
290 int b = fonts.weight(family, style);
291 int bindex = 0;
292 for (int i = 0; i < styles.size(); i++) {
293 if (b > fonts.weight(family, styles.at(i))) {
294 bindex = i;
295 }
296 }
297 if (!styles.contains(style)) {
298 styles.insert(bindex, style);
299 maxWidth = qMax(m_styles->view()->fontMetrics().horizontalAdvance(style + " "), maxWidth);
300 }
301 }
302 m_styles->addItems(styles);
303 if (m_styles->count() > m_styles->maxVisibleItems()) {
304 maxWidth += m_styles->view()->style()->pixelMetric(QStyle::PixelMetric::PM_ScrollBarExtent);
305 }
306 m_styles->view()->setMinimumWidth(maxWidth);
307 if (styles.contains(currentText)) {
308 m_styles->setCurrentText(currentText);
309 }
310} // KisFontComboBoxes::fontFamilyChanged
311
313{
314 Q_EMIT fontChanged(currentFont(10).toString());
315}
316
318{
319 KisFontFamilyComboBox *cmb = qobject_cast<KisFontFamilyComboBox *>(m_family);
320 cmb->setInitialized();
321}
QList< QString > QStringList
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
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)