/** * iccconfig.cpp * * Copyright (c) 2009-2010 Timothy Pearson <kb9vqf@pearsoncomputing.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include <tqcheckbox.h> #include <tqlabel.h> #include <tqlayout.h> #include <tqlineedit.h> #include <tqpushbutton.h> #include <dcopclient.h> #include <tdeaboutdata.h> #include <tdeapplication.h> #include <tdeconfig.h> #include <kcombobox.h> #include <kdebug.h> #include <kdialog.h> #include <tdeglobal.h> #include <tdelistview.h> #include <tdelocale.h> #include <tdemessagebox.h> #include <tdepopupmenu.h> #include <kinputdialog.h> #include <kurlrequester.h> #include <kgenericfactory.h> #include <unistd.h> #include <ksimpleconfig.h> #include <string> #include <stdio.h> #include <tqstring.h> #include "iccconfig.h" using namespace std; /**** DLL Interface ****/ typedef KGenericFactory<KICCConfig, TQWidget> KICCCFactory; K_EXPORT_COMPONENT_FACTORY( kcm_iccconfig, KICCCFactory("kcmiccconfig") ) KSimpleConfig *config; KSimpleConfig *systemconfig; /**** KICCConfig ****/ KICCConfig::KICCConfig(TQWidget *parent, const char *name, const TQStringList &) : TDECModule(KICCCFactory::instance(), parent, name), iccFileArray(NULL) { TQVBoxLayout *layout = new TQVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint()); if (getuid() != 0) { config = new KSimpleConfig( TQString::fromLatin1( "kiccconfigrc" )); } else { config = NULL; } systemconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/kicc/kiccconfigrc" )); TDEAboutData *about = new TDEAboutData(I18N_NOOP("kcmiccconfig"), I18N_NOOP("TDE ICC Profile Control Module"), 0, 0, TDEAboutData::License_GPL, I18N_NOOP("(c) 2009,2010 Timothy Pearson")); about->addAuthor("Timothy Pearson", 0, "kb9vqf@pearsoncomputing.net"); setAboutData( about ); base = new ICCConfigBase(this); layout->add(base); setRootOnlyMsg(i18n("<b>The global ICC color profile is a system wide setting, and requires administrator access</b><br>To alter the system's global ICC profile, click on the \"Administrator Mode\" button below.")); // setUseRootOnlyMsg(true); // Setting this hides the Apply button! connect(base->systemEnableSupport, TQT_SIGNAL(clicked()), TQT_SLOT(changed())); connect(base->systemEnableSupport, TQT_SIGNAL(toggled(bool)), base->systemIccFile, TQT_SLOT(setEnabled(bool))); connect(base->enableSupport, TQT_SIGNAL(clicked()), TQT_SLOT(changed())); connect(base->enableSupport, TQT_SIGNAL(toggled(bool)), base->iccFile, TQT_SLOT(setEnabled(bool))); connect(base->enableSupport, TQT_SIGNAL(toggled(bool)), base->randrScreenList, TQT_SLOT(setEnabled(bool))); connect(base->enableSupport, TQT_SIGNAL(toggled(bool)), base->iccProfileList, TQT_SLOT(setEnabled(bool))); connect(base->enableSupport, TQT_SIGNAL(toggled(bool)), base->addProfileButton, TQT_SLOT(setEnabled(bool))); connect(base->enableSupport, TQT_SIGNAL(toggled(bool)), base->renameProfileButton, TQT_SLOT(setEnabled(bool))); connect(base->enableSupport, TQT_SIGNAL(toggled(bool)), base->deleteProfileButton, TQT_SLOT(setEnabled(bool))); connect(base->iccProfileList, TQT_SIGNAL(activated(int)), this, TQT_SLOT(selectProfile(int))); connect(base->randrScreenList, TQT_SIGNAL(activated(int)), this, TQT_SLOT(selectScreen(int))); connect(base->iccFile, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(updateArray())); connect(base->systemIccFile, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(changed())); connect(base->addProfileButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(addProfile())); connect(base->renameProfileButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(renameProfile())); connect(base->deleteProfileButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(deleteProfile())); load(); if (!config || !config->checkConfigFilesWritable( true )) { base->enableSupport->setEnabled(false); base->randrScreenList->setEnabled(false); base->iccProfileList->setEnabled(false); base->iccFile->setEnabled(false); base->addProfileButton->setEnabled(false); base->renameProfileButton->setEnabled(false); base->deleteProfileButton->setEnabled(false); } if (getuid() != 0 || !systemconfig->checkConfigFilesWritable( true )) { base->systemEnableSupport->setEnabled(false); base->systemIccFile->setEnabled(false); } } KICCConfig::~KICCConfig() { if (iccFileArray) { delete [] iccFileArray; } if (config) { delete config; } delete systemconfig; } void KICCConfig::deleteProfile () { int i; TQString *iccFileArrayNew; // Delete the profile if (config) config->deleteGroup(base->iccProfileList->currentText()); base->iccProfileList->removeItem(base->iccProfileList->currentItem()); base->iccProfileList->setCurrentItem(base->iccProfileList->count()-1); // Contract the profile memory numberOfProfiles--; iccFileArrayNew = new TQString[numberOfProfiles*numberOfScreens]; for (i=0;i<(numberOfProfiles*numberOfScreens);i++) { iccFileArrayNew[i] = iccFileArray[i]; } delete [] iccFileArray; iccFileArray = iccFileArrayNew; } void KICCConfig::renameProfile () { int i; TQString *iccFileArrayNew; // Pop up a text entry box asking for the name of the new profile bool _ok = false; bool _end = false; TQString _new; TQString _text = i18n("Please enter the new profile name below:"); TQString _error; while (!_end) { _new = KInputDialog::getText( i18n("ICC Profile Configuration"), _error + _text, TQString::null, &_ok, this); if (!_ok ) { _end = true; } else { _error = TQString(); if (!_new.isEmpty()) { if (findProfileIndex(_new) != -1) _error = i18n("Error: A profile with that name already exists") + TQString("\n"); else _end = true; } } } if (!_ok) return; // Rename the profile if (config) config->deleteGroup(base->iccProfileList->currentText()); base->iccProfileList->changeItem(_new, base->iccProfileList->currentItem()); updateDisplayedInformation(); emit changed(); } void KICCConfig::addProfile () { int i; TQString *iccFileArrayNew; // Pop up a text entry box asking for the name of the new profile bool _ok = false; bool _end = false; TQString _new; TQString _text = i18n("Please enter the new profile name below:"); TQString _error; while (!_end) { _new = KInputDialog::getText( i18n("ICC Profile Configuration"), _error + _text, TQString::null, &_ok, this); if (!_ok ) { _end = true; } else { _error = TQString(); if (!_new.isEmpty()) { if (findProfileIndex(_new) != -1) _error = i18n("Error: A profile with that name already exists") + TQString("\n"); else _end = true; } } } if (!_ok) return; // Expand the profile memory numberOfProfiles++; iccFileArrayNew = new TQString[numberOfProfiles*numberOfScreens]; for (i=0;i<((numberOfProfiles-1)*numberOfScreens);i++) { iccFileArrayNew[i] = iccFileArray[i]; } delete [] iccFileArray; iccFileArray = iccFileArrayNew; for (;i<(numberOfProfiles*numberOfScreens);i++) { iccFileArray[i] = ""; } // Insert the new profile name base->iccProfileList->insertItem(_new, -1); base->iccProfileList->setCurrentItem(base->iccProfileList->count()-1); updateDisplayedInformation(); emit changed(); } void KICCConfig::load() { load( false ); } void KICCConfig::selectProfile (int slotNumber) { updateDisplayedInformation(); emit changed(); } void KICCConfig::selectScreen (int slotNumber) { updateDisplayedInformation(); } void KICCConfig::updateArray (void) { iccFileArray[((base->iccProfileList->currentItem())*(base->randrScreenList->count()))+(base->randrScreenList->currentItem())] = base->iccFile->url(); if (config) { config->setGroup(base->iccProfileList->currentText()); if (config->readEntry(base->randrScreenList->currentText()) != iccFileArray[((base->iccProfileList->currentItem())*(base->randrScreenList->count()))+(base->randrScreenList->currentItem())]) { emit changed(); } } } void KICCConfig::updateDisplayedInformation () { base->iccFile->setURL(iccFileArray[((base->iccProfileList->currentItem())*(base->randrScreenList->count()))+(base->randrScreenList->currentItem())]); } TQString KICCConfig::extractFileName(TQString displayName, TQString profileName) { // } int KICCConfig::findProfileIndex(TQString profileName) { int i; for (i=0;i<numberOfProfiles;i++) { if (base->iccProfileList->text(i) == profileName) { return i; } } return -1; } int KICCConfig::findScreenIndex(TQString screenName) { int i; for (i=0;i<(base->randrScreenList->count());i++) { if (base->randrScreenList->text(i) == screenName) { return i; } } return -1; } void KICCConfig::load(bool useDefaults ) { //Update the toggle buttons with the current configuration int i; int j; // FIXME Should use font size (basically resultant string length) to set button widths... base->addProfileButton->setFixedWidth(110); base->renameProfileButton->setFixedWidth(90); base->deleteProfileButton->setFixedWidth(90); XRROutputInfo *output_info; KRandrSimpleAPI *randrsimple = new KRandrSimpleAPI(); if (config) { config->setReadDefaults( useDefaults ); config->setGroup(NULL); base->enableSupport->setChecked(config->readBoolEntry("EnableICC", false)); base->randrScreenList->setEnabled(config->readBoolEntry("EnableICC", false)); base->iccProfileList->setEnabled(config->readBoolEntry("EnableICC", false)); base->iccFile->setEnabled(config->readBoolEntry("EnableICC", false)); base->addProfileButton->setEnabled(config->readBoolEntry("EnableICC", false)); base->renameProfileButton->setEnabled(config->readBoolEntry("EnableICC", false)); base->deleteProfileButton->setEnabled(config->readBoolEntry("EnableICC", false)); numberOfScreens = 0; if (randrsimple->isValid() == true) { randr_display = XOpenDisplay(NULL); randr_screen_info = randrsimple->read_screen_info(randr_display); for (i = 0; i < randr_screen_info->n_output; i++) { output_info = randr_screen_info->outputs[i]->info; base->randrScreenList->insertItem(output_info->name, -1); numberOfScreens++; } } else { base->randrScreenList->insertItem("Default", -1); numberOfScreens++; } // Find all profile names numberOfProfiles = 0; cfgProfiles = config->groupList(); for (TQStringList::Iterator i(cfgProfiles.begin()); i != cfgProfiles.end(); ++i) { base->iccProfileList->insertItem((*i), -1); numberOfProfiles++; } if (numberOfProfiles == 0) { base->iccProfileList->insertItem("<default>", -1); numberOfProfiles++; } // Load all profiles into memory iccFileArray = new TQString[numberOfProfiles*numberOfScreens]; for (i=0;i<(base->iccProfileList->count());i++) { config->setGroup(base->iccProfileList->text(i)); for (j=0;j<(base->randrScreenList->count());j++) { iccFileArray[(i*(base->randrScreenList->count()))+j] = config->readEntry(base->randrScreenList->text(j)); } } if ((findProfileIndex(base->iccProfileList->currentText()) >= 0) && (findScreenIndex(base->randrScreenList->currentText()) >= 0)) { base->iccFile->setURL(iccFileArray[(findProfileIndex(base->iccProfileList->currentText())*base->randrScreenList->count())+findScreenIndex(base->randrScreenList->currentText())]); } else { base->iccFile->setURL(""); } } else { base->enableSupport->setChecked(false); base->randrScreenList->setEnabled(false); base->iccProfileList->setEnabled(false); base->iccFile->setEnabled(false); base->addProfileButton->setEnabled(false); base->renameProfileButton->setEnabled(false); base->deleteProfileButton->setEnabled(false); } systemconfig->setGroup(NULL); base->systemEnableSupport->setChecked(systemconfig->readBoolEntry("EnableICC", false)); base->systemIccFile->setEnabled(systemconfig->readBoolEntry("EnableICC", false)); base->systemIccFile->setURL(systemconfig->readEntry("ICCFile")); delete randrsimple; emit changed(useDefaults); } void KICCConfig::save() { int i; int j; KRandrSimpleAPI *randrsimple = new KRandrSimpleAPI(); // Write system configuration systemconfig->setGroup(NULL); systemconfig->writeEntry("EnableICC", base->systemEnableSupport->isChecked()); systemconfig->writeEntry("ICCFile", base->systemIccFile->url()); systemconfig->sync(); if (config) { // Write user configuration config->setGroup(NULL); config->writeEntry("DefaultProfile", m_defaultProfile); config->writeEntry("EnableICC", base->enableSupport->isChecked()); // Save all profiles to disk for (i=0;i<(base->iccProfileList->count());i++) { config->setGroup(base->iccProfileList->text(i)); for (j=0;j<(base->randrScreenList->count());j++) { config->writeEntry(base->randrScreenList->text(j), iccFileArray[(i*(base->randrScreenList->count()))+j]); } } config->sync(); } TQString errorstr; if (base->enableSupport->isChecked() == true) { errorstr = randrsimple->applyIccConfiguration(base->iccProfileList->currentText(), KDE_CONFDIR); } else if (base->systemEnableSupport->isChecked() == true) { errorstr = randrsimple->applySystemWideIccConfiguration(KDE_CONFDIR); } else { errorstr = randrsimple->clearIccConfiguration(); } if (errorstr != "") { KMessageBox::error(this, TQString("Unable to apply ICC configuration:\n%1").arg(errorstr)); } emit changed(false); } void KICCConfig::defaults() { load( true ); } TQString KICCConfig::quickHelp() const { return i18n("<h1>ICC Profile Configuration</h1> This module allows you to configure TDE support" " for ICC profiles. This allows you to easily color correct your monitor" " for a more lifelike and vibrant image."); } #include "iccconfig.moc"