1
// KDE Display fonts setup tab
3
// Copyright (c) Mark Donohoe 1997
7
// Ported to kcontrol2 by Geert Jansen.
9
#include <config-workspace.h>
15
#include <QPushButton>
16
#include <QtCore/QSettings>
22
#include <QGridLayout>
23
#include <QHBoxLayout>
24
#include <QVBoxLayout>
25
#include <QFormLayout>
28
#include <kacceleratormanager.h>
29
#include <kapplication.h>
30
#include <kglobalsettings.h>
31
#include <kmessagebox.h>
32
#include <knuminput.h>
35
#include <kstandarddirs.h>
38
#include "../krdb/krdb.h"
47
#ifdef FT_LCD_FILTER_H
48
#include FT_FREETYPE_H
49
#include FT_LCD_FILTER_H
57
#include <KPluginFactory>
66
static const char * const aa_rgb_xpm[]={
83
static const char * const aa_bgr_xpm[]={
100
static const char * const aa_vrgb_xpm[]={
117
static const char * const aa_vbgr_xpm[]={
135
static const char* const * const aaPixmaps[]={ aa_rgb_xpm, aa_bgr_xpm, aa_vrgb_xpm, aa_vbgr_xpm };
137
/**** DLL Interface ****/
138
K_PLUGIN_FACTORY(FontFactory, registerPlugin<KFonts>(); )
139
K_EXPORT_PLUGIN(FontFactory("kcmfonts"))
141
/**** FontUseItem ****/
143
FontUseItem::FontUseItem(
149
const QFont &default_fnt,
152
: KFontRequester(parent, f),
156
_default(default_fnt)
158
KAcceleratorManager::setNoAccel( this );
163
void FontUseItem::setDefault()
165
setFont( _default, isFixedOnly() );
168
void FontUseItem::readFont()
172
bool deleteme = false;
173
if (_rcfile.isEmpty())
174
config = KGlobal::config().data();
177
config = new KConfig(_rcfile);
181
KConfigGroup group(config, _rcgroup);
182
QFont tmpFnt(_default);
183
setFont( group.readEntry(_rckey, tmpFnt), isFixedOnly() );
184
if (deleteme) delete config;
187
void FontUseItem::writeFont()
191
if (_rcfile.isEmpty()) {
192
config = KGlobal::config().data();
193
KConfigGroup(config, _rcgroup).writeEntry(_rckey, font(), KConfig::Normal|KConfig::Global);
195
config = new KConfig(KStandardDirs::locateLocal("config", _rcfile));
196
KConfigGroup(config, _rcgroup).writeEntry(_rckey, font());
202
void FontUseItem::applyFontDiff( const QFont &fnt, int fontDiffFlags )
204
QFont _font( font() );
206
if (fontDiffFlags & KFontChooser::FontDiffSize) {
207
_font.setPointSizeF( fnt.pointSizeF() );
209
if (fontDiffFlags & KFontChooser::FontDiffFamily) {
210
if (!isFixedOnly() || QFontInfo(fnt).fixedPitch()) _font.setFamily( fnt.family() );
212
if (fontDiffFlags & KFontChooser::FontDiffStyle) {
213
_font.setWeight( fnt.weight() );
214
_font.setStyle( fnt.style() );
215
_font.setUnderline( fnt.underline() );
218
setFont( _font, isFixedOnly() );
221
/**** FontAASettings ****/
222
#ifdef HAVE_FONTCONFIG
223
FontAASettings::FontAASettings(QWidget *parent)
227
setObjectName( "FontAASettings" );
229
setCaption( i18n("Configure Anti-Alias Settings") );
230
setButtons( Ok|Cancel );
232
QWidget *mw=new QWidget(this);
233
QFormLayout *layout=new QFormLayout(mw);
234
layout->setMargin(0);
236
excludeRange=new QCheckBox(i18n("E&xclude range:"), mw);
237
QHBoxLayout *rangeLayout = new QHBoxLayout();
238
excludeFrom=new KDoubleNumInput(0, 72, 8.0, mw, 1, 1);
239
excludeFrom->setSuffix(i18n(" pt"));
240
rangeLayout->addWidget(excludeFrom);
241
excludeToLabel=new QLabel(i18n(" to "), mw);
242
rangeLayout->addWidget(excludeToLabel);
243
excludeTo=new KDoubleNumInput(0, 72, 15.0, mw, 1, 1);
244
excludeTo->setSuffix(i18n(" pt"));
245
rangeLayout->addWidget(excludeTo);
246
layout->addRow(excludeRange, rangeLayout);
248
QString subPixelWhatsThis = i18n("<p>If you have a TFT or LCD screen you"
249
" can further improve the quality of displayed fonts by selecting"
250
" this option.<br />Sub-pixel rendering is also known as ClearType(tm).<br />"
251
" In order for sub-pixel rendering to"
252
" work correctly you need to know how the sub-pixels of your display"
254
" <p>On TFT or LCD displays a single pixel is actually composed of"
255
" three sub-pixels, red, green and blue. Most displays"
256
" have a linear ordering of RGB sub-pixel, some have BGR.<br />"
257
" This feature does not work with CRT monitors.</p>" );
259
useSubPixel=new QCheckBox(i18n("&Use sub-pixel rendering:"), mw);
260
useSubPixel->setWhatsThis( subPixelWhatsThis );
262
subPixelType=new QComboBox(mw);
263
layout->addRow(useSubPixel, subPixelType);
265
subPixelType->setEditable(false);
266
subPixelType->setWhatsThis( subPixelWhatsThis );
268
for(int t=KXftConfig::SubPixel::None+1; t<=KXftConfig::SubPixel::Vbgr; ++t)
269
subPixelType->addItem(QPixmap(aaPixmaps[t-1]), i18n(KXftConfig::description((KXftConfig::SubPixel::Type)t).toUtf8()));
271
QLabel *hintingLabel=new QLabel(i18n("Hinting style: "), mw);
272
hintingStyle=new QComboBox(mw);
273
hintingStyle->setEditable(false);
274
layout->addRow(hintingLabel, hintingStyle);
275
for(int s=KXftConfig::Hint::NotSet+1; s<=KXftConfig::Hint::Full; ++s)
276
hintingStyle->addItem(i18n(KXftConfig::description((KXftConfig::Hint::Style)s).toUtf8()));
278
QString hintingText(i18n("Hinting is a process used to enhance the quality of fonts at small sizes."));
279
hintingStyle->setWhatsThis( hintingText);
280
hintingLabel->setWhatsThis( hintingText);
285
connect(excludeRange, SIGNAL(toggled(bool)), SLOT(changed()));
286
connect(useSubPixel, SIGNAL(toggled(bool)), SLOT(changed()));
287
connect(excludeFrom, SIGNAL(valueChanged(double)), SLOT(changed()));
288
connect(excludeTo, SIGNAL(valueChanged(double)), SLOT(changed()));
289
connect(subPixelType, SIGNAL(activated(const QString &)), SLOT(changed()));
290
connect(hintingStyle, SIGNAL(activated(const QString &)), SLOT(changed()));
293
bool FontAASettings::load()
298
if(xft.getExcludeRange(from, to))
299
excludeRange->setChecked(true);
302
excludeRange->setChecked(false);
307
excludeFrom->setValue(from);
308
excludeTo->setValue(to);
310
KXftConfig::SubPixel::Type spType;
312
if(!xft.getSubPixelType(spType) || KXftConfig::SubPixel::None==spType)
313
useSubPixel->setChecked(false);
316
int idx=getIndex(spType);
320
useSubPixel->setChecked(true);
321
subPixelType->setCurrentIndex(idx);
324
useSubPixel->setChecked(false);
327
KXftConfig::Hint::Style hStyle;
329
if(!xft.getHintStyle(hStyle) || KXftConfig::Hint::NotSet==hStyle)
331
KConfig kglobals("kdeglobals", KConfig::NoGlobals);
333
hStyle=KXftConfig::Hint::Medium;
334
xft.setHintStyle(hStyle);
335
xft.apply(); // Save this setting
336
KConfigGroup(&kglobals, "General").writeEntry("XftHintStyle", KXftConfig::toStr(hStyle));
338
runRdb(KRdbExportXftSettings | KRdbExportGtkTheme);
341
hintingStyle->setCurrentIndex(getIndex(hStyle));
345
return xft.getAntiAliasing();
348
bool FontAASettings::save( bool useAA )
351
KConfig kglobals("kdeglobals", KConfig::NoGlobals);
352
KConfigGroup grp(&kglobals, "General");
354
xft.setAntiAliasing( useAA );
356
if(excludeRange->isChecked())
357
xft.setExcludeRange(excludeFrom->value(), excludeTo->value());
359
xft.setExcludeRange(0, 0);
361
KXftConfig::SubPixel::Type spType(useSubPixel->isChecked()
363
: KXftConfig::SubPixel::None);
365
xft.setSubPixelType(spType);
366
grp.writeEntry("XftSubPixel", KXftConfig::toStr(spType));
367
grp.writeEntry("XftAntialias", useAA);
370
KXftConfig::Hint::Style hStyle(getHintStyle());
372
xft.setHintStyle(hStyle);
374
QString hs(KXftConfig::toStr(hStyle));
376
if(!hs.isEmpty() && hs!=grp.readEntry("XftHintStyle"))
378
grp.writeEntry("XftHintStyle", hs);
391
void FontAASettings::defaults()
393
excludeRange->setChecked(true);
394
excludeFrom->setValue(8.0);
395
excludeTo->setValue(15.0);
396
useSubPixel->setChecked(false);
397
hintingStyle->setCurrentIndex(getIndex(KXftConfig::Hint::Medium));
401
int FontAASettings::getIndex(KXftConfig::SubPixel::Type spType)
406
for(index=0; index<subPixelType->count(); ++index)
407
if(subPixelType->itemText(index)==i18n(KXftConfig::description(spType).toUtf8()))
416
KXftConfig::SubPixel::Type FontAASettings::getSubPixelType()
420
for(t=KXftConfig::SubPixel::None; t<=KXftConfig::SubPixel::Vbgr; ++t)
421
if(subPixelType->currentText()==i18n(KXftConfig::description((KXftConfig::SubPixel::Type)t).toUtf8()))
422
return (KXftConfig::SubPixel::Type)t;
424
return KXftConfig::SubPixel::None;
427
int FontAASettings::getIndex(KXftConfig::Hint::Style hStyle)
432
for(index=0; index<hintingStyle->count(); ++index)
433
if(hintingStyle->itemText(index)==i18n(KXftConfig::description(hStyle).toUtf8()))
443
KXftConfig::Hint::Style FontAASettings::getHintStyle()
447
for(s=KXftConfig::Hint::NotSet; s<=KXftConfig::Hint::Full; ++s)
448
if(hintingStyle->currentText()==i18n(KXftConfig::description((KXftConfig::Hint::Style)s).toUtf8()))
449
return (KXftConfig::Hint::Style)s;
451
return KXftConfig::Hint::Medium;
454
void FontAASettings::enableWidgets()
456
excludeFrom->setEnabled(excludeRange->isChecked());
457
excludeTo->setEnabled(excludeRange->isChecked());
458
excludeToLabel->setEnabled(excludeRange->isChecked());
459
subPixelType->setEnabled(useSubPixel->isChecked());
460
#ifdef FT_LCD_FILTER_H
461
static int ft_has_subpixel = -1;
462
if( ft_has_subpixel == -1 ) {
463
FT_Library ftLibrary;
464
if(FT_Init_FreeType(&ftLibrary) == 0) {
465
ft_has_subpixel = ( FT_Library_SetLcdFilter(ftLibrary, FT_LCD_FILTER_DEFAULT )
466
== FT_Err_Unimplemented_Feature ) ? 0 : 1;
467
FT_Done_FreeType(ftLibrary);
470
useSubPixel->setEnabled(ft_has_subpixel);
471
subPixelType->setEnabled(ft_has_subpixel);
476
void FontAASettings::changed()
478
#ifdef HAVE_FONTCONFIG
484
#ifdef HAVE_FONTCONFIG
485
int FontAASettings::exec()
487
int i=KDialog::exec();
490
load(); // Reset settings...
492
return i && changesMade;
498
KFonts::KFonts(QWidget *parent, const QVariantList &args)
499
: KCModule(FontFactory::componentData(), parent, args)
501
QStringList nameGroupKeyRc;
504
<< i18nc("font usage", "General") << "General" << "font" << ""
505
<< i18nc("font usage", "Fixed width") << "General" << "fixed" << ""
506
<< i18nc("font usage", "Small") << "General" << "smallestReadableFont" << ""
507
<< i18nc("font usage", "Toolbar") << "General" << "toolBarFont" << ""
508
<< i18nc("font usage", "Menu") << "General" << "menuFont" << ""
509
<< i18nc("font usage", "Window title") << "WM" << "activeFont" << ""
510
<< i18nc("font usage", "Taskbar") << "General" << "taskbarFont" << ""
511
<< i18nc("font usage", "Desktop") << "General" << "desktopFont" << "";
513
QList<QFont> defaultFontList;
515
// NOTE: keep in sync with kdelibs/kdeui/kernel/kglobalsettings.cpp
517
QFont f0("Sans Serif", 9); // general/menu/desktop
518
QFont f1("Monospace", 9);
519
QFont f2("Sans Serif", 8); // toolbar
520
QFont f3("Sans Serif", 8); // window title
521
QFont f4("Sans Serif", 9); // taskbar
522
QFont f5("Sans Serif", 8); // smallestReadableFont
524
defaultFontList << f0 << f1 << f5 << f2 << f0 << f3 << f4 << f0;
526
QList<bool> fixedList;
538
QStringList quickHelpList;
541
<< i18n("Used for normal text (e.g. button labels, list items).")
542
<< i18n("A non-proportional font (i.e. typewriter font).")
543
<< i18n("Smallest font that is still readable well.")
544
<< i18n("Used to display text beside toolbar icons.")
545
<< i18n("Used by menu bars and popup menus.")
546
<< i18n("Used by the window titlebar.")
547
<< i18n("Used by the taskbar.")
548
<< i18n("Used for desktop icons.");
550
QVBoxLayout * layout = new QVBoxLayout(this );
551
layout->setMargin(0);
553
QGridLayout * fontUseLayout = new QGridLayout( );
554
layout->addLayout( fontUseLayout );
555
fontUseLayout->setColumnStretch(0, 0);
556
fontUseLayout->setColumnStretch(1, 1);
557
fontUseLayout->setColumnStretch(2, 0);
559
QList<QFont>::ConstIterator defaultFontIt(defaultFontList.begin());
560
QList<bool>::ConstIterator fixedListIt(fixedList.begin());
561
QStringList::ConstIterator quickHelpIt(quickHelpList.begin());
562
QStringList::ConstIterator it(nameGroupKeyRc.begin());
564
unsigned int count = 0;
566
while (it != nameGroupKeyRc.constEnd()) {
568
QString name = *it; it++;
569
QString group = *it; it++;
570
QString key = *it; it++;
571
QString file = *it; it++;
584
fontUseList.append(i);
585
connect(i, SIGNAL(fontSelected(const QFont &)), SLOT(fontSelected()));
587
QLabel * fontUse = new QLabel(i18nc("Font role", "%1: ", name), this);
588
fontUse->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
589
fontUse->setWhatsThis( *quickHelpIt++);
591
fontUseLayout->addWidget(fontUse, count, 0);
592
fontUseLayout->addWidget(i, count, 1);
597
QHBoxLayout *hblay = new QHBoxLayout();
598
layout->addLayout(hblay);
600
QPushButton * fontAdjustButton = new QPushButton(i18n("Ad&just All Fonts..."), this);
601
fontAdjustButton->setWhatsThis( i18n("Click to change all fonts"));
602
hblay->addWidget( fontAdjustButton );
603
connect(fontAdjustButton, SIGNAL(clicked()), SLOT(slotApplyFontDiff()));
605
layout->addSpacing(KDialog::spacingHint());
607
QGridLayout* lay = new QGridLayout();
608
layout->addLayout(lay);
609
lay->setColumnStretch( 3, 10 );
611
#ifdef HAVE_FONTCONFIG
612
label = new QLabel( i18n( "Use a&nti-aliasing:" ), this );
613
label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
614
lay->addWidget( label, 0, 0 );
615
cbAA = new QComboBox( this );
616
cbAA->insertItem( AAEnabled, i18nc( "Use anti-aliasing", "Enabled" )); // change AASetting type if order changes
617
cbAA->insertItem( AASystem, i18nc( "Use anti-aliasing", "System Settings" ));
618
cbAA->insertItem( AADisabled, i18nc( "Use anti-aliasing", "Disabled" ));
619
cbAA->setWhatsThis( i18n("If this option is selected, KDE will smooth the edges of curves in "
621
aaSettingsButton = new QPushButton( i18n( "Configure..." ), this);
622
connect(aaSettingsButton, SIGNAL(clicked()), SLOT(slotCfgAa()));
623
label->setBuddy( cbAA );
624
lay->addWidget( cbAA, 0, 1 );
625
lay->addWidget( aaSettingsButton, 0, 2 );
626
connect(cbAA, SIGNAL(activated(int)), SLOT(slotUseAntiAliasing()));
628
label = new QLabel( i18n( "Force fonts DPI:" ), this );
629
label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
630
lay->addWidget( label, 1, 0 );
631
comboForceDpi = new QComboBox( this );
632
label->setBuddy( comboForceDpi );
633
comboForceDpi->insertItem( DPINone, i18nc("Force fonts DPI", "Disabled" )); // change DPISetti ng type if order changes
634
comboForceDpi->insertItem( DPI96, i18n( "96 DPI" ));
635
comboForceDpi->insertItem( DPI120, i18n( "120 DPI" ));
636
QString whatsthis = i18n(
637
"<p>This option forces a specific DPI value for fonts. It may be useful"
638
" when the real DPI of the hardware is not detected properly and it"
639
" is also often misused when poor quality fonts are used that do not"
640
" look well with DPI values other than 96 or 120 DPI.</p>"
641
"<p>The use of this option is generally discouraged. For selecting proper DPI"
642
" value a better option is explicitly configuring it for the whole X server if"
643
" possible (e.g. DisplaySize in xorg.conf or adding <i>-dpi value</i> to"
644
" ServerLocalArgs= in $KDEDIR/share/config/kdm/kdmrc). When fonts do not render"
645
" properly with real DPI value better fonts should be used or configuration"
646
" of font hinting should be checked.</p>" );
647
comboForceDpi->setWhatsThis(whatsthis);
648
connect( comboForceDpi, SIGNAL( activated( int )), SLOT( changed()));
649
lay->addWidget( comboForceDpi, 1, 1 );
651
layout->addStretch(1);
653
#ifdef HAVE_FONTCONFIG
654
aaSettings=new FontAASettings(this);
661
QList<FontUseItem *>::Iterator it(fontUseList.begin()),
662
end(fontUseList.end());
669
void KFonts::fontSelected()
674
void KFonts::defaults()
676
for ( int i = 0; i < (int) fontUseList.count(); i++ )
677
fontUseList.at( i )->setDefault();
679
#ifdef HAVE_FONTCONFIG
681
cbAA->setCurrentIndex( useAA );
682
aaSettings->defaults();
684
comboForceDpi->setCurrentIndex( DPINone );
690
QList<FontUseItem *>::Iterator it(fontUseList.begin()),
691
end(fontUseList.end());
696
#ifdef HAVE_FONTCONFIG
697
useAA_original = useAA = aaSettings->load() ? AAEnabled : AADisabled;
698
cbAA->setCurrentIndex( useAA );
701
KConfig _cfgfonts( "kcmfonts" );
702
KConfigGroup cfgfonts(&_cfgfonts, "General");
703
int dpicfg = cfgfonts.readEntry( "forceFontDPI", 0 );
704
DPISetting dpi = dpicfg == 120 ? DPI120 : dpicfg == 96 ? DPI96 : DPINone;
705
comboForceDpi->setCurrentIndex( dpi );
707
#ifdef HAVE_FONTCONFIG
708
if( cfgfonts.readEntry( "dontChangeAASettings", true )) {
709
useAA_original = useAA = AASystem;
710
cbAA->setCurrentIndex( useAA );
712
aaSettingsButton->setEnabled( cbAA->currentIndex() == AAEnabled );
720
QList<FontUseItem *>::Iterator it(fontUseList.begin()),
721
end(fontUseList.end());
726
KGlobal::config()->sync();
728
KConfig _cfgfonts( "kcmfonts" );
729
KConfigGroup cfgfonts(&_cfgfonts, "General");
730
DPISetting dpi = static_cast< DPISetting >( comboForceDpi->currentIndex());
731
const int dpi2value[] = { 0, 96, 120 };
732
cfgfonts.writeEntry( "forceFontDPI", dpi2value[ dpi ] );
733
#ifdef HAVE_FONTCONFIG
734
cfgfonts.writeEntry( "dontChangeAASettings", cbAA->currentIndex() == AASystem );
737
// if the setting is reset in the module, remove the dpi value,
738
// otherwise don't explicitly remove it and leave any possible system-wide value
739
if( dpi == DPINone && dpi_original != DPINone ) {
741
proc << "xrdb" << "-quiet" << "-remove" << "-nocpp";
743
if (proc.waitForStarted()) {
744
proc.write( QByteArray( "Xft.dpi\n" ) );
745
proc.closeWriteChannel();
746
proc.waitForFinished();
752
KConfig config( QDir::homePath() + "/.kderc", KConfig::SimpleConfig);
753
KConfigGroup grp(&config, "General");
755
for(it=fontUseList.begin(); it!=end; ++it) {
756
if("font"==(*it)->rcKey())
757
QSettings().setValue("/qt/font", (*it)->font().toString());
758
kDebug(1208) << "write entry " << (*it)->rcKey();
759
grp.writeEntry( (*it)->rcKey(), (*it)->font() );
764
KGlobalSettings::self()->emitChange(KGlobalSettings::FontChanged);
766
kapp->processEvents(); // Process font change ourselves
769
// Don't overwrite global settings unless explicitly asked for - e.g. the system
770
// fontconfig setup may be much more complex than this module can provide.
771
// TODO: With AASystem the changes already made by this module should be reverted somehow.
772
#ifdef HAVE_FONTCONFIG
774
if( cbAA->currentIndex() != AASystem )
775
aaSave = aaSettings->save( useAA == AAEnabled );
777
if( aaSave || (useAA != useAA_original) || dpi != dpi_original) {
778
KMessageBox::information(this,
780
"<p>Some changes such as anti-aliasing will only affect newly started applications.</p>"
781
), i18n("Font Settings Changed"), "FontSettingsChanged");
782
useAA_original = useAA;
786
if(dpi != dpi_original) {
787
KMessageBox::information(this,
789
"<p>Some changes such as DPI will only affect newly started applications.</p>"
790
), i18n("Font Settings Changed"), "FontSettingsChanged");
794
runRdb(KRdbExportXftSettings | KRdbExportGtkTheme);
800
void KFonts::slotApplyFontDiff()
802
QFont font = QFont(fontUseList.first()->font());
803
KFontChooser::FontDiffFlags fontDiffFlags = 0;
804
int ret = KFontDialog::getFontDiff(font,fontDiffFlags,KFontChooser::NoDisplayFlags,this);
806
if (ret == KDialog::Accepted && fontDiffFlags)
808
for ( int i = 0; i < (int) fontUseList.count(); i++ )
809
fontUseList.at( i )->applyFontDiff( font,fontDiffFlags );
814
void KFonts::slotUseAntiAliasing()
816
#ifdef HAVE_FONTCONFIG
817
useAA = static_cast< AASetting >( cbAA->currentIndex());
818
aaSettingsButton->setEnabled( cbAA->currentIndex() == AAEnabled );
823
void KFonts::slotCfgAa()
825
#ifdef HAVE_FONTCONFIG
826
if(aaSettings->exec())
833
// vim:ts=2:sw=2:tw=78