Fix crash if key bindings specified in profile cannot be found. Improve
[personal-kdebase.git] / apps / konqueror / settings / konqhtml / appearance.cpp
blobfd78c3239ac65acfc7fbd7e1b7a44c4fadeecdee
1 #include "kcmcss.h"
3 #include <QtGui/QLabel>
4 #include <QtGui/QLayout>
5 #include <QtGui/QFormLayout>
6 #include <QtGui/QLineEdit>
7 #include <QtDBus/QDBusMessage>
8 #include <QtDBus/QDBusConnection>
9 #include <QtGui/QGroupBox>
11 #include <kapplication.h>
12 #include <kcharsets.h>
13 #include <ksharedconfig.h>
14 #include <kdebug.h>
15 #include <kdialog.h>
16 #include <kglobal.h>
17 #include <khtmldefaults.h>
18 #include <klocale.h>
19 #include <knuminput.h>
20 #include <kglobalsettings.h>
21 #include <KPluginFactory>
22 #include <KPluginLoader>
23 #include <KFontComboBox>
24 #include <KTabWidget>
26 #if defined Q_WS_X11 && !defined K_WS_QTONLY
27 #include <X11/Xlib.h>
28 #endif
30 #include "appearance.moc"
32 K_PLUGIN_FACTORY_DECLARATION(KcmKonqHtmlFactory)
34 static const char* animationValues[]={"Enabled","Disabled","LoopOnce"};
35 enum AnimationsType { AnimationsAlways=0, AnimationsNever=1, AnimationsLoopOnce=2 };
37 static const char* smoothScrollingValues[]={"Enabled","Disabled","WhenEfficient"};
38 enum SmoothScrollingType { SmoothScrollingAlways=0, SmoothScrollingNever=1, SmoothScrollingWhenEfficient=2 };
40 enum UnderlineLinkType { UnderlineAlways=0, UnderlineNever=1, UnderlineHover=2 };
42 KAppearanceOptions::KAppearanceOptions(QWidget *parent, const QVariantList&)
43 : KCModule( KcmKonqHtmlFactory::componentData(), parent ), m_groupname("HTML Settings"),
44 fSize( 10 ), fMinSize( HTML_DEFAULT_MIN_FONT_SIZE )
47 QVBoxLayout* l=new QVBoxLayout(this);
48 KTabWidget* tab=new KTabWidget(this);
49 l->addWidget(tab);
50 QWidget* mainTab=new QWidget(this);
51 QWidget* fontsTab=new QWidget(this);
52 cssConfig=new CSSConfig(this);
53 tab->addTab(mainTab,i18nc("@title:tab","General"));
54 tab->addTab(fontsTab,i18nc("@title:tab","Fonts"));
55 tab->addTab(cssConfig,i18nc("@title:tab","Stylesheets"));
57 connect( cssConfig, SIGNAL( changed() ), this, SLOT(changed()) );
58 connect( cssConfig, SIGNAL( changed(bool) ), this, SIGNAL(changed(bool)) );
61 l=new QVBoxLayout(mainTab);
63 //Images
64 QGroupBox *box = new QGroupBox( i18n("Images"),mainTab);
65 l->addWidget(box);
66 QFormLayout *fl= new QFormLayout(box);
67 fl->setSpacing(KDialog::spacingHint());
69 m_pAutoLoadImagesCheckBox = new QCheckBox( i18n( "A&utomatically load images"), this );
70 m_pAutoLoadImagesCheckBox->setWhatsThis( i18n( "<html>If this box is checked, Konqueror will"
71 " automatically load any images that are embedded in a web page."
72 " Otherwise, it will display placeholders for the images, and"
73 " you can then manually load the images by clicking on the image"
74 " button.<br />Unless you have a very slow network connection, you"
75 " will probably want to check this box to enhance your browsing"
76 " experience.</html>" ) );
77 connect(m_pAutoLoadImagesCheckBox, SIGNAL(toggled(bool)), SLOT(changed()));
78 fl->addRow( m_pAutoLoadImagesCheckBox);
80 m_pUnfinishedImageFrameCheckBox = new QCheckBox( i18n( "Dra&w frame around not completely loaded images"), this );
81 m_pUnfinishedImageFrameCheckBox->setWhatsThis( i18n( "<html>If this box is checked, Konqueror will draw"
82 " a frame as a placeholder around images embedded in a web page that are"
83 " not yet fully loaded.<br />You will probably want to check this box to"
84 " enhance your browsing experience, especially if have a slow network"
85 " connection.</html>" ) );
86 connect(m_pUnfinishedImageFrameCheckBox, SIGNAL(toggled(bool)), SLOT(changed()));
87 fl->addRow( m_pUnfinishedImageFrameCheckBox );
90 m_pAnimationsCombo = new QComboBox( this );
91 m_pAnimationsCombo->setEditable(false);
92 m_pAnimationsCombo->insertItem(AnimationsAlways, i18nc("animations","Enabled"));
93 m_pAnimationsCombo->insertItem(AnimationsNever, i18nc("animations","Disabled"));
94 m_pAnimationsCombo->insertItem(AnimationsLoopOnce, i18n("Show Only Once"));
95 m_pAnimationsCombo->setWhatsThis(i18n("<html>Controls how Konqueror shows animated images:<br />"
96 "<ul><li><b>Enabled</b>: Show all animations completely.</li>"
97 "<li><b>Disabled</b>: Never show animations, show the starting image only.</li>"
98 "<li><b>Show only once</b>: Show all animations completely but do not repeat them.</li></ul></html>"));
99 connect(m_pAnimationsCombo, SIGNAL(currentIndexChanged(int)), SLOT(changed()));
100 fl->addRow(i18n("A&nimations:"), m_pAnimationsCombo);
104 //Other
105 box = new QGroupBox(i18nc("@title:group","Miscellaneous"),mainTab);
106 l->addWidget(box);
107 fl=new QFormLayout(box);
108 m_pUnderlineCombo = new QComboBox( this );
109 m_pUnderlineCombo->setEditable(false);
110 m_pUnderlineCombo->insertItem(UnderlineAlways, i18nc("underline","Enabled"));
111 m_pUnderlineCombo->insertItem(UnderlineNever, i18nc("underline","Disabled"));
112 m_pUnderlineCombo->insertItem(UnderlineHover, i18n("Only on Hover"));
113 fl->addRow(i18n("Und&erline links:"),m_pUnderlineCombo);
115 m_pUnderlineCombo->setWhatsThis(i18n(
116 "<html>Controls how Konqueror handles underlining hyperlinks:<br />"
117 "<ul><li><b>Enabled</b>: Always underline links</li>"
118 "<li><b>Disabled</b>: Never underline links</li>"
119 "<li><b>Only on Hover</b>: Underline when the mouse is moved over the link</li>"
120 "</ul><br /><i>Note: The site's CSS definitions can override this value.</i></html>"));
121 connect(m_pUnderlineCombo, SIGNAL(currentIndexChanged(int)), SLOT(changed()));
124 m_pSmoothScrollingCombo = new QComboBox( this );
125 m_pSmoothScrollingCombo->setEditable(false);
126 m_pSmoothScrollingCombo->insertItem(SmoothScrollingWhenEfficient, i18n("When Efficient"));
127 m_pSmoothScrollingCombo->insertItem(SmoothScrollingAlways, i18nc("smooth scrolling","Always"));
128 m_pSmoothScrollingCombo->insertItem(SmoothScrollingNever, i18nc("soft scrolling","Never"));
129 fl->addRow(i18n("S&mooth scrolling:"), m_pSmoothScrollingCombo);
130 m_pSmoothScrollingCombo->setWhatsThis(i18n(
131 "<html>Determines whether Konqueror should use smooth steps to scroll HTML pages, or whole steps:<br />"
132 "<ul><li><b>Always</b>: Always use smooth steps when scrolling.</li>"
133 "<li><b>Never</b>: Never use smooth scrolling, scroll with whole steps instead.</li>"
134 "<li><b>When Efficient</b>: Only use smooth scrolling on pages where it can be achieved with moderate usage of system resources.</li></ul></html>"));
135 connect(m_pSmoothScrollingCombo, SIGNAL(currentIndexChanged(int)), SLOT(changed()));
137 l->addStretch(5);
143 m_pConfig = KSharedConfig::openConfig("konquerorrc", KConfig::NoGlobals);
144 setQuickHelp( i18n("<h1>Konqueror Fonts</h1>On this page, you can configure "
145 "which fonts Konqueror should use to display the web "
146 "pages you view.") + "<br /><br />" +cssConfig->whatsThis());
148 QString empty;
149 //initialise fonts list otherwise it crashs
150 while (fonts.count() < 7)
151 fonts.append(empty);
153 QVBoxLayout *lay = new QVBoxLayout(fontsTab);
154 lay->setSpacing(KDialog::spacingHint());
156 QGroupBox* gb = new QGroupBox( i18n("Font Si&ze"));
157 lay->addWidget(gb);
158 fl=new QFormLayout(gb);
159 gb->setWhatsThis( i18n("This is the relative font size Konqueror uses to display web sites.") );
161 m_minSize = new KIntNumInput( fMinSize);
162 fl->addRow(i18n( "M&inimum font size:" ),m_minSize);
163 m_minSize->setRange( 2, 30 );
164 connect( m_minSize, SIGNAL( valueChanged( int ) ), this, SLOT( slotMinimumFontSize( int ) ) );
165 connect( m_minSize, SIGNAL( valueChanged( int ) ), this, SLOT( changed() ) );
166 m_minSize->setWhatsThis( i18n( "Konqueror will never display text smaller than "
167 "this size,<br />overriding any other settings." ) );
169 m_MedSize = new KIntNumInput( fSize,m_minSize );
170 fl->addRow(i18n( "&Medium font size:" ),m_MedSize);
171 m_MedSize->setRange( 2, 30 );
172 connect( m_MedSize, SIGNAL( valueChanged( int ) ), this, SLOT( slotFontSize( int ) ) );
173 connect( m_MedSize, SIGNAL( valueChanged( int ) ), this, SLOT( changed() ) );
174 m_MedSize->setWhatsThis(
175 i18n("This is the relative font size Konqueror uses "
176 "to display web sites.") );
179 box = new QGroupBox(/*i18n("Font Families")*/);
180 lay->addWidget(box);
181 fl=new QFormLayout(box);
184 m_pFonts[0] = new KFontComboBox( fontsTab );
185 fl->addRow(i18n("S&tandard font:"), m_pFonts[0]);
186 m_pFonts[0]->setWhatsThis( i18n("This is the font used to display normal text in a web page.") );
187 connect( m_pFonts[0], SIGNAL( currentFontChanged(const QFont&) ),
188 SLOT( slotStandardFont(const QFont&) ) );
190 m_pFonts[1] = new KFontComboBox( fontsTab );
191 fl->addRow( i18n( "&Fixed font:"),m_pFonts[1]);
192 m_pFonts[1]->setWhatsThis( i18n("This is the font used to display fixed-width (i.e. non-proportional) text."));
193 connect( m_pFonts[1], SIGNAL( currentFontChanged(const QFont&) ),
194 SLOT(slotFixedFont(const QFont&) ) );
196 m_pFonts[2] = new KFontComboBox( this );
197 fl->addRow(i18n( "S&erif font:" ), m_pFonts[2]);
198 m_pFonts[2]->setWhatsThis( i18n( "This is the font used to display text that is marked up as serif." ) );
200 connect( m_pFonts[2], SIGNAL( currentFontChanged(const QFont&) ),
201 SLOT(slotSerifFont(const QFont&) ) );
203 m_pFonts[3] = new KFontComboBox( this );
204 fl->addRow(i18n( "Sa&ns serif font:" ), m_pFonts[3]);
205 m_pFonts[3]->setWhatsThis( i18n( "This is the font used to display text that is marked up as sans-serif." ) );
206 connect( m_pFonts[3], SIGNAL( currentFontChanged(const QFont&) ),
207 SLOT(slotSansSerifFont(const QFont&) ) );
209 m_pFonts[4] = new KFontComboBox( this );
210 fl->addRow(i18n( "C&ursive font:" ), m_pFonts[4]);
211 m_pFonts[4]->setWhatsThis( i18n( "This is the font used to display text that is marked up as italic." ) );
212 connect( m_pFonts[4], SIGNAL( currentFontChanged(const QFont&) ),
213 SLOT(slotCursiveFont(const QFont&) ) );
215 m_pFonts[5] = new KFontComboBox( this );
216 fl->addRow(i18n( "Fantas&y font:" ), m_pFonts[5]);
217 m_pFonts[5]->setWhatsThis( i18n( "This is the font used to display text that is marked up as a fantasy font." ) );
218 connect( m_pFonts[5], SIGNAL( currentFontChanged(const QFont&) ),
219 SLOT(slotFantasyFont(const QFont&) ) );
221 for(int i = 0; i < 6; ++i)
222 connect( m_pFonts[i], SIGNAL( currentFontChanged(const QFont&) ),
223 SLOT(changed() ) );
228 m_pFontSizeAdjust = new QSpinBox( this );
229 m_pFontSizeAdjust->setRange( -5, 5 );
230 m_pFontSizeAdjust->setSingleStep( 1 );
231 fl->addRow(i18n( "Font &size adjustment for this encoding:" ), m_pFontSizeAdjust);
233 connect( m_pFontSizeAdjust, SIGNAL( valueChanged( int ) ),
234 SLOT( slotFontSizeAdjust( int ) ) );
235 connect( m_pFontSizeAdjust, SIGNAL( valueChanged( int ) ),
236 SLOT( changed() ) );
239 m_pEncoding = new QComboBox( this );
240 m_pEncoding->setEditable( false );
241 encodings = KGlobal::charsets()->availableEncodingNames();
242 encodings.prepend(i18n("Use Language Encoding"));
243 m_pEncoding->addItems( encodings );
244 fl->addRow(i18n( "Default encoding:"), m_pEncoding);
246 m_pEncoding->setWhatsThis( i18n( "Select the default encoding to be used; normally, you will be fine with 'Use language encoding' "
247 "and should not have to change this.") );
249 connect( m_pEncoding, SIGNAL( activated(const QString& ) ),
250 SLOT( slotEncoding(const QString&) ) );
251 connect( m_pEncoding, SIGNAL( activated(const QString& ) ),
252 SLOT( changed() ) );
254 lay->addStretch(5);
257 KAppearanceOptions::~KAppearanceOptions()
261 void KAppearanceOptions::slotFontSize( int i )
263 fSize = i;
264 if ( fSize < fMinSize ) {
265 m_minSize->setValue( fSize );
266 fMinSize = fSize;
271 void KAppearanceOptions::slotMinimumFontSize( int i )
273 fMinSize = i;
274 if ( fMinSize > fSize ) {
275 m_MedSize->setValue( fMinSize );
276 fSize = fMinSize;
281 void KAppearanceOptions::slotStandardFont(const QFont& n )
283 fonts[0] = n.family();
287 void KAppearanceOptions::slotFixedFont(const QFont& n )
289 fonts[1] = n.family();
293 void KAppearanceOptions::slotSerifFont( const QFont& n )
295 fonts[2] = n.family();
299 void KAppearanceOptions::slotSansSerifFont( const QFont& n )
301 fonts[3] = n.family();
305 void KAppearanceOptions::slotCursiveFont( const QFont& n )
307 fonts[4] = n.family();
311 void KAppearanceOptions::slotFantasyFont( const QFont& n )
313 fonts[5] = n.family();
316 void KAppearanceOptions::slotFontSizeAdjust( int value )
318 fonts[6] = QString::number( value );
321 void KAppearanceOptions::slotEncoding(const QString& n)
323 encodingName = n;
327 static int stringToIndex(const char** possibleValues, int possibleValuesCount, int defaultValue, const QString& value)
329 int i=possibleValuesCount;
330 while (--i>=0)
331 if (possibleValues[i]==value) break;
332 if (i==-1) i=defaultValue;
333 return i;
336 void KAppearanceOptions::load()
338 KConfigGroup khtmlrc(KSharedConfig::openConfig("khtmlrc", KConfig::NoGlobals), "");
339 KConfigGroup cg(m_pConfig, "");
340 #define SET_GROUP(x) cg = KConfigGroup(m_pConfig,x); khtmlrc = KConfigGroup(KSharedConfig::openConfig("khtmlrc", KConfig::NoGlobals),x)
341 #define READ_NUM(x,y) cg.readEntry(x, khtmlrc.readEntry(x, y))
342 #define READ_ENTRY(x,y) cg.readEntry(x, khtmlrc.readEntry(x, y))
343 #define READ_LIST(x) cg.readEntry(x, khtmlrc.readEntry(x, QStringList() ))
344 #define READ_BOOL(x,y) cg.readEntry(x, khtmlrc.readEntry(x, y))
345 #define READ_ENTRYNODEFAULT(x) cg.readEntry(x, khtmlrc.readEntry(x))
347 SET_GROUP(m_groupname);
348 fSize = READ_NUM( "MediumFontSize", 12 );
349 fMinSize = READ_NUM( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE );
350 if (fSize < fMinSize)
351 fSize = fMinSize;
353 defaultFonts = QStringList();
354 defaultFonts.append( READ_ENTRY( "StandardFont", KGlobalSettings::generalFont().family() ) );
355 defaultFonts.append( READ_ENTRY( "FixedFont", KGlobalSettings::fixedFont().family() ) );
356 defaultFonts.append( READ_ENTRY( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT ) );
357 defaultFonts.append( READ_ENTRY( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ) );
358 defaultFonts.append( READ_ENTRY( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT ) );
359 defaultFonts.append( READ_ENTRY( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT ) );
360 defaultFonts.append( QString("0") ); // default font size adjustment
362 if (cg.hasKey("Fonts"))
363 fonts = cg.readEntry( "Fonts" , QStringList() );
364 else
365 fonts = khtmlrc.readEntry( "Fonts" , QStringList() );
366 while (fonts.count() < 7)
367 fonts.append(QString());
369 encodingName = READ_ENTRYNODEFAULT( "DefaultEncoding");//TODO move
370 //kDebug(0) << "encoding = " << encodingName;
375 m_pAutoLoadImagesCheckBox->setChecked( READ_BOOL( "AutoLoadImages", true ) );
376 m_pUnfinishedImageFrameCheckBox->setChecked( READ_BOOL( "UnfinishedImageFrame", true ) );
378 m_pAnimationsCombo->setCurrentIndex( stringToIndex(animationValues, sizeof(animationValues)/sizeof(char*), /*default*/2, READ_ENTRYNODEFAULT( "ShowAnimations" )) );
379 m_pSmoothScrollingCombo->setCurrentIndex( stringToIndex(smoothScrollingValues,sizeof(smoothScrollingValues)/sizeof(char*),/*default*/2, READ_ENTRYNODEFAULT( "SmoothScrolling")) );
380 // we use two keys for link underlining so that this config file
381 // is backwards compatible with KDE 2.0. the HoverLink setting
382 // has precedence over the UnderlineLinks setting
383 if (READ_BOOL("HoverLinks", true))
384 m_pUnderlineCombo->setCurrentIndex( UnderlineHover );
385 else
386 m_pUnderlineCombo->setCurrentIndex( READ_BOOL("UnderlineLinks",true)? UnderlineAlways : UnderlineNever);
389 cssConfig->load();
393 updateGUI();
394 emit changed(false);
397 void KAppearanceOptions::defaults()
399 bool old = m_pConfig->readDefaults();
400 m_pConfig->setReadDefaults(true);
401 load();
402 m_pConfig->setReadDefaults(old);
404 cssConfig->defaults();
405 emit changed(true);
408 void KAppearanceOptions::updateGUI()
410 //kDebug() << "KAppearanceOptions::updateGUI " << charset;
411 for ( int f = 0; f < 6; f++ ) {
412 QString ff = fonts[f];
413 if (ff.isEmpty())
414 ff = defaultFonts[f];
415 m_pFonts[f]->setCurrentFont(ff);
418 int i = 0;
419 for ( QStringList::const_iterator it = encodings.constBegin(); it != encodings.constEnd(); ++it, ++i )
420 if ( encodingName == *it )
421 m_pEncoding->setCurrentIndex( i );
422 if(encodingName.isEmpty())
423 m_pEncoding->setCurrentIndex( 0 );
424 m_pFontSizeAdjust->setValue( fonts[6].toInt() );
425 m_MedSize->blockSignals(true);
426 m_MedSize->setValue( fSize );
427 m_MedSize->blockSignals(false);
428 m_minSize->blockSignals(true);
429 m_minSize->setValue( fMinSize );
430 m_minSize->blockSignals(false);
433 void KAppearanceOptions::save()
435 KConfigGroup cg(m_pConfig, m_groupname);
436 cg.writeEntry( "MediumFontSize", fSize );
437 cg.writeEntry( "MinimumFontSize", fMinSize );
438 cg.writeEntry( "Fonts", fonts );
440 //TODO move to behaviour
441 // If the user chose "Use language encoding", write an empty string
442 if (encodingName == i18n("Use Language Encoding"))
443 encodingName = "";
444 cg.writeEntry( "DefaultEncoding", encodingName );
448 //Images
449 cg.writeEntry( "AutoLoadImages", m_pAutoLoadImagesCheckBox->isChecked() );
450 cg.writeEntry( "UnfinishedImageFrame", m_pUnfinishedImageFrameCheckBox->isChecked() );
451 cg.writeEntry( "ShowAnimations", animationValues[m_pAnimationsCombo->currentIndex()] );
452 cg.writeEntry( "UnderlineLinks", m_pUnderlineCombo->currentIndex()==UnderlineAlways);
453 cg.writeEntry( "HoverLinks", m_pUnderlineCombo->currentIndex()==UnderlineHover);
454 cg.writeEntry( "SmoothScrolling", smoothScrollingValues[m_pSmoothScrollingCombo->currentIndex()] );
456 cssConfig->save();
458 cg.sync();
459 // Send signal to all konqueror instances
460 QDBusMessage message =
461 QDBusMessage::createSignal("/KonqMain", "org.kde.Konqueror.Main", "reparseConfiguration");
462 QDBusConnection::sessionBus().send(message);
465 emit changed(false);