• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Konsole

EditProfileDialog.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or
00007     (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software
00016     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301  USA.
00018 */
00019 
00020 // Own
00021 #include "EditProfileDialog.h"
00022 
00023 // Qt
00024 #include <QtGui/QKeyEvent>
00025 #include <QtGui/QBrush>
00026 #include <QtGui/QPainter>
00027 #include <QtGui/QStandardItem>
00028 #include <KDebug>
00029 #include <QtCore/QTextCodec>
00030 #include <QtGui/QTextEdit>
00031 #include <QtGui/QLinearGradient>
00032 #include <QtGui/QRadialGradient>
00033 
00034 #include <QtCore/QTimer>
00035 #include <QtCore/QTimeLine>
00036 
00037 // KDE
00038 #include <kcodecaction.h>
00039 #include <KDebug>
00040 #include <KFontDialog>
00041 #include <KIcon>
00042 #include <KIconDialog>
00043 #include <KFileDialog>
00044 #include <KUrlCompletion>
00045 #include <KWindowSystem>
00046 
00047 // Konsole
00048 #include "ColorScheme.h"
00049 #include "ColorSchemeEditor.h"
00050 #include "ui_EditProfileDialog.h"
00051 #include "KeyBindingEditor.h"
00052 #include "KeyboardTranslator.h"
00053 #include "Profile.h"
00054 #include "SessionManager.h"
00055 #include "ShellCommand.h"
00056 #include "TabTitleFormatAction.h"
00057 
00058 using namespace Konsole;
00059 
00060 EditProfileDialog::EditProfileDialog(QWidget* parent)
00061     : KDialog(parent)
00062     , _colorSchemeAnimationTimeLine(0)
00063     , _delayedPreviewTimer(new QTimer(this))
00064 {
00065     setCaption(i18n("Edit Profile"));
00066     setButtons( KDialog::Ok | KDialog::Cancel | KDialog::Apply );
00067 
00068     connect( this , SIGNAL(applyClicked()) , this , SLOT(save()) );
00069     connect( _delayedPreviewTimer , SIGNAL(timeout()) , this , SLOT(delayedPreviewActivate()) );
00070     _ui = new Ui::EditProfileDialog();
00071     _ui->setupUi(mainWidget());
00072 
00073     // TODO - Renable in a later KDE 4.x release when this feature works again
00074     _ui->enableResizeWindowButton->setVisible(false);
00075 
00076 
00077     // there are various setupXYZPage() methods to load the items
00078     // for each page and update their states to match the profile
00079     // being edited.
00080     //
00081     // these are only called when needed ( ie. when the user clicks
00082     // the tab to move to that page ).
00083     //
00084     // the _pageNeedsUpdate vector keeps track of the pages that have
00085     // not been updated since the last profile change and will need
00086     // to be refreshed when the user switches to them
00087     _pageNeedsUpdate.resize( _ui->tabWidget->count() );
00088     connect( _ui->tabWidget , SIGNAL(currentChanged(int)) , this , 
00089             SLOT(preparePage(int)) );
00090 
00091     _tempProfile = new Profile;
00092 }
00093 EditProfileDialog::~EditProfileDialog()
00094 {
00095     delete _ui;
00096     delete _tempProfile;
00097 }
00098 void EditProfileDialog::save()
00099 {
00100     if ( _tempProfile->isEmpty() )
00101         return;
00102 
00103     SessionManager::instance()->changeProfile(_profileKey,_tempProfile->setProperties());
00104 
00105     // ensure that these settings are not undone by a call
00106     // to unpreview()
00107     QHashIterator<Profile::Property,QVariant> iter(_tempProfile->setProperties());
00108     while ( iter.hasNext() )
00109     {
00110         iter.next();
00111         _previewedProperties.remove(iter.key());
00112     }
00113 }
00114 void EditProfileDialog::reject()
00115 {
00116     unpreviewAll();
00117     KDialog::reject();
00118 }
00119 void EditProfileDialog::accept()
00120 {
00121     save();
00122     unpreviewAll();
00123     KDialog::accept(); 
00124 }
00125 void EditProfileDialog::updateCaption(const QString& profileName)
00126 {
00127     setCaption( i18n("Edit Profile \"%1\"",profileName) );
00128 }
00129 void EditProfileDialog::setProfile(const QString& key)
00130 {
00131     _profileKey = key;
00132 
00133     const Profile* info = SessionManager::instance()->profile(key);
00134 
00135     Q_ASSERT( info );
00136 
00137     // update caption
00138     updateCaption(info->name());
00139 
00140     // mark each page of the dialog as out of date
00141     // and force an update of the currently visible page
00142     //
00143     // the other pages will be updated as necessary
00144     _pageNeedsUpdate.fill(true);
00145     preparePage( _ui->tabWidget->currentIndex() );
00146 
00147     if ( _tempProfile )
00148     {
00149         delete _tempProfile;
00150         _tempProfile = new Profile;
00151     }
00152 }
00153 const Profile* EditProfileDialog::lookupProfile() const
00154 {
00155     return SessionManager::instance()->profile(_profileKey);
00156 }
00157 void EditProfileDialog::preparePage(int page)
00158 {
00159     const Profile* info = lookupProfile();
00160 
00161     Q_ASSERT( _pageNeedsUpdate.count() > page );
00162     Q_ASSERT( info );
00163 
00164     QWidget* pageWidget = _ui->tabWidget->widget(page);
00165     
00166     if ( _pageNeedsUpdate[page] )
00167     {
00168        if ( pageWidget == _ui->generalTab )
00169             setupGeneralPage(info);
00170        else if ( pageWidget == _ui->tabsTab )
00171             setupTabsPage(info);
00172        else if ( pageWidget == _ui->appearanceTab )
00173             setupAppearancePage(info);
00174        else if ( pageWidget == _ui->scrollingTab )
00175             setupScrollingPage(info);
00176        else if ( pageWidget == _ui->keyboardTab )
00177             setupKeyboardPage(info);
00178        else if ( pageWidget == _ui->advancedTab )
00179             setupAdvancedPage(info);
00180        else
00181            Q_ASSERT(false);
00182 
00183         _pageNeedsUpdate[page] = false;
00184     }
00185 
00186     // start page entry animation for color schemes
00187     if ( pageWidget == _ui->appearanceTab )
00188             _colorSchemeAnimationTimeLine->start();
00189 }
00190 void EditProfileDialog::selectProfileName()
00191 {
00192     _ui->profileNameEdit->selectAll();
00193     _ui->profileNameEdit->setFocus();
00194 }
00195 void EditProfileDialog::setupGeneralPage(const Profile* info)
00196 {
00197 
00198     // basic profile options
00199     _ui->profileNameEdit->setText( info->name() );
00200 
00201     ShellCommand command( info->command() , info->arguments() );
00202     _ui->commandEdit->setText( command.fullCommand() );
00203 
00204     KUrlCompletion* exeCompletion = new KUrlCompletion(KUrlCompletion::ExeCompletion);
00205     exeCompletion->setParent(this);
00206     exeCompletion->setDir(QString());
00207     _ui->commandEdit->setCompletionObject( exeCompletion );
00208     _ui->initialDirEdit->setText( info->defaultWorkingDirectory() );
00209 
00210     KUrlCompletion* dirCompletion = new KUrlCompletion(KUrlCompletion::DirCompletion);
00211     dirCompletion->setParent(this);
00212     _ui->initialDirEdit->setCompletionObject( dirCompletion );
00213     _ui->initialDirEdit->setClearButtonShown(true);
00214     _ui->dirSelectButton->setIcon( KIcon("folder-open") );
00215     _ui->iconSelectButton->setIcon( KIcon(info->icon()) );
00216 
00217     // window options
00218     _ui->showMenuBarButton->setChecked( info->property(Profile::ShowMenuBar).value<bool>() );
00219 
00220     // signals and slots
00221     connect( _ui->dirSelectButton , SIGNAL(clicked()) , this , SLOT(selectInitialDir()) );
00222     connect( _ui->iconSelectButton , SIGNAL(clicked()) , this , SLOT(selectIcon()) );
00223 
00224     connect( _ui->profileNameEdit , SIGNAL(textChanged(const QString&)) , this ,
00225             SLOT(profileNameChanged(const QString&)) );
00226     connect( _ui->initialDirEdit , SIGNAL(textChanged(const QString&)) , this , 
00227             SLOT(initialDirChanged(const QString&)) );
00228     connect(_ui->commandEdit , SIGNAL(textChanged(const QString&)) , this ,
00229             SLOT(commandChanged(const QString&)) ); 
00230     
00231     connect(_ui->showMenuBarButton , SIGNAL(toggled(bool)) , this , 
00232             SLOT(showMenuBar(bool)) );
00233 
00234     connect(_ui->environmentEditButton , SIGNAL(clicked()) , this , 
00235             SLOT(showEnvironmentEditor()) );
00236 }
00237 void EditProfileDialog::showEnvironmentEditor()
00238 {
00239     const Profile* info = lookupProfile();
00240 
00241     KDialog* dialog = new KDialog(this);
00242     QTextEdit* edit = new QTextEdit(dialog);
00243 
00244     QStringList currentEnvironment = info->property(Profile::Environment).value<QStringList>();
00245 
00246     edit->setPlainText( currentEnvironment.join("\n") );
00247     dialog->setPlainCaption(i18n("Edit Environment"));
00248     dialog->setMainWidget(edit);
00249 
00250     if ( dialog->exec() == QDialog::Accepted )
00251     {
00252         QStringList newEnvironment = edit->toPlainText().split('\n');
00253         _tempProfile->setProperty(Profile::Environment,newEnvironment);
00254     }
00255 
00256     dialog->deleteLater();
00257 }
00258 void EditProfileDialog::setupTabsPage(const Profile* info)
00259 {
00260     // tab title format
00261     _ui->tabTitleEdit->setClearButtonShown(true);
00262     _ui->remoteTabTitleEdit->setClearButtonShown(true);
00263     _ui->tabTitleEdit->setText( info->property(Profile::LocalTabTitleFormat).value<QString>() );
00264     _ui->remoteTabTitleEdit->setText( 
00265             info->property(Profile::RemoteTabTitleFormat).value<QString>());
00266 
00267     // tab options
00268     int tabMode = info->property(Profile::TabBarMode).value<int>();
00269     int tabPosition = info->property(Profile::TabBarPosition).value<int>();
00270 
00271     // note: Items should be in the same order as the 
00272     // Profile::TabBarModeEnum enum
00273     _ui->tabBarVisibilityCombo->addItems( QStringList() << i18n("Always hide tab bar")
00274                                                         << i18n("Show tab bar when needed") 
00275                                                         << i18n("Always show tab bar") );
00276     _ui->tabBarVisibilityCombo->setCurrentIndex(tabMode);
00277 
00278     // note: Items should be in the same order as the
00279     // Profile::TabBarPositionEnum enum
00280     _ui->tabBarPositionCombo->addItems( QStringList() << i18n("Below terminal displays")
00281                                                       << i18n("Above terminal displays") );
00282 
00283     _ui->tabBarPositionCombo->setCurrentIndex(tabPosition);
00284 
00285     // signals and slots
00286     connect( _ui->tabBarVisibilityCombo , SIGNAL(activated(int)) , this , 
00287              SLOT(tabBarVisibilityChanged(int)) );
00288     connect( _ui->tabBarPositionCombo , SIGNAL(activated(int)) , this ,
00289              SLOT(tabBarPositionChanged(int)) );
00290 
00291     connect(_ui->tabTitleEdit , SIGNAL(textChanged(const QString&)) , this ,
00292             SLOT(tabTitleFormatChanged(const QString&)) );
00293     connect(_ui->remoteTabTitleEdit , SIGNAL(textChanged(const QString&)) , this ,
00294             SLOT(remoteTabTitleFormatChanged(const QString&)));
00295 
00296     // menus for local and remote tab title dynamic elements
00297     TabTitleFormatAction* localTabTitleAction = new TabTitleFormatAction(this);
00298     localTabTitleAction->setContext(Session::LocalTabTitle);
00299     _ui->tabTitleEditButton->setMenu(localTabTitleAction->menu());
00300     connect( localTabTitleAction , SIGNAL(dynamicElementSelected(const QString&)) , 
00301             this , SLOT(insertTabTitleText(const QString&)) );
00302 
00303     TabTitleFormatAction* remoteTabTitleAction = new TabTitleFormatAction(this);
00304     remoteTabTitleAction->setContext(Session::RemoteTabTitle);
00305     _ui->remoteTabTitleEditButton->setMenu(remoteTabTitleAction->menu());
00306     connect( remoteTabTitleAction , SIGNAL(dynamicElementSelected(const QString&)) ,
00307            this , SLOT(insertRemoteTabTitleText(const QString&)) ); 
00308 }
00309 void EditProfileDialog::tabBarVisibilityChanged(int newValue)
00310 {
00311     _tempProfile->setProperty( Profile::TabBarMode , newValue );
00312 }
00313 void EditProfileDialog::tabBarPositionChanged(int newValue)
00314 {
00315     _tempProfile->setProperty( Profile::TabBarPosition , newValue );
00316 }
00317 void EditProfileDialog::insertTabTitleText(const QString& text)
00318 {
00319     _ui->tabTitleEdit->insert(text);
00320 }
00321 void EditProfileDialog::insertRemoteTabTitleText(const QString& text)
00322 {
00323     _ui->remoteTabTitleEdit->insert(text);
00324 }
00325 void EditProfileDialog::showMenuBar(bool show)
00326 {
00327     _tempProfile->setProperty(Profile::ShowMenuBar,show);
00328 }
00329 void EditProfileDialog::tabTitleFormatChanged(const QString& format)
00330 {
00331     _tempProfile->setProperty(Profile::LocalTabTitleFormat,format);
00332 }
00333 void EditProfileDialog::remoteTabTitleFormatChanged(const QString& format)
00334 {
00335     _tempProfile->setProperty(Profile::RemoteTabTitleFormat,format);
00336 }
00337 
00338 void EditProfileDialog::selectIcon()
00339 {
00340     const QString& icon = KIconDialog::getIcon(KIconLoader::Desktop, KIconLoader::Application,
00341                                                false, 0, false, this);
00342     if (!icon.isEmpty())
00343     {
00344         _ui->iconSelectButton->setIcon( KIcon(icon) );
00345         _tempProfile->setProperty(Profile::Icon,icon);
00346     }
00347 }
00348 void EditProfileDialog::profileNameChanged(const QString& text)
00349 {
00350     _tempProfile->setProperty(Profile::Name,text);
00351     updateCaption(_tempProfile->name());
00352 }
00353 void EditProfileDialog::initialDirChanged(const QString& dir)
00354 {
00355     _tempProfile->setProperty(Profile::Directory,dir);
00356 }
00357 void EditProfileDialog::commandChanged(const QString& command)
00358 {
00359     ShellCommand shellCommand(command);
00360 
00361     _tempProfile->setProperty(Profile::Command,shellCommand.command());
00362     _tempProfile->setProperty(Profile::Arguments,shellCommand.arguments());
00363 }
00364 void EditProfileDialog::selectInitialDir()
00365 {
00366     const KUrl url = KFileDialog::getExistingDirectoryUrl(_ui->initialDirEdit->text(),
00367                                                           this,
00368                                                           i18n("Select Initial Directory"));
00369 
00370     if ( !url.isEmpty() )
00371         _ui->initialDirEdit->setText(url.path());
00372 }
00373 void EditProfileDialog::setupAppearancePage(const Profile* info)
00374 {
00375     ColorSchemeViewDelegate* delegate = new ColorSchemeViewDelegate(this);
00376     _ui->colorSchemeList->setItemDelegate(delegate);
00377     
00378     _colorSchemeAnimationTimeLine = new QTimeLine( 500 , this );
00379     delegate->setEntryTimeLine(_colorSchemeAnimationTimeLine);
00380     
00381     connect( _colorSchemeAnimationTimeLine , SIGNAL(valueChanged(qreal)) , this ,
00382              SLOT(colorSchemeAnimationUpdate()) );
00383    
00384     _ui->transparencyWarningWidget->setVisible(false);
00385     _ui->editColorSchemeButton->setEnabled(false);
00386     _ui->removeColorSchemeButton->setEnabled(false);
00387 
00388     // setup color list
00389     updateColorSchemeList(true);
00390     
00391     _ui->colorSchemeList->setMouseTracking(true);
00392     _ui->colorSchemeList->installEventFilter(this);
00393     _ui->colorSchemeList->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
00394 
00395     connect( _ui->colorSchemeList->selectionModel() , 
00396             SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)) 
00397             , this , SLOT(colorSchemeSelected()) );
00398     connect( _ui->colorSchemeList , SIGNAL(entered(const QModelIndex&)) , this , 
00399             SLOT(previewColorScheme(const QModelIndex&)) );
00400     
00401     updateColorSchemeButtons();
00402 
00403     connect( _ui->editColorSchemeButton , SIGNAL(clicked()) , this , 
00404             SLOT(editColorScheme()) );
00405     connect( _ui->removeColorSchemeButton , SIGNAL(clicked()) , this ,
00406             SLOT(removeColorScheme()) );
00407     connect( _ui->newColorSchemeButton , SIGNAL(clicked()) , this , 
00408             SLOT(newColorScheme()) );
00409 
00410     // setup font preview
00411     const QFont& font = info->font();
00412     _ui->fontPreviewLabel->installEventFilter(this);
00413     _ui->fontPreviewLabel->setFont(font);
00414     _ui->fontSizeSlider->setValue( font.pointSize() );
00415     _ui->fontSizeSlider->setMinimum( KGlobalSettings::smallestReadableFont().pointSize() );
00416 
00417     connect( _ui->fontSizeSlider , SIGNAL(valueChanged(int)) , this ,
00418              SLOT(setFontSize(int)) );
00419     connect( _ui->editFontButton , SIGNAL(clicked()) , this ,
00420              SLOT(showFontDialog()) );
00421 }
00422 void EditProfileDialog::colorSchemeAnimationUpdate()
00423 {
00424     QAbstractItemModel* model = _ui->colorSchemeList->model();
00425 
00426     for ( int i = model->rowCount() ; i >= 0 ; i-- )
00427         _ui->colorSchemeList->update( model->index(i,0) );
00428 }
00429 void EditProfileDialog::updateColorSchemeList(bool selectCurrentScheme)
00430 {
00431     if (!_ui->colorSchemeList->model())
00432         _ui->colorSchemeList->setModel(new QStandardItemModel(this));
00433 
00434     const QString& name = lookupProfile()->colorScheme();
00435     const ColorScheme* currentScheme = ColorSchemeManager::instance()->findColorScheme(name);
00436 
00437     QStandardItemModel* model = qobject_cast<QStandardItemModel*>(_ui->colorSchemeList->model());
00438 
00439     Q_ASSERT(model);
00440     
00441     model->clear();
00442 
00443     QList<const ColorScheme*> schemeList = ColorSchemeManager::instance()->allColorSchemes();
00444     QListIterator<const ColorScheme*> schemeIter(schemeList);
00445 
00446     QStandardItem* selectedItem = 0;
00447 
00448     while (schemeIter.hasNext())
00449     {
00450         const ColorScheme* colors = schemeIter.next();
00451         QStandardItem* item = new QStandardItem(colors->description());
00452         item->setData( QVariant::fromValue(colors) ,  Qt::UserRole + 1);
00453         item->setFlags( item->flags() );
00454        
00455         if ( currentScheme == colors ) 
00456             selectedItem = item;  
00457 
00458         model->appendRow(item);
00459     }
00460 
00461     model->sort(0);
00462 
00463     if ( selectCurrentScheme && selectedItem )
00464     {
00465         _ui->colorSchemeList->updateGeometry();
00466         _ui->colorSchemeList->selectionModel()->setCurrentIndex( selectedItem->index() , 
00467                                                                  QItemSelectionModel::Select );
00468 
00469         // update transparency warning label
00470         updateTransparencyWarning();
00471     }
00472 }
00473 void EditProfileDialog::updateKeyBindingsList(bool selectCurrentTranslator)
00474 {
00475     if (!_ui->keyBindingList->model())
00476         _ui->keyBindingList->setModel(new QStandardItemModel(this));
00477 
00478     KeyboardTranslatorManager* keyManager = KeyboardTranslatorManager::instance();
00479 
00480     const QString& name = lookupProfile()
00481                                     ->property(Profile::KeyBindings).value<QString>();
00482 
00483     const KeyboardTranslator* currentTranslator = keyManager->findTranslator(name);
00484     
00485     QStandardItemModel* model = qobject_cast<QStandardItemModel*>(_ui->keyBindingList->model());
00486 
00487     Q_ASSERT(model);
00488 
00489     model->clear();
00490 
00491     QStandardItem* selectedItem = 0;
00492 
00493     QList<QString> translatorNames = keyManager->allTranslators();
00494     QListIterator<QString> iter(translatorNames);
00495     while (iter.hasNext())
00496     {
00497         const QString& name = iter.next();
00498 
00499         const KeyboardTranslator* translator = keyManager->findTranslator(name);
00500 
00501         QStandardItem* item = new QStandardItem(translator->description());
00502         item->setData(QVariant::fromValue(translator),Qt::UserRole+1);
00503         item->setIcon( KIcon("keyboard") );
00504 
00505         if ( translator == currentTranslator )
00506             selectedItem = item;
00507 
00508         model->appendRow(item);
00509     }
00510 
00511     model->sort(0);
00512     
00513     if ( selectCurrentTranslator && selectedItem )
00514     {
00515         _ui->keyBindingList->selectionModel()->setCurrentIndex( selectedItem->index() , 
00516                                                                   QItemSelectionModel::Select );
00517     }
00518 }
00519 bool EditProfileDialog::eventFilter( QObject* watched , QEvent* event )
00520 {
00521     if ( watched == _ui->colorSchemeList && event->type() == QEvent::Leave )
00522     {
00523         if ( _tempProfile->isPropertySet(Profile::ColorScheme) )
00524             preview(Profile::ColorScheme,_tempProfile->colorScheme());
00525         else
00526             unpreview(Profile::ColorScheme);
00527     }
00528     if ( watched == _ui->fontPreviewLabel && event->type() == QEvent::FontChange )
00529     {
00530         const QFont& labelFont = _ui->fontPreviewLabel->font();
00531         _ui->fontPreviewLabel->setText(i18n("%1, size %2",labelFont.family(),labelFont.pointSize()));
00532     }
00533 
00534     return KDialog::eventFilter(watched,event);
00535 }
00536 void EditProfileDialog::unpreviewAll()
00537 {
00538     _delayedPreviewTimer->stop();
00539     _delayedPreviewProperties.clear();
00540 
00541     QHash<Profile::Property,QVariant> map;
00542     QHashIterator<int,QVariant> iter(_previewedProperties);
00543     while ( iter.hasNext() )
00544     {
00545         iter.next();
00546         map.insert((Profile::Property)iter.key(),iter.value());
00547     }
00548 
00549     // undo any preview changes
00550     if ( !map.isEmpty() )
00551         SessionManager::instance()->changeProfile(_profileKey,map,false);
00552 }
00553 void EditProfileDialog::unpreview(int property)
00554 {
00555     _delayedPreviewProperties.remove(property);
00556     
00557     if (!_previewedProperties.contains(property))
00558         return;
00559     
00560     QHash<Profile::Property,QVariant> map;
00561     map.insert((Profile::Property)property,_previewedProperties[property]);
00562     SessionManager::instance()->changeProfile(_profileKey,map,false); 
00563 
00564     _previewedProperties.remove(property);
00565 }
00566 void EditProfileDialog::delayedPreview(int property , const QVariant& value)
00567 {
00568     _delayedPreviewProperties.insert(property,value); 
00569     QTimer* timer = new QTimer(this);
00570     timer->setSingleShot(true);
00571 
00572     _delayedPreviewTimer->stop();
00573     _delayedPreviewTimer->start(300);    
00574 }
00575 void EditProfileDialog::delayedPreviewActivate()
00576 {
00577     Q_ASSERT( qobject_cast<QTimer*>(sender()) );
00578 
00579     QMutableHashIterator<int,QVariant> iter(_delayedPreviewProperties);
00580     if ( iter.hasNext() ) 
00581     {
00582         iter.next();
00583         preview(iter.key(),iter.value());
00584     }
00585 }
00586 void EditProfileDialog::preview(int property , const QVariant& value)
00587 {
00588     QHash<Profile::Property,QVariant> map;
00589     map.insert((Profile::Property)property,value);
00590     
00591     _delayedPreviewProperties.remove(property);
00592 
00593     const Profile* original = lookupProfile();
00594 
00595     if (!_previewedProperties.contains(property))    
00596         _previewedProperties.insert(property , original->property((Profile::Property)property) );
00597 
00598     // temporary change to color scheme
00599     SessionManager::instance()->changeProfile( _profileKey , map , false);
00600 }
00601 void EditProfileDialog::previewColorScheme(const QModelIndex& index)
00602 {
00603     const QString& name = index.data(Qt::UserRole+1).value<const ColorScheme*>()->name();
00604 
00605     delayedPreview( Profile::ColorScheme , name );
00606 }
00607 void EditProfileDialog::removeColorScheme()
00608 {
00609     QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes();
00610 
00611     if ( !selected.isEmpty() )
00612     {
00613         const QString& name = selected.first().data(Qt::UserRole+1).value<const ColorScheme*>()->name();
00614         
00615         if (ColorSchemeManager::instance()->deleteColorScheme(name))    
00616             _ui->colorSchemeList->model()->removeRow(selected.first().row());
00617     }
00618 }
00619 void EditProfileDialog::showColorSchemeEditor(bool isNewScheme)
00620 {    
00621     QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes();
00622 
00623     QAbstractItemModel* model = _ui->colorSchemeList->model();
00624     const ColorScheme* colors = 0;
00625     if ( !selected.isEmpty() )
00626         colors = model->data(selected.first(),Qt::UserRole+1).value<const ColorScheme*>();
00627     else
00628         colors = ColorSchemeManager::instance()->defaultColorScheme();
00629 
00630     Q_ASSERT(colors);
00631 
00632     KDialog* dialog = new KDialog(this);
00633 
00634     if ( isNewScheme )
00635         dialog->setCaption(i18n("New Color Scheme"));
00636     else
00637         dialog->setCaption(i18n("Edit Color Scheme"));
00638 
00639     ColorSchemeEditor* editor = new ColorSchemeEditor;
00640     dialog->setMainWidget(editor);
00641     editor->setup(colors);
00642 
00643     if ( isNewScheme )
00644         editor->setDescription(i18n("New Color Scheme"));
00645         
00646     if ( dialog->exec() == QDialog::Accepted )
00647     {
00648         ColorScheme* newScheme = new ColorScheme(*editor->colorScheme());
00649 
00650         // if this is a new color scheme, pick a name based on the description
00651         if ( isNewScheme )
00652             newScheme->setName(newScheme->description());
00653 
00654         ColorSchemeManager::instance()->addColorScheme( newScheme );
00655         
00656         updateColorSchemeList(true);
00657 
00658         preview(Profile::ColorScheme,newScheme->name());
00659     }
00660 }
00661 void EditProfileDialog::newColorScheme()
00662 {
00663     showColorSchemeEditor(true);    
00664 }
00665 void EditProfileDialog::editColorScheme()
00666 {
00667     showColorSchemeEditor(false);
00668 }
00669 void EditProfileDialog::colorSchemeSelected()
00670 {
00671     QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes();
00672 
00673     if ( !selected.isEmpty() )
00674     {
00675         QAbstractItemModel* model = _ui->colorSchemeList->model();
00676         const ColorScheme* colors = model->data(selected.first(),Qt::UserRole+1).value<const ColorScheme*>();
00677 
00678         kDebug() << "Setting temp profile color to" << colors->name();
00679         
00680         previewColorScheme(selected.first());
00681         _tempProfile->setProperty(Profile::ColorScheme,colors->name());
00682 
00683         updateTransparencyWarning();
00684     }
00685 
00686     updateColorSchemeButtons();
00687 }
00688 void EditProfileDialog::updateColorSchemeButtons()
00689 {
00690     enableIfNonEmptySelection(_ui->editColorSchemeButton,_ui->colorSchemeList->selectionModel());
00691     enableIfNonEmptySelection(_ui->removeColorSchemeButton,_ui->colorSchemeList->selectionModel());
00692 }
00693 void EditProfileDialog::updateKeyBindingsButtons()
00694 {    
00695     enableIfNonEmptySelection(_ui->editKeyBindingsButton,_ui->keyBindingList->selectionModel());
00696     enableIfNonEmptySelection(_ui->removeKeyBindingsButton,_ui->keyBindingList->selectionModel());
00697 }
00698 void EditProfileDialog::enableIfNonEmptySelection(QWidget* widget,QItemSelectionModel* selectionModel)
00699 {
00700     widget->setEnabled(selectionModel->hasSelection());
00701 }
00702 void EditProfileDialog::updateTransparencyWarning() 
00703 {
00704     // zero or one indexes can be selected
00705     foreach( const QModelIndex& index , _ui->colorSchemeList->selectionModel()->selectedIndexes() ) 
00706     {
00707         bool hasTransparency = index.data(Qt::UserRole+1).value<const ColorScheme*>()->opacity() < 1.0;
00708 
00709         _ui->transparencyWarningWidget->setHidden(KWindowSystem::compositingActive() || !hasTransparency);
00710         _ui->transparencyWarningIcon->setPixmap( KIcon("dialog-warning").pixmap(QSize(48,48)) );
00711     }
00712 }
00713 void EditProfileDialog::setupKeyboardPage(const Profile* /* info */)
00714 {
00715     // setup translator list
00716     updateKeyBindingsList(true); 
00717 
00718     connect( _ui->keyBindingList->selectionModel() , 
00719                 SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),
00720                 SLOT(keyBindingSelected()) );
00721     connect( _ui->newKeyBindingsButton , SIGNAL(clicked()) , this ,
00722             SLOT(newKeyBinding()) );
00723 
00724     updateKeyBindingsButtons();
00725 
00726     connect( _ui->editKeyBindingsButton , SIGNAL(clicked()) , this , 
00727           SLOT(editKeyBinding()) );  
00728     connect( _ui->removeKeyBindingsButton , SIGNAL(clicked()) , this ,
00729             SLOT(removeKeyBinding()) );
00730 }
00731 void EditProfileDialog::keyBindingSelected()
00732 {
00733     QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes();
00734 
00735     if ( !selected.isEmpty() )
00736     {
00737         QAbstractItemModel* model = _ui->keyBindingList->model();
00738         const KeyboardTranslator* translator = model->data(selected.first(),Qt::UserRole+1)
00739                                                 .value<const KeyboardTranslator*>();
00740         _tempProfile->setProperty(Profile::KeyBindings,translator->name());
00741     }
00742 
00743     updateKeyBindingsButtons();
00744 }
00745 void EditProfileDialog::removeKeyBinding()
00746 {
00747     QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes();
00748 
00749     if ( !selected.isEmpty() )
00750     {
00751         const QString& name = selected.first().data(Qt::UserRole+1).value<const KeyboardTranslator*>()->name();
00752         if (KeyboardTranslatorManager::instance()->deleteTranslator(name))
00753             _ui->keyBindingList->model()->removeRow(selected.first().row());   
00754     }
00755 }
00756 void EditProfileDialog::showKeyBindingEditor(bool isNewTranslator)
00757 {
00758     QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes();
00759     QAbstractItemModel* model = _ui->keyBindingList->model();
00760 
00761     const KeyboardTranslator* translator = 0;
00762     if ( !selected.isEmpty() )
00763         translator = model->data(selected.first(),Qt::UserRole+1).value<const KeyboardTranslator*>();
00764     else
00765         translator = KeyboardTranslatorManager::instance()->defaultTranslator();
00766 
00767     Q_ASSERT(translator);
00768 
00769     KDialog* dialog = new KDialog(this);
00770 
00771     if ( isNewTranslator )
00772         dialog->setCaption(i18n("New Key Binding List"));
00773     else
00774         dialog->setCaption(i18n("Edit Key Binding List"));
00775 
00776     KeyBindingEditor* editor = new KeyBindingEditor;
00777     dialog->setMainWidget(editor);
00778     
00779     if ( translator )
00780         editor->setup(translator);
00781 
00782     if ( isNewTranslator )
00783         editor->setDescription(i18n("New Key Binding List"));
00784 
00785     if ( dialog->exec() == QDialog::Accepted )
00786     {
00787         KeyboardTranslator* newTranslator = new KeyboardTranslator(*editor->translator());
00788 
00789         if ( isNewTranslator )
00790             newTranslator->setName(newTranslator->description());
00791 
00792         KeyboardTranslatorManager::instance()->addTranslator( newTranslator );
00793 
00794         updateKeyBindingsList();
00795         
00796         const QString& currentTranslator = lookupProfile()
00797                                         ->property(Profile::KeyBindings).value<QString>();
00798 
00799         if ( newTranslator->name() == currentTranslator )
00800         {
00801             _tempProfile->setProperty(Profile::KeyBindings,newTranslator->name());
00802         }
00803     }
00804 }
00805 void EditProfileDialog::newKeyBinding()
00806 {
00807     showKeyBindingEditor(true);
00808 }
00809 void EditProfileDialog::editKeyBinding()
00810 {
00811     showKeyBindingEditor(false);
00812 }
00813 void EditProfileDialog::setupCombo( ComboOption* options , const Profile* profile )
00814 {
00815     while ( options->button != 0 )
00816     {
00817         options->button->setChecked( profile->property((Profile::Property)options->property).value<bool>() );
00818         connect( options->button , SIGNAL(toggled(bool)) , this , options->slot );
00819 
00820         ++options;
00821     }
00822 }
00823 void EditProfileDialog::setupRadio( RadioOption* possible , int actual )
00824 {
00825     while (possible->button != 0)
00826     {
00827         if ( possible->property == actual )
00828             possible->button->setChecked(true);
00829         else
00830             possible->button->setChecked(false);
00831    
00832         connect( possible->button , SIGNAL(clicked()) , this , possible->slot );
00833 
00834         ++possible;
00835     }
00836 }
00837 
00838 void EditProfileDialog::setupScrollingPage(const Profile* profile)
00839 {
00840     // setup scrollbar radio
00841     int scrollBarPosition = profile->property(Profile::ScrollBarPosition).value<int>();
00842    
00843     RadioOption positions[] = { {_ui->scrollBarHiddenButton,Profile::ScrollBarHidden,SLOT(hideScrollBar())},
00844                                 {_ui->scrollBarLeftButton,Profile::ScrollBarLeft,SLOT(showScrollBarLeft())},
00845                                 {_ui->scrollBarRightButton,Profile::ScrollBarRight,SLOT(showScrollBarRight())},
00846                                 {0,0,0} 
00847                               }; 
00848 
00849     setupRadio( positions , scrollBarPosition );
00850    
00851     // setup scrollback type radio
00852     int scrollBackType = profile->property(Profile::HistoryMode).value<int>();
00853     
00854     RadioOption types[] = { {_ui->disableScrollbackButton,Profile::DisableHistory,SLOT(noScrollBack())},
00855                             {_ui->fixedScrollbackButton,Profile::FixedSizeHistory,SLOT(fixedScrollBack())},
00856                             {_ui->unlimitedScrollbackButton,Profile::UnlimitedHistory,SLOT(unlimitedScrollBack())},
00857                             {0,0,0} };
00858     setupRadio( types , scrollBackType ); 
00859     
00860     // setup scrollback line count spinner
00861     _ui->scrollBackLinesSpinner->setValue( profile->property(Profile::HistorySize).value<int>() );
00862 
00863     // signals and slots
00864     connect( _ui->scrollBackLinesSpinner , SIGNAL(valueChanged(int)) , this , 
00865             SLOT(scrollBackLinesChanged(int)) );
00866 }
00867 
00868 void EditProfileDialog::scrollBackLinesChanged(int lineCount)
00869 {
00870     _tempProfile->setProperty(Profile::HistorySize , lineCount);
00871 }
00872 void EditProfileDialog::noScrollBack()
00873 {
00874     _tempProfile->setProperty(Profile::HistoryMode , Profile::DisableHistory);
00875 }
00876 void EditProfileDialog::fixedScrollBack()
00877 {
00878     _tempProfile->setProperty(Profile::HistoryMode , Profile::FixedSizeHistory);
00879 }
00880 void EditProfileDialog::unlimitedScrollBack()
00881 {
00882     _tempProfile->setProperty(Profile::HistoryMode , Profile::UnlimitedHistory );
00883 }
00884 void EditProfileDialog::hideScrollBar()
00885 {
00886     _tempProfile->setProperty(Profile::ScrollBarPosition , Profile::ScrollBarHidden );
00887 }
00888 void EditProfileDialog::showScrollBarLeft()
00889 {
00890     _tempProfile->setProperty(Profile::ScrollBarPosition , Profile::ScrollBarLeft );
00891 }
00892 void EditProfileDialog::showScrollBarRight()
00893 {
00894     _tempProfile->setProperty(Profile::ScrollBarPosition , Profile::ScrollBarRight );
00895 }
00896 void EditProfileDialog::setupAdvancedPage(const Profile* profile)
00897 {
00898     ComboOption  options[] = { { _ui->enableBlinkingTextButton , Profile::BlinkingTextEnabled , 
00899                                  SLOT(toggleBlinkingText(bool)) },
00900                                { _ui->enableFlowControlButton , Profile::FlowControlEnabled ,
00901                                  SLOT(toggleFlowControl(bool)) },
00902                                { _ui->enableResizeWindowButton , Profile::AllowProgramsToResizeWindow ,
00903                                  SLOT(toggleResizeWindow(bool)) },
00904                                { _ui->enableBlinkingCursorButton , Profile::BlinkingCursorEnabled ,
00905                                  SLOT(toggleBlinkingCursor(bool)) },
00906                                { 0 , 0 , 0 }
00907                              };
00908     setupCombo( options , profile );
00909 
00910     // interaction options
00911     _ui->wordCharacterEdit->setText( profile->