1 /*
2  *  SPDX-License-Identifier: GPL-2.0-or-later
3  *
4  *  SPDX-FileCopyrightText: 2001 Michael v.Ostheim <MvOstheim@web.de>
5  */
6 
7 #include "kgamma.h"
8 
9 #include "config-kgamma.h"
10 #include "gammactrl.h"
11 #include "xf86configpath.h"
12 #include <unistd.h>
13 
14 #include <QBoxLayout>
15 #include <QCheckBox>
16 #include <QComboBox>
17 #include <QDir>
18 #include <QFormLayout>
19 #include <QFrame>
20 #include <QGridLayout>
21 #include <QHBoxLayout>
22 #include <QLabel>
23 #include <QLayout>
24 #include <QPixmap>
25 #include <QProcess>
26 #include <QStackedWidget>
27 #include <QStandardPaths>
28 #include <QString>
29 #include <QStringList>
30 #include <QTextStream>
31 #include <QVBoxLayout>
32 
33 #include <KConfig>
34 #include <KConfigGroup>
35 #include <KLocalizedString>
36 #include <KPluginFactory>
37 
38 #include "xvidextwrap.h"
39 
40 extern "C" {
test_kgamma()41 bool test_kgamma()
42 {
43     bool retval;
44     (void)new XVidExtWrap(&retval, nullptr);
45     return retval;
46 }
47 }
48 
K_PLUGIN_FACTORY(KGammaConfigFactory,registerPlugin<KGamma> ();)49 K_PLUGIN_FACTORY(KGammaConfigFactory, registerPlugin<KGamma>();)
50 
51 KGamma::KGamma(QWidget *parent_P, const QVariantList &)
52     : KCModule(parent_P)
53     , rootProcess(nullptr)
54 {
55     bool ok;
56     GammaCorrection = false;
57     xv = new XVidExtWrap(&ok, nullptr);
58     if (ok) { /* KDE 4: Uneccessary test, when all KCM wrappers do conditional loading */
59         xv->getGamma(XVidExtWrap::Red, &ok);
60         if (ok) {
61             ScreenCount = xv->_ScreenCount();
62             currentScreen = xv->getScreen();
63             xv->setGammaLimits(0.4, 3.5);
64 
65             for (int i = 0; i < ScreenCount; i++) {
66                 assign << 0;
67                 rgamma << QString();
68                 ggamma << QString();
69                 bgamma << QString();
70 
71                 // Store the current gamma values
72                 xv->setScreen(i);
73                 rbak << xv->getGamma(XVidExtWrap::Red);
74                 gbak << xv->getGamma(XVidExtWrap::Green);
75                 bbak << xv->getGamma(XVidExtWrap::Blue);
76             }
77             xv->setScreen(currentScreen);
78 
79             rootProcess = new QProcess;
80             GammaCorrection = true;
81             setupUI();
82             saved = false;
83 
84             if (!loadSettings()) { // try to load gamma values from config file
85                 // if failed, take current gamma values
86                 for (int i = 0; i < ScreenCount; i++) {
87                     rgamma[i].setNum(rbak[i], 'f', 2);
88                     ggamma[i].setNum(gbak[i], 'f', 2);
89                     bgamma[i].setNum(bbak[i], 'f', 2);
90                 }
91             }
92             load();
93         }
94     }
95     if (!GammaCorrection) { // something is wrong, show only error message
96         setupUI();
97     }
98 }
99 
~KGamma()100 KGamma::~KGamma()
101 {
102     // Restore the old gamma settings, if the user has not saved
103     // and there is no valid kgammarc.
104     // Existing user settings overwrite system settings
105     if (GammaCorrection) {
106         // Do not emit signals during destruction (bug 221611)
107         bool blocked = blockSignals(true);
108         if (loadUserSettings()) {
109             load();
110         } else if (!saved) {
111             for (int i = 0; i < ScreenCount; i++) {
112                 xv->setScreen(i);
113                 xv->setGamma(XVidExtWrap::Red, rbak[i]);
114                 xv->setGamma(XVidExtWrap::Green, gbak[i]);
115                 xv->setGamma(XVidExtWrap::Blue, bbak[i]);
116             }
117         }
118         delete rootProcess;
119         blockSignals(blocked);
120     }
121     delete xv;
122 }
123 
124 /** User interface */
setupUI()125 void KGamma::setupUI()
126 {
127     QBoxLayout *topLayout = new QVBoxLayout(this);
128     topLayout->setContentsMargins(0, 0, 0, 0);
129 
130     if (GammaCorrection) {
131         QHBoxLayout *hbox = new QHBoxLayout();
132         topLayout->addLayout(hbox);
133         QLabel *label = new QLabel(i18n("&Select test picture:"), this);
134         QComboBox *combo = new QComboBox(this);
135         label->setBuddy(combo);
136 
137         QStringList list;
138         list << i18n("Gray Scale") << i18n("RGB Scale") << i18n("CMY Scale") << i18n("Dark Gray") << i18n("Mid Gray") << i18n("Light Gray");
139         combo->addItems(list);
140 
141         hbox->addWidget(label);
142         hbox->addWidget(combo);
143         hbox->addStretch();
144 
145         QStackedWidget *stack = new QStackedWidget(this);
146         stack->setFrameStyle(QFrame::Box | QFrame::Raised);
147 
148         connect(combo, QOverload<int>::of(&QComboBox::activated), stack, &QStackedWidget::setCurrentIndex);
149 
150         QLabel *pic1 = new QLabel(stack);
151         pic1->setMinimumSize(530, 171);
152         pic1->setPixmap(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kgamma/pics/greyscale.png"))));
153         pic1->setAlignment(Qt::AlignCenter);
154         stack->insertWidget(0, pic1);
155 
156         QLabel *pic2 = new QLabel(stack);
157         pic2->setPixmap(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kgamma/pics/rgbscale.png"))));
158         pic2->setAlignment(Qt::AlignCenter);
159         stack->insertWidget(1, pic2);
160 
161         QLabel *pic3 = new QLabel(stack);
162         pic3->setPixmap(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kgamma/pics/cmyscale.png"))));
163         pic3->setAlignment(Qt::AlignCenter);
164         stack->insertWidget(2, pic3);
165 
166         QLabel *pic4 = new QLabel(stack);
167         pic4->setPixmap(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kgamma/pics/darkgrey.png"))));
168         pic4->setAlignment(Qt::AlignCenter);
169         stack->insertWidget(3, pic4);
170 
171         QLabel *pic5 = new QLabel(stack);
172         pic5->setPixmap(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kgamma/pics/midgrey.png"))));
173         pic5->setAlignment(Qt::AlignCenter);
174         stack->insertWidget(4, pic5);
175 
176         QLabel *pic6 = new QLabel(stack);
177         pic6->setPixmap(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kgamma/pics/lightgrey.png"))));
178         pic6->setAlignment(Qt::AlignCenter);
179         stack->insertWidget(5, pic6);
180 
181         topLayout->addWidget(stack, 10);
182 
183         // Sliders for gamma correction
184 
185         QLabel *gammalabel = new QLabel(this);
186         gammalabel->setText(i18n("Gamma:"));
187 
188         QLabel *redlabel = new QLabel(this);
189         redlabel->setText(i18n("Red:"));
190 
191         QLabel *greenlabel = new QLabel(this);
192         greenlabel->setText(i18n("Green:"));
193 
194         QLabel *bluelabel = new QLabel(this);
195         bluelabel->setText(i18n("Blue:"));
196 
197         gctrl = new GammaCtrl(this, xv);
198         connect(gctrl, &GammaCtrl::gammaChanged, this, &KGamma::Changed);
199         connect(gctrl, &GammaCtrl::gammaChanged, this, &KGamma::SyncScreens);
200         gammalabel->setBuddy(gctrl);
201 
202         rgctrl = new GammaCtrl(this, xv, XVidExtWrap::Red);
203         connect(rgctrl, &GammaCtrl::gammaChanged, this, &KGamma::Changed);
204         connect(rgctrl, &GammaCtrl::gammaChanged, this, &KGamma::SyncScreens);
205         connect(gctrl, SIGNAL(gammaChanged(int)), rgctrl, SLOT(setCtrl(int)));
206         connect(rgctrl, &GammaCtrl::gammaChanged, gctrl, &GammaCtrl::suspend);
207         redlabel->setBuddy(rgctrl);
208 
209         ggctrl = new GammaCtrl(this, xv, XVidExtWrap::Green);
210         connect(ggctrl, &GammaCtrl::gammaChanged, this, &KGamma::Changed);
211         connect(ggctrl, &GammaCtrl::gammaChanged, this, &KGamma::SyncScreens);
212         connect(gctrl, SIGNAL(gammaChanged(int)), ggctrl, SLOT(setCtrl(int)));
213         connect(ggctrl, &GammaCtrl::gammaChanged, gctrl, &GammaCtrl::suspend);
214         greenlabel->setBuddy(ggctrl);
215 
216         bgctrl = new GammaCtrl(this, xv, XVidExtWrap::Blue);
217         connect(bgctrl, &GammaCtrl::gammaChanged, this, &KGamma::Changed);
218         connect(bgctrl, &GammaCtrl::gammaChanged, this, &KGamma::SyncScreens);
219         connect(gctrl, SIGNAL(gammaChanged(int)), bgctrl, SLOT(setCtrl(int)));
220         connect(bgctrl, &GammaCtrl::gammaChanged, gctrl, &GammaCtrl::suspend);
221         bluelabel->setBuddy(bgctrl);
222 
223         QFormLayout *form = new QFormLayout;
224         form->addRow(gammalabel, gctrl);
225         form->addItem(new QSpacerItem(0, gammalabel->sizeHint().height() / 3));
226         form->addRow(redlabel, rgctrl);
227         form->addRow(greenlabel, ggctrl);
228         form->addRow(bluelabel, bgctrl);
229 
230         topLayout->addLayout(form);
231 
232         // Options
233         QWidget *options = new QWidget(this);
234         QHBoxLayout *optionsHBoxLayout = new QHBoxLayout(options);
235         optionsHBoxLayout->setContentsMargins(0, 0, 0, 0);
236 
237         xf86cfgbox = new QCheckBox(i18n("Save settings system wide"), options);
238         optionsHBoxLayout->addWidget(xf86cfgbox);
239         connect(xf86cfgbox, &QAbstractButton::clicked, this, &KGamma::changeConfig);
240 
241         syncbox = new QCheckBox(i18n("Sync screens"), options);
242         optionsHBoxLayout->addWidget(syncbox);
243         connect(syncbox, &QAbstractButton::clicked, this, &KGamma::SyncScreens);
244         connect(syncbox, &QAbstractButton::clicked, this, &KGamma::Changed);
245 
246         screenselect = new QComboBox(options);
247         optionsHBoxLayout->addWidget(screenselect);
248         for (int i = 0; i < ScreenCount; i++) {
249             screenselect->addItem(i18n("Screen %1", i + 1));
250         }
251         screenselect->setCurrentIndex(currentScreen);
252         if (ScreenCount <= 1) {
253             screenselect->setEnabled(false);
254         } else {
255             connect(screenselect, QOverload<int>::of(&QComboBox::activated), this, &KGamma::changeScreen);
256         }
257 
258         optionsHBoxLayout->setSpacing(10);
259         optionsHBoxLayout->setStretchFactor(xf86cfgbox, 10);
260         optionsHBoxLayout->setStretchFactor(syncbox, 1);
261         optionsHBoxLayout->setStretchFactor(screenselect, 1);
262 
263         topLayout->addWidget(options);
264     } else {
265         QLabel *error = new QLabel(this);
266         error->setText(
267             i18n("Gamma correction is not supported by your"
268                  " graphics hardware or driver."));
269         error->setAlignment(Qt::AlignCenter);
270         topLayout->addWidget(error);
271     }
272 }
273 
274 /** Restore latest saved gamma values */
load()275 void KGamma::load()
276 {
277     if (GammaCorrection) {
278         KConfig *config = new KConfig(QStringLiteral("kgammarc"));
279         KConfigGroup group = config->group("ConfigFile");
280 
281         // save checkbox status
282         if (xf86cfgbox->isChecked()) {
283             group.writeEntry("use", "XF86Config");
284         } else {
285             group.writeEntry("use", "kgammarc");
286         }
287 
288         // load syncbox status
289         group = config->group("SyncBox");
290         if (group.readEntry("sync") == QLatin1String("yes")) {
291             syncbox->setChecked(true);
292         } else {
293             syncbox->setChecked(false);
294         }
295 
296         config->sync();
297         delete config;
298 
299         for (int i = 0; i < ScreenCount; i++) {
300             xv->setScreen(i);
301             if (rgamma[i] == ggamma[i] && rgamma[i] == bgamma[i]) {
302                 if (i == currentScreen) {
303                     gctrl->setGamma(rgamma[i]);
304                 } else {
305                     xv->setGamma(XVidExtWrap::Value, rgamma[i].toFloat());
306                 }
307             } else {
308                 if (i == currentScreen) {
309                     rgctrl->setGamma(rgamma[i]);
310                     ggctrl->setGamma(ggamma[i]);
311                     bgctrl->setGamma(bgamma[i]);
312                     gctrl->suspend();
313                 } else {
314                     xv->setGamma(XVidExtWrap::Red, rgamma[i].toFloat());
315                     xv->setGamma(XVidExtWrap::Green, ggamma[i].toFloat());
316                     xv->setGamma(XVidExtWrap::Blue, bgamma[i].toFloat());
317                 }
318             }
319         }
320         xv->setScreen(currentScreen);
321 
322         Q_EMIT changed(false);
323     }
324 }
325 
save()326 void KGamma::save()
327 {
328     if (GammaCorrection) {
329         for (int i = 0; i < ScreenCount; i++) {
330             xv->setScreen(i);
331             rgamma[i] = rgctrl->gamma(2);
332             ggamma[i] = ggctrl->gamma(2);
333             bgamma[i] = bgctrl->gamma(2);
334         }
335         xv->setScreen(currentScreen);
336 
337         KConfig *config = new KConfig(QStringLiteral("kgammarc"));
338         KConfigGroup group = config->group("SyncBox");
339         if (syncbox->isChecked()) {
340             group.writeEntry("sync", "yes");
341         } else {
342             group.writeEntry("sync", "no");
343         }
344 
345         if (!xf86cfgbox->isChecked()) { // write gamma settings to the users config
346             for (int i = 0; i < ScreenCount; i++) {
347                 KConfigGroup screenGroup = config->group(QStringLiteral("Screen %1").arg(i));
348                 screenGroup.writeEntry("rgamma", rgamma[i]);
349                 screenGroup.writeEntry("ggamma", ggamma[i]);
350                 screenGroup.writeEntry("bgamma", bgamma[i]);
351             }
352             KConfigGroup confGroup = config->group("ConfigFile");
353             confGroup.writeEntry("use", "kgammarc");
354         } else { // write gamma settings to section "Monitor" of XF86Config
355             KConfigGroup x86group = config->group("ConfigFile");
356             x86group.writeEntry("use", "XF86Config");
357 
358             if (!(rootProcess->state() == QProcess::Running)) {
359                 QString Arguments = QStringLiteral("xf86gammacfg ");
360                 for (int i = 0; i < ScreenCount; i++) {
361                     Arguments += rgamma[assign[i]] + QLatin1Char(' ') + ggamma[assign[i]] + QLatin1Char(' ') + bgamma[assign[i]] + QLatin1Char(' ');
362                 }
363                 rootProcess->setProgram(QStandardPaths::findExecutable(QStringLiteral("kdesu")));
364                 rootProcess->setArguments(Arguments.split(QLatin1Char(' ')));
365                 rootProcess->start();
366             }
367         }
368         config->sync();
369         delete config;
370         saved = true;
371         Q_EMIT changed(false);
372     }
373 }
374 
defaults()375 void KGamma::defaults()
376 {
377     if (GammaCorrection) {
378         for (int i = 0; i < ScreenCount; i++) {
379             xv->setScreen(i);
380             gctrl->setGamma(QStringLiteral("1.00"));
381         }
382         xv->setScreen(currentScreen);
383     }
384     xf86cfgbox->setChecked(false);
385     syncbox->setChecked(false);
386 }
387 
loadSettings()388 bool KGamma::loadSettings()
389 {
390     KConfig *config = new KConfig(QStringLiteral("kgammarc"));
391     KConfigGroup grp = config->group("ConfigFile");
392     QString ConfigFile(grp.readEntry("use"));
393     KConfigGroup syncGroup = config->group("SyncBox");
394     if (syncGroup.readEntry("sync") == QLatin1String("yes")) {
395         syncbox->setChecked(true);
396     }
397     delete config;
398 
399     if (ConfigFile == QLatin1String("XF86Config")) { // parse XF86Config
400         bool validGlobalConfig = loadSystemSettings();
401         xf86cfgbox->setChecked(validGlobalConfig);
402         return (validGlobalConfig);
403     } else { // get gamma settings from user config
404         return (loadUserSettings());
405     }
406 }
407 
loadUserSettings()408 bool KGamma::loadUserSettings()
409 {
410     KConfig *config = new KConfig(QStringLiteral("kgammarc"));
411 
412     for (int i = 0; i < ScreenCount; i++) {
413         KConfigGroup screenGroup = config->group(QStringLiteral("Screen %1").arg(i));
414         rgamma[i] = screenGroup.readEntry("rgamma");
415         ggamma[i] = screenGroup.readEntry("ggamma");
416         bgamma[i] = screenGroup.readEntry("bgamma");
417     }
418     delete config;
419 
420     return (validateGammaValues());
421 }
422 
loadSystemSettings()423 bool KGamma::loadSystemSettings()
424 {
425     QStringList Monitor, Screen, ScreenLayout, ScreenMonitor, Gamma;
426     QList<int> ScreenNr;
427     QString Section;
428     XF86ConfigPath Path;
429     QFile f(QString::fromUtf8(Path.get()));
430     if (f.open(QIODevice::ReadOnly)) {
431         QTextStream t(&f);
432         QString s;
433         int sn = 0;
434         bool gm = false;
435 
436         // Analyze Screen<->Monitor assignments of multi-head configurations
437         while (!t.atEnd()) {
438             s = (t.readLine()).simplified();
439             QStringList words = s.split(QLatin1Char(' '));
440             if (!words.empty()) {
441                 if (words[0] == QLatin1String("Section") && words.size() > 1) {
442                     if ((Section = words[1]) == QLatin1String("\"Monitor\"")) {
443                         gm = false;
444                     }
445                 } else if (words[0] == QLatin1String("EndSection")) {
446                     if (Section == QLatin1String("\"Monitor\"") && !gm) {
447                         Gamma << QString();
448                         gm = false;
449                     }
450                     Section = QString();
451                 } else if (words[0] == QLatin1String("Identifier") && words.size() > 1) {
452                     if (Section == QLatin1String("\"Monitor\"")) {
453                         Monitor << words[1];
454                     } else if (Section == QLatin1String("\"Screen\"")) {
455                         Screen << words[1];
456                     }
457                 } else if (words[0] == QLatin1String("Screen") && words.size() > 1) {
458                     if (Section == QLatin1String("\"ServerLayout\"")) {
459                         bool ok;
460                         int i = words[1].toInt(&ok);
461                         if (ok && words.size() > 2) {
462                             ScreenNr << i;
463                             ScreenLayout << words[2];
464                         } else {
465                             ScreenNr << sn++;
466                             ScreenLayout << words[1];
467                         }
468                     }
469                 } else if (words[0] == QLatin1String("Monitor") && words.size() > 1) {
470                     if (Section == QLatin1String("\"Screen\"")) {
471                         ScreenMonitor << words[1];
472                     }
473                 } else if (words[0] == QLatin1String("Gamma")) {
474                     if (Section == QLatin1String("\"Monitor\"")) {
475                         Gamma << s;
476                         gm = true;
477                     }
478                 }
479             }
480         } // End while
481         f.close();
482         if (!Monitor.isEmpty() && !ScreenMonitor.isEmpty() && !ScreenLayout.isEmpty()) {
483             for (int i = 0; i < ScreenCount; i++) {
484                 for (int j = 0; j < ScreenCount; j++) {
485                     if (ScreenLayout[i] == Screen[j]) {
486                         for (int k = 0; k < ScreenCount; k++) {
487                             if (Monitor[k] == ScreenMonitor[j]) {
488                                 assign[ScreenNr[i]] = k;
489                             }
490                         }
491                     }
492                 }
493             }
494             // Extract gamma values
495             if (gm) {
496                 for (int i = 0; i < ScreenCount; i++) {
497                     rgamma[i] = ggamma[i] = bgamma[i] = QString();
498 
499                     QStringList words = Gamma[assign[i]].split(QLatin1Char(' '));
500                     QStringList::ConstIterator it = words.constBegin();
501                     if (words.size() < 4) {
502                         rgamma[i] = ggamma[i] = bgamma[i] = *(++it); // single gamma value
503                     } else {
504                         rgamma[i] = *(++it); // eventually rgb gamma values
505                         ggamma[i] = *(++it);
506                         bgamma[i] = *(++it);
507                     }
508                 }
509             }
510         }
511     }
512     return (validateGammaValues());
513 }
514 
validateGammaValues()515 bool KGamma::validateGammaValues()
516 {
517     bool rOk, gOk, bOk, result;
518 
519     result = true;
520     for (int i = 0; i < ScreenCount; i++) {
521         rgamma[i].toFloat(&rOk);
522         ggamma[i].toFloat(&gOk);
523         bgamma[i].toFloat(&bOk);
524 
525         if (!(rOk && gOk && bOk)) {
526             if (rOk) {
527                 ggamma[i] = bgamma[i] = rgamma[i];
528             } else {
529                 result = false;
530             }
531         }
532     }
533     return (result);
534 }
535 
changeConfig()536 void KGamma::changeConfig()
537 {
538     bool Ok = false;
539 
540     if (xf86cfgbox->isChecked()) {
541         Ok = loadSystemSettings();
542     } else {
543         Ok = loadUserSettings();
544     }
545 
546     if (!Ok) {
547         for (int i = 0; i < ScreenCount; i++) {
548             xv->setScreen(i);
549             rgamma[i].setNum(xv->getGamma(XVidExtWrap::Red), 'f', 2);
550             ggamma[i].setNum(xv->getGamma(XVidExtWrap::Green), 'f', 2);
551             bgamma[i].setNum(xv->getGamma(XVidExtWrap::Blue), 'f', 2);
552         }
553         xv->setScreen(currentScreen);
554     }
555     load();
556 }
557 
SyncScreens()558 void KGamma::SyncScreens()
559 {
560     if (syncbox->isChecked()) {
561         float rg = xv->getGamma(XVidExtWrap::Red);
562         float gg = xv->getGamma(XVidExtWrap::Green);
563         float bg = xv->getGamma(XVidExtWrap::Blue);
564 
565         for (int i = 0; i < ScreenCount; i++) {
566             if (i != currentScreen) {
567                 xv->setScreen(i);
568                 xv->setGamma(XVidExtWrap::Red, rg);
569                 xv->setGamma(XVidExtWrap::Green, gg);
570                 xv->setGamma(XVidExtWrap::Blue, bg);
571             }
572         }
573         xv->setScreen(currentScreen);
574     }
575 }
576 
changeScreen(int sn)577 void KGamma::changeScreen(int sn)
578 {
579     QString red, green, blue;
580 
581     xv->setScreen(sn);
582     currentScreen = sn;
583 
584     red.setNum(xv->getGamma(XVidExtWrap::Red), 'f', 2);
585     green.setNum(xv->getGamma(XVidExtWrap::Green), 'f', 2);
586     blue.setNum(xv->getGamma(XVidExtWrap::Blue), 'f', 2);
587 
588     gctrl->setControl(red);
589     rgctrl->setControl(red);
590     ggctrl->setControl(green);
591     bgctrl->setControl(blue);
592     if (red != green || red != blue) {
593         gctrl->suspend();
594     }
595 }
596 
buttons()597 int KGamma::buttons()
598 {
599     return Default | Apply | Help;
600 }
601 
quickHelp() const602 QString KGamma::quickHelp() const
603 {
604     return i18n(
605         "<h1>Monitor Gamma</h1> This is a tool for changing monitor gamma"
606         " correction. Use the four sliders to define the gamma correction either"
607         " as a single value, or separately for the red, green and blue components."
608         " You may need to correct the brightness and contrast settings of your"
609         " monitor for good results. The test images help you to find proper"
610         " settings.<br> You can save them system-wide to XF86Config (root access"
611         " is required for that) or to your own KDE settings. On multi head"
612         " systems you can correct the gamma values separately for all screens.");
613 }
614 
615 // ------------------------------------------------------------------------
616 
617 extern "C" {
618 // Restore the user gamma settings
kcminit_kgamma()619 Q_DECL_EXPORT void kcminit_kgamma()
620 {
621     bool ok;
622     XVidExtWrap xv(&ok);
623 
624     if (ok) {
625         xv.setGammaLimits(0.4, 3.5);
626         float rgamma, ggamma, bgamma;
627         KConfig *config = new KConfig(QStringLiteral("kgammarc"));
628 
629         for (int i = 0; i < xv._ScreenCount(); i++) {
630             xv.setScreen(i);
631             KConfigGroup screenGroup = config->group(QStringLiteral("Screen %1").arg(i));
632 
633             if ((rgamma = screenGroup.readEntry("rgamma").toFloat())) {
634                 xv.setGamma(XVidExtWrap::Red, rgamma);
635             }
636             if ((ggamma = screenGroup.readEntry("ggamma").toFloat())) {
637                 xv.setGamma(XVidExtWrap::Green, ggamma);
638             }
639             if ((bgamma = screenGroup.readEntry("bgamma").toFloat())) {
640                 xv.setGamma(XVidExtWrap::Blue, bgamma);
641             }
642         }
643         delete config;
644     }
645 }
646 }
647 
648 #include "kgamma.moc"
649