EditProfileDialog.cpp 41.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
    Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>

    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.
*/

20
21
22
// Own
#include "EditProfileDialog.h"

23
// Qt
Dirk Mueller's avatar
Dirk Mueller committed
24
25
26
27
#include <QtGui/QKeyEvent>
#include <QtGui/QBrush>
#include <QtGui/QPainter>
#include <QtGui/QStandardItem>
Robert Knight's avatar
   
Robert Knight committed
28
#include <KDebug>
29
#include <QtCore/QTextCodec>
30
#include <QtGui/QTextEdit>
31
32
33
#include <QtGui/QLinearGradient>
#include <QtGui/QRadialGradient>

34
#include <QtCore/QTimer>
35
36
#include <QtCore/QTimeLine>

37
// KDE
38
#include <kcodecaction.h>
Robert Knight's avatar
   
Robert Knight committed
39
#include <KDebug>
40
41
#include <KFontDialog>
#include <KIcon>
42
#include <KIconDialog>
43
#include <KFileDialog>
44
#include <KUrlCompletion>
45
#include <KWindowSystem>
46
47
48

// Konsole
#include "ColorScheme.h"
49
#include "ColorSchemeEditor.h"
50
#include "ui_EditProfileDialog.h"
51
52
#include "KeyBindingEditor.h"
#include "KeyboardTranslator.h"
53
#include "Profile.h"
54
#include "SessionManager.h"
55
#include "ShellCommand.h"
56
#include "TabTitleFormatAction.h"
57
58
59

using namespace Konsole;

60
EditProfileDialog::EditProfileDialog(QWidget* parent)
61
    : KDialog(parent)
Robert Knight's avatar
   
Robert Knight committed
62
    , _colorSchemeAnimationTimeLine(0)
63
    , _delayedPreviewTimer(new QTimer(this))
64
{
65
    setCaption(i18n("Edit Profile"));
66
    setButtons( KDialog::Ok | KDialog::Cancel | KDialog::Apply );
67

68
    connect( this , SIGNAL(applyClicked()) , this , SLOT(save()) );
69
    connect( _delayedPreviewTimer , SIGNAL(timeout()) , this , SLOT(delayedPreviewActivate()) );
70
    _ui = new Ui::EditProfileDialog();
71
    _ui->setupUi(mainWidget());
72

73
    // - Renable in a later KDE 4.x release when this feature works again
74
    _ui->enableResizeWindowButton->setVisible(false);
75
76
77
	
#warning "Re-enable when flow control is working again - bug in KDE 4.1"
	_ui->enableFlowControlButton->setEnabled(false);
78

79
80
81
82
83
84
85
86
87
88
89
    // there are various setupXYZPage() methods to load the items
    // for each page and update their states to match the profile
    // being edited.
    //
    // these are only called when needed ( ie. when the user clicks
    // the tab to move to that page ).
    //
    // the _pageNeedsUpdate vector keeps track of the pages that have
    // not been updated since the last profile change and will need
    // to be refreshed when the user switches to them
    _pageNeedsUpdate.resize( _ui->tabWidget->count() );
90
    connect( _ui->tabWidget , SIGNAL(currentChanged(int)) , this , 
Robert Knight's avatar
   
Robert Knight committed
91
            SLOT(preparePage(int)) );
92

93
    _tempProfile = new Profile;
94
}
95
EditProfileDialog::~EditProfileDialog()
96
97
{
    delete _ui;
98
99
    delete _tempProfile;
}
100
void EditProfileDialog::save()
101
{
102
103
    if ( _tempProfile->isEmpty() )
        return;
104
105

    SessionManager::instance()->changeProfile(_profileKey,_tempProfile->setProperties());
106
107
108
109
110
111
112
113
114
115
116
117
118
119

    // ensure that these settings are not undone by a call
    // to unpreview()
    QHashIterator<Profile::Property,QVariant> iter(_tempProfile->setProperties());
    while ( iter.hasNext() )
    {
        iter.next();
        _previewedProperties.remove(iter.key());
    }
}
void EditProfileDialog::reject()
{
    unpreviewAll();
    KDialog::reject();
120
121
122
123
}
void EditProfileDialog::accept()
{
    save();
124
    unpreviewAll();
125
    KDialog::accept(); 
126
}
Robert Knight's avatar
   
Robert Knight committed
127
128
129
130
void EditProfileDialog::updateCaption(const QString& profileName)
{
    setCaption( i18n("Edit Profile \"%1\"",profileName) );
}
131
void EditProfileDialog::setProfile(const QString& key)
132
{
133
    _profileKey = key;
134

135
    const Profile* info = SessionManager::instance()->profile(key);
136
137
138

    Q_ASSERT( info );

139
    // update caption
Robert Knight's avatar
   
Robert Knight committed
140
    updateCaption(info->name());
141

142
143
144
145
146
    // mark each page of the dialog as out of date
    // and force an update of the currently visible page
    //
    // the other pages will be updated as necessary
    _pageNeedsUpdate.fill(true);
Robert Knight's avatar
   
Robert Knight committed
147
    preparePage( _ui->tabWidget->currentIndex() );
148

149
150
151
152
153
    if ( _tempProfile )
    {
        delete _tempProfile;
        _tempProfile = new Profile;
    }
154
}
155
156
157
158
const Profile* EditProfileDialog::lookupProfile() const
{
    return SessionManager::instance()->profile(_profileKey);
}
Robert Knight's avatar
   
Robert Knight committed
159
void EditProfileDialog::preparePage(int page)
160
{
161
    const Profile* info = lookupProfile();
162

163
    Q_ASSERT( _pageNeedsUpdate.count() > page );
164
165
    Q_ASSERT( info );

Robert Knight's avatar
   
Robert Knight committed
166
167
    QWidget* pageWidget = _ui->tabWidget->widget(page);
    
168
    if ( _pageNeedsUpdate[page] )
169
170
171
    {
       if ( pageWidget == _ui->generalTab )
            setupGeneralPage(info);
172
173
       else if ( pageWidget == _ui->tabsTab )
            setupTabsPage(info);
174
175
176
177
178
179
180
181
182
183
184
       else if ( pageWidget == _ui->appearanceTab )
            setupAppearancePage(info);
       else if ( pageWidget == _ui->scrollingTab )
            setupScrollingPage(info);
       else if ( pageWidget == _ui->keyboardTab )
            setupKeyboardPage(info);
       else if ( pageWidget == _ui->advancedTab )
            setupAdvancedPage(info);
       else
           Q_ASSERT(false);

185
        _pageNeedsUpdate[page] = false;
186
    }
Robert Knight's avatar
   
Robert Knight committed
187
188
189
190
191
192
193
194
195

    // start page entry animation for color schemes
    if ( pageWidget == _ui->appearanceTab )
            _colorSchemeAnimationTimeLine->start();
}
void EditProfileDialog::selectProfileName()
{
    _ui->profileNameEdit->selectAll();
    _ui->profileNameEdit->setFocus();
196
}
197
void EditProfileDialog::setupGeneralPage(const Profile* info)
198
{
199
200

    // basic profile options
201
    _ui->profileNameEdit->setText( info->name() );
202
203
204

    ShellCommand command( info->command() , info->arguments() );
    _ui->commandEdit->setText( command.fullCommand() );
205
206

    KUrlCompletion* exeCompletion = new KUrlCompletion(KUrlCompletion::ExeCompletion);
207
    exeCompletion->setParent(this);
208
    exeCompletion->setDir(QString());
209
    _ui->commandEdit->setCompletionObject( exeCompletion );
210
    _ui->initialDirEdit->setText( info->defaultWorkingDirectory() );
211
212
213
214

    KUrlCompletion* dirCompletion = new KUrlCompletion(KUrlCompletion::DirCompletion);
    dirCompletion->setParent(this);
    _ui->initialDirEdit->setCompletionObject( dirCompletion );
215
    _ui->initialDirEdit->setClearButtonShown(true);
216
    _ui->dirSelectButton->setIcon( KIcon("folder-open") );
217
    _ui->iconSelectButton->setIcon( KIcon(info->icon()) );
218

219
    // window options
220
    _ui->showMenuBarButton->setChecked( info->property<bool>(Profile::ShowMenuBar) );
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

    // signals and slots
    connect( _ui->dirSelectButton , SIGNAL(clicked()) , this , SLOT(selectInitialDir()) );
    connect( _ui->iconSelectButton , SIGNAL(clicked()) , this , SLOT(selectIcon()) );

    connect( _ui->profileNameEdit , SIGNAL(textChanged(const QString&)) , this ,
            SLOT(profileNameChanged(const QString&)) );
    connect( _ui->initialDirEdit , SIGNAL(textChanged(const QString&)) , this , 
            SLOT(initialDirChanged(const QString&)) );
    connect(_ui->commandEdit , SIGNAL(textChanged(const QString&)) , this ,
            SLOT(commandChanged(const QString&)) ); 
    
    connect(_ui->showMenuBarButton , SIGNAL(toggled(bool)) , this , 
            SLOT(showMenuBar(bool)) );

    connect(_ui->environmentEditButton , SIGNAL(clicked()) , this , 
            SLOT(showEnvironmentEditor()) );
}
void EditProfileDialog::showEnvironmentEditor()
{
    const Profile* info = lookupProfile();

    KDialog* dialog = new KDialog(this);
    QTextEdit* edit = new QTextEdit(dialog);

246
    QStringList currentEnvironment = info->property<QStringList>(Profile::Environment);
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261

    edit->setPlainText( currentEnvironment.join("\n") );
    dialog->setPlainCaption(i18n("Edit Environment"));
    dialog->setMainWidget(edit);

    if ( dialog->exec() == QDialog::Accepted )
    {
        QStringList newEnvironment = edit->toPlainText().split('\n');
        _tempProfile->setProperty(Profile::Environment,newEnvironment);
    }

    dialog->deleteLater();
}
void EditProfileDialog::setupTabsPage(const Profile* info)
{
262
263
264
    // tab title format
    _ui->tabTitleEdit->setClearButtonShown(true);
    _ui->remoteTabTitleEdit->setClearButtonShown(true);
265
    _ui->tabTitleEdit->setText( info->property<QString>(Profile::LocalTabTitleFormat) );
266
    _ui->remoteTabTitleEdit->setText( 
267
            info->property<QString>(Profile::RemoteTabTitleFormat));
268

269
    // tab options
270
271
    int tabMode = info->property<int>(Profile::TabBarMode);
    int tabPosition = info->property<int>(Profile::TabBarPosition);
272

273
274
    // note: Items should be in the same order as the 
    // Profile::TabBarModeEnum enum
275
276
277
    _ui->tabBarVisibilityCombo->addItems( QStringList() << i18n("Always Hide Tab Bar")
                                                        << i18n("Show Tab Bar When Needed") 
                                                        << i18n("Always Show Tab Bar") );
278
279
280
281
    _ui->tabBarVisibilityCombo->setCurrentIndex(tabMode);

    // note: Items should be in the same order as the
    // Profile::TabBarPositionEnum enum
282
283
    _ui->tabBarPositionCombo->addItems( QStringList() << i18n("Below Terminal Displays")
                                                      << i18n("Above Terminal Displays") );
284
285
286

    _ui->tabBarPositionCombo->setCurrentIndex(tabPosition);

287
    // signals and slots
288
289
290
291
    connect( _ui->tabBarVisibilityCombo , SIGNAL(activated(int)) , this , 
             SLOT(tabBarVisibilityChanged(int)) );
    connect( _ui->tabBarPositionCombo , SIGNAL(activated(int)) , this ,
             SLOT(tabBarPositionChanged(int)) );
292

293
294
295
296
    connect(_ui->tabTitleEdit , SIGNAL(textChanged(const QString&)) , this ,
            SLOT(tabTitleFormatChanged(const QString&)) );
    connect(_ui->remoteTabTitleEdit , SIGNAL(textChanged(const QString&)) , this ,
            SLOT(remoteTabTitleFormatChanged(const QString&)));
297

298
299
300
301
302
303
304
305
306
307
308
309
    // menus for local and remote tab title dynamic elements
    TabTitleFormatAction* localTabTitleAction = new TabTitleFormatAction(this);
    localTabTitleAction->setContext(Session::LocalTabTitle);
    _ui->tabTitleEditButton->setMenu(localTabTitleAction->menu());
    connect( localTabTitleAction , SIGNAL(dynamicElementSelected(const QString&)) , 
            this , SLOT(insertTabTitleText(const QString&)) );

    TabTitleFormatAction* remoteTabTitleAction = new TabTitleFormatAction(this);
    remoteTabTitleAction->setContext(Session::RemoteTabTitle);
    _ui->remoteTabTitleEditButton->setMenu(remoteTabTitleAction->menu());
    connect( remoteTabTitleAction , SIGNAL(dynamicElementSelected(const QString&)) ,
           this , SLOT(insertRemoteTabTitleText(const QString&)) ); 
310
}
311
312
313
314
315
316
317
318
void EditProfileDialog::tabBarVisibilityChanged(int newValue)
{
    _tempProfile->setProperty( Profile::TabBarMode , newValue );
}
void EditProfileDialog::tabBarPositionChanged(int newValue)
{
    _tempProfile->setProperty( Profile::TabBarPosition , newValue );
}
319
320
321
322
323
324
325
326
void EditProfileDialog::insertTabTitleText(const QString& text)
{
    _ui->tabTitleEdit->insert(text);
}
void EditProfileDialog::insertRemoteTabTitleText(const QString& text)
{
    _ui->remoteTabTitleEdit->insert(text);
}
327
328
329
330
void EditProfileDialog::showMenuBar(bool show)
{
    _tempProfile->setProperty(Profile::ShowMenuBar,show);
}
331
332
333
334
335
336
337
338
339
340
341
void EditProfileDialog::tabTitleFormatChanged(const QString& format)
{
    _tempProfile->setProperty(Profile::LocalTabTitleFormat,format);
}
void EditProfileDialog::remoteTabTitleFormatChanged(const QString& format)
{
    _tempProfile->setProperty(Profile::RemoteTabTitleFormat,format);
}

void EditProfileDialog::selectIcon()
{
Craig Drummond's avatar
Craig Drummond committed
342
343
    const QString& icon = KIconDialog::getIcon(KIconLoader::Desktop, KIconLoader::Application,
                                               false, 0, false, this);
344
345
346
347
348
349
350
351
352
    if (!icon.isEmpty())
    {
        _ui->iconSelectButton->setIcon( KIcon(icon) );
        _tempProfile->setProperty(Profile::Icon,icon);
    }
}
void EditProfileDialog::profileNameChanged(const QString& text)
{
    _tempProfile->setProperty(Profile::Name,text);
Robert Knight's avatar
   
Robert Knight committed
353
    updateCaption(_tempProfile->name());
354
355
356
357
358
359
360
}
void EditProfileDialog::initialDirChanged(const QString& dir)
{
    _tempProfile->setProperty(Profile::Directory,dir);
}
void EditProfileDialog::commandChanged(const QString& command)
{
361
362
363
364
    ShellCommand shellCommand(command);

    _tempProfile->setProperty(Profile::Command,shellCommand.command());
    _tempProfile->setProperty(Profile::Arguments,shellCommand.arguments());
365
366
367
}
void EditProfileDialog::selectInitialDir()
{
368
369
370
    const KUrl url = KFileDialog::getExistingDirectoryUrl(_ui->initialDirEdit->text(),
                                                          this,
                                                          i18n("Select Initial Directory"));
371
372
373

    if ( !url.isEmpty() )
        _ui->initialDirEdit->setText(url.path());
374
}
375
void EditProfileDialog::setupAppearancePage(const Profile* info)
376
{
377
    ColorSchemeViewDelegate* delegate = new ColorSchemeViewDelegate(this);
378
379
    _ui->colorSchemeList->setItemDelegate(delegate);
    
Robert Knight's avatar
   
Robert Knight committed
380
381
    _colorSchemeAnimationTimeLine = new QTimeLine( 500 , this );
    delegate->setEntryTimeLine(_colorSchemeAnimationTimeLine);
382
    
Robert Knight's avatar
   
Robert Knight committed
383
    connect( _colorSchemeAnimationTimeLine , SIGNAL(valueChanged(qreal)) , this ,
384
             SLOT(colorSchemeAnimationUpdate()) );
Robert Knight's avatar
   
Robert Knight committed
385
386
   
    _ui->transparencyWarningWidget->setVisible(false);
Robert Knight's avatar
   
Robert Knight committed
387
388
389
    _ui->editColorSchemeButton->setEnabled(false);
    _ui->removeColorSchemeButton->setEnabled(false);

390
391
    // setup color list
    updateColorSchemeList(true);
Robert Knight's avatar
   
Robert Knight committed
392
    
393
394
    _ui->colorSchemeList->setMouseTracking(true);
    _ui->colorSchemeList->installEventFilter(this);
Robert Knight's avatar
   
Robert Knight committed
395
    _ui->colorSchemeList->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
396

397
398
399
    connect( _ui->colorSchemeList->selectionModel() , 
            SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)) 
            , this , SLOT(colorSchemeSelected()) );
400
401
    connect( _ui->colorSchemeList , SIGNAL(entered(const QModelIndex&)) , this , 
            SLOT(previewColorScheme(const QModelIndex&)) );
Robert Knight's avatar
   
Robert Knight committed
402
403
    
    updateColorSchemeButtons();
404

405
406
407
408
409
410
    connect( _ui->editColorSchemeButton , SIGNAL(clicked()) , this , 
            SLOT(editColorScheme()) );
    connect( _ui->removeColorSchemeButton , SIGNAL(clicked()) , this ,
            SLOT(removeColorScheme()) );
    connect( _ui->newColorSchemeButton , SIGNAL(clicked()) , this , 
            SLOT(newColorScheme()) );
411

412
    // setup font preview
413
414
415
416
417
418
	bool antialias = info->property<bool>(Profile::AntiAliasFonts);

    QFont font = info->font();
	if (!antialias)
		font.setStyleStrategy(QFont::NoAntialias);

419
420
	_ui->fontPreviewLabel->installEventFilter(this);
	_ui->fontPreviewLabel->setFont(font);
421
    _ui->fontSizeSlider->setValue( font.pointSize() );
422
    _ui->fontSizeSlider->setMinimum( KGlobalSettings::smallestReadableFont().pointSize() );
423
424
425
426
427

    connect( _ui->fontSizeSlider , SIGNAL(valueChanged(int)) , this ,
             SLOT(setFontSize(int)) );
    connect( _ui->editFontButton , SIGNAL(clicked()) , this ,
             SLOT(showFontDialog()) );
428
429

	// setup font smoothing 
430
	_ui->antialiasTextButton->setChecked(antialias);
431
432
433
434
435
436
	connect( _ui->antialiasTextButton , SIGNAL(toggled(bool)) , this , 
			 SLOT(setAntialiasText(bool)) );
}
void EditProfileDialog::setAntialiasText(bool enable)
{
	_tempProfile->setProperty(Profile::AntiAliasFonts,enable);
437
438
439

	// update preview to reflect text smoothing state
	fontSelected(_ui->fontPreviewLabel->font());
440
441
442
443
444
445
446
}
void EditProfileDialog::colorSchemeAnimationUpdate()
{
    QAbstractItemModel* model = _ui->colorSchemeList->model();

    for ( int i = model->rowCount() ; i >= 0 ; i-- )
        _ui->colorSchemeList->update( model->index(i,0) );
447
}
448
void EditProfileDialog::updateColorSchemeList(bool selectCurrentScheme)
449
{
Robert Knight's avatar
   
Robert Knight committed
450
451
    if (!_ui->colorSchemeList->model())
        _ui->colorSchemeList->setModel(new QStandardItemModel(this));
452

453
    const QString& name = lookupProfile()->colorScheme();
454
455
    const ColorScheme* currentScheme = ColorSchemeManager::instance()->findColorScheme(name);

Robert Knight's avatar
   
Robert Knight committed
456
457
458
459
460
461
    QStandardItemModel* model = qobject_cast<QStandardItemModel*>(_ui->colorSchemeList->model());

    Q_ASSERT(model);
    
    model->clear();

462
463
464
    QList<const ColorScheme*> schemeList = ColorSchemeManager::instance()->allColorSchemes();
    QListIterator<const ColorScheme*> schemeIter(schemeList);

465
466
    QStandardItem* selectedItem = 0;

467
468
469
470
471
    while (schemeIter.hasNext())
    {
        const ColorScheme* colors = schemeIter.next();
        QStandardItem* item = new QStandardItem(colors->description());
        item->setData( QVariant::fromValue(colors) ,  Qt::UserRole + 1);
472
        item->setFlags( item->flags() );
473
474
       
        if ( currentScheme == colors ) 
Robert Knight's avatar
   
Robert Knight committed
475
476
            selectedItem = item;  

477
478
479
        model->appendRow(item);
    }

480
481
    model->sort(0);

Robert Knight's avatar
   
Robert Knight committed
482
    if ( selectCurrentScheme && selectedItem )
483
484
485
486
    {
        _ui->colorSchemeList->updateGeometry();
        _ui->colorSchemeList->selectionModel()->setCurrentIndex( selectedItem->index() , 
                                                                 QItemSelectionModel::Select );
Robert Knight's avatar
   
Robert Knight committed
487
488
489

        // update transparency warning label
        updateTransparencyWarning();
490
    }
491
}
492
void EditProfileDialog::updateKeyBindingsList(bool selectCurrentTranslator)
493
{
Robert Knight's avatar
   
Robert Knight committed
494
495
    if (!_ui->keyBindingList->model())
        _ui->keyBindingList->setModel(new QStandardItemModel(this));
496

Robert Knight's avatar
   
Robert Knight committed
497
    KeyboardTranslatorManager* keyManager = KeyboardTranslatorManager::instance();
498

499
    const QString& name = lookupProfile()
500
                                    ->property<QString>(Profile::KeyBindings);
501

502
    const KeyboardTranslator* currentTranslator = keyManager->findTranslator(name);
503
    
Robert Knight's avatar
   
Robert Knight committed
504
505
506
507
508
    QStandardItemModel* model = qobject_cast<QStandardItemModel*>(_ui->keyBindingList->model());

    Q_ASSERT(model);

    model->clear();
509

510
511
    QStandardItem* selectedItem = 0;

512
    QList<QString> translatorNames = keyManager->allTranslators();
513
514
515
516
517
    QListIterator<QString> iter(translatorNames);
    while (iter.hasNext())
    {
        const QString& name = iter.next();

518
        const KeyboardTranslator* translator = keyManager->findTranslator(name);
519
520
521

        QStandardItem* item = new QStandardItem(translator->description());
        item->setData(QVariant::fromValue(translator),Qt::UserRole+1);
Laurent Montel's avatar
Laurent Montel committed
522
        item->setIcon( KIcon("preferences-desktop-keyboard") );
523
524

        if ( translator == currentTranslator )
525
            selectedItem = item;
526
527
528
529

        model->appendRow(item);
    }

530
    model->sort(0);
531
    
Robert Knight's avatar
   
Robert Knight committed
532
    if ( selectCurrentTranslator && selectedItem )
533
534
535
536
    {
        _ui->keyBindingList->selectionModel()->setCurrentIndex( selectedItem->index() , 
                                                                  QItemSelectionModel::Select );
    }
537
}
538
539
540
541
bool EditProfileDialog::eventFilter( QObject* watched , QEvent* event )
{
    if ( watched == _ui->colorSchemeList && event->type() == QEvent::Leave )
    {
542
543
544
545
        if ( _tempProfile->isPropertySet(Profile::ColorScheme) )
            preview(Profile::ColorScheme,_tempProfile->colorScheme());
        else
            unpreview(Profile::ColorScheme);
546
    }
547
548
549
550
551
	if ( watched == _ui->fontPreviewLabel && event->type() == QEvent::FontChange )
	{
		const QFont& labelFont = _ui->fontPreviewLabel->font();
		_ui->fontPreviewLabel->setText(i18n("%1, size %2",labelFont.family(),labelFont.pointSize()));
	}
552
553
554

    return KDialog::eventFilter(watched,event);
}
555
void EditProfileDialog::unpreviewAll()
556
{
557
558
559
    _delayedPreviewTimer->stop();
    _delayedPreviewProperties.clear();

560
561
562
563
564
    QHash<Profile::Property,QVariant> map;
    QHashIterator<int,QVariant> iter(_previewedProperties);
    while ( iter.hasNext() )
    {
        iter.next();
565
        map.insert((Profile::Property)iter.key(),iter.value());
566
567
568
    }

    // undo any preview changes
569
    if ( !map.isEmpty() )
570
571
572
573
        SessionManager::instance()->changeProfile(_profileKey,map,false);
}
void EditProfileDialog::unpreview(int property)
{
574
575
    _delayedPreviewProperties.remove(property);
    
576
577
    if (!_previewedProperties.contains(property))
        return;
578
    
579
580
581
582
583
584
    QHash<Profile::Property,QVariant> map;
    map.insert((Profile::Property)property,_previewedProperties[property]);
    SessionManager::instance()->changeProfile(_profileKey,map,false); 

    _previewedProperties.remove(property);
}
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
void EditProfileDialog::delayedPreview(int property , const QVariant& value)
{
    _delayedPreviewProperties.insert(property,value); 
    QTimer* timer = new QTimer(this);
    timer->setSingleShot(true);

    _delayedPreviewTimer->stop();
    _delayedPreviewTimer->start(300);    
}
void EditProfileDialog::delayedPreviewActivate()
{
    Q_ASSERT( qobject_cast<QTimer*>(sender()) );

    QMutableHashIterator<int,QVariant> iter(_delayedPreviewProperties);
    if ( iter.hasNext() ) 
    {
        iter.next();
        preview(iter.key(),iter.value());
    }
}
Robert Knight's avatar
Robert Knight committed
605
void EditProfileDialog::preview(int property , const QVariant& value)
606
607
608
{
    QHash<Profile::Property,QVariant> map;
    map.insert((Profile::Property)property,value);
609
610
    
    _delayedPreviewProperties.remove(property);
611

612
    const Profile* original = lookupProfile();
613
614

    if (!_previewedProperties.contains(property))    
615
        _previewedProperties.insert(property , original->property<QVariant>((Profile::Property)property) );
616
617
618
619
620
621
622
623

    // temporary change to color scheme
    SessionManager::instance()->changeProfile( _profileKey , map , false);
}
void EditProfileDialog::previewColorScheme(const QModelIndex& index)
{
    const QString& name = index.data(Qt::UserRole+1).value<const ColorScheme*>()->name();

624
    delayedPreview( Profile::ColorScheme , name );
625
}
626
627
void EditProfileDialog::removeColorScheme()
{
628
629
630
631
632
    QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes();

    if ( !selected.isEmpty() )
    {
        const QString& name = selected.first().data(Qt::UserRole+1).value<const ColorScheme*>()->name();
633
634
635
        
        if (ColorSchemeManager::instance()->deleteColorScheme(name))    
            _ui->colorSchemeList->model()->removeRow(selected.first().row());
636
    }
637
}
638
void EditProfileDialog::showColorSchemeEditor(bool isNewScheme)
639
640
641
{    
    QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes();

642
    QAbstractItemModel* model = _ui->colorSchemeList->model();
Robert Knight's avatar
   
Robert Knight committed
643
    const ColorScheme* colors = 0;
644
    if ( !selected.isEmpty() )
Robert Knight's avatar
   
Robert Knight committed
645
        colors = model->data(selected.first(),Qt::UserRole+1).value<const ColorScheme*>();
646
    else
Robert Knight's avatar
   
Robert Knight committed
647
        colors = ColorSchemeManager::instance()->defaultColorScheme();
648

Robert Knight's avatar
   
Robert Knight committed
649
    Q_ASSERT(colors);
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665

    KDialog* dialog = new KDialog(this);

    if ( isNewScheme )
        dialog->setCaption(i18n("New Color Scheme"));
    else
        dialog->setCaption(i18n("Edit Color Scheme"));

    ColorSchemeEditor* editor = new ColorSchemeEditor;
    dialog->setMainWidget(editor);
    editor->setup(colors);

    if ( isNewScheme )
        editor->setDescription(i18n("New Color Scheme"));
        
    if ( dialog->exec() == QDialog::Accepted )
666
    {
667
        ColorScheme* newScheme = new ColorScheme(*editor->colorScheme());
668

669
670
671
        // if this is a new color scheme, pick a name based on the description
        if ( isNewScheme )
            newScheme->setName(newScheme->description());
672

673
674
        ColorSchemeManager::instance()->addColorScheme( newScheme );
        
Robert Knight's avatar
   
Robert Knight committed
675
        updateColorSchemeList(true);
676

Robert Knight's avatar
   
Robert Knight committed
677
        preview(Profile::ColorScheme,newScheme->name());
678
679
680
681
682
683
684
685
686
687
    }
}
void EditProfileDialog::newColorScheme()
{
    showColorSchemeEditor(true);    
}
void EditProfileDialog::editColorScheme()
{
    showColorSchemeEditor(false);
}
688
689
690
691
692
693
694
void EditProfileDialog::colorSchemeSelected()
{
    QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes();

    if ( !selected.isEmpty() )
    {
        QAbstractItemModel* model = _ui->colorSchemeList->model();
695
        const ColorScheme* colors = model->data(selected.first(),Qt::UserRole+1).value<const ColorScheme*>();
696

Robert Knight's avatar
   
Robert Knight committed
697
        kDebug() << "Setting temp profile color to" << colors->name();
698
699
700
        
		previewColorScheme(selected.first());
		_tempProfile->setProperty(Profile::ColorScheme,colors->name());
Robert Knight's avatar
   
Robert Knight committed
701
702
703

        updateTransparencyWarning();
    }
Robert Knight's avatar
   
Robert Knight committed
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719

    updateColorSchemeButtons();
}
void EditProfileDialog::updateColorSchemeButtons()
{
    enableIfNonEmptySelection(_ui->editColorSchemeButton,_ui->colorSchemeList->selectionModel());
    enableIfNonEmptySelection(_ui->removeColorSchemeButton,_ui->colorSchemeList->selectionModel());
}
void EditProfileDialog::updateKeyBindingsButtons()
{    
    enableIfNonEmptySelection(_ui->editKeyBindingsButton,_ui->keyBindingList->selectionModel());
    enableIfNonEmptySelection(_ui->removeKeyBindingsButton,_ui->keyBindingList->selectionModel());
}
void EditProfileDialog::enableIfNonEmptySelection(QWidget* widget,QItemSelectionModel* selectionModel)
{
    widget->setEnabled(selectionModel->hasSelection());
Robert Knight's avatar
   
Robert Knight committed
720
721
722
723
724
725
726
727
728
729
}
void EditProfileDialog::updateTransparencyWarning() 
{
    // zero or one indexes can be selected
    foreach( const QModelIndex& index , _ui->colorSchemeList->selectionModel()->selectedIndexes() ) 
    {
        bool hasTransparency = index.data(Qt::UserRole+1).value<const ColorScheme*>()->opacity() < 1.0;

        _ui->transparencyWarningWidget->setHidden(KWindowSystem::compositingActive() || !hasTransparency);
        _ui->transparencyWarningIcon->setPixmap( KIcon("dialog-warning").pixmap(QSize(48,48)) );
730
731
    }
}
Robert Knight's avatar
   
Robert Knight committed
732
void EditProfileDialog::setupKeyboardPage(const Profile* /* info */)
733
734
{
    // setup translator list
735
    updateKeyBindingsList(true); 
736

737
738
739
    connect( _ui->keyBindingList->selectionModel() , 
                SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),
                SLOT(keyBindingSelected()) );
740
741
    connect( _ui->newKeyBindingsButton , SIGNAL(clicked()) , this ,
            SLOT(newKeyBinding()) );
Robert Knight's avatar
   
Robert Knight committed
742
743
744

    updateKeyBindingsButtons();

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
    connect( _ui->editKeyBindingsButton , SIGNAL(clicked()) , this , 
          SLOT(editKeyBinding()) );  
    connect( _ui->removeKeyBindingsButton , SIGNAL(clicked()) , this ,
            SLOT(removeKeyBinding()) );
}
void EditProfileDialog::keyBindingSelected()
{
    QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes();

    if ( !selected.isEmpty() )
    {
        QAbstractItemModel* model = _ui->keyBindingList->model();
        const KeyboardTranslator* translator = model->data(selected.first(),Qt::UserRole+1)
                                                .value<const KeyboardTranslator*>();
        _tempProfile->setProperty(Profile::KeyBindings,translator->name());
    }
Robert Knight's avatar
   
Robert Knight committed
761
762

    updateKeyBindingsButtons();
763
764
765
766
767
768
769
770
}
void EditProfileDialog::removeKeyBinding()
{
    QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes();

    if ( !selected.isEmpty() )
    {
        const QString& name = selected.first().data(Qt::UserRole+1).value<const KeyboardTranslator*>()->name();
771
772
        if (KeyboardTranslatorManager::instance()->deleteTranslator(name))
            _ui->keyBindingList->model()->removeRow(selected.first().row());   
773
774
    }
}
775
void EditProfileDialog::showKeyBindingEditor(bool isNewTranslator)
776
777
{
    QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes();
778
    QAbstractItemModel* model = _ui->keyBindingList->model();
779

Robert Knight's avatar
   
Robert Knight committed
780
    const KeyboardTranslator* translator = 0;
781
    if ( !selected.isEmpty() )
Robert Knight's avatar
   
Robert Knight committed
782
        translator = model->data(selected.first(),Qt::UserRole+1).value<const KeyboardTranslator*>();
783
    else
Robert Knight's avatar
   
Robert Knight committed
784
        translator = KeyboardTranslatorManager::instance()->defaultTranslator();
785

Robert Knight's avatar
   
Robert Knight committed
786
    Q_ASSERT(translator);
787

788
    KDialog* dialog = new KDialog(this);
789

790
791
792
793
    if ( isNewTranslator )
        dialog->setCaption(i18n("New Key Binding List"));
    else
        dialog->setCaption(i18n("Edit Key Binding List"));
794

795
796
    KeyBindingEditor* editor = new KeyBindingEditor;
    dialog->setMainWidget(editor);
797
798
799
    
    if ( translator )
        editor->setup(translator);
800
801
802
803
804
805
806
807
808
809

    if ( isNewTranslator )
        editor->setDescription(i18n("New Key Binding List"));

    if ( dialog->exec() == QDialog::Accepted )
    {
        KeyboardTranslator* newTranslator = new KeyboardTranslator(*editor->translator());

        if ( isNewTranslator )
            newTranslator->setName(newTranslator->description());
810

811
        KeyboardTranslatorManager::instance()->addTranslator( newTranslator );
812

813
814
        updateKeyBindingsList();
        
815
        const QString& currentTranslator = lookupProfile()
816
                                        ->property<QString>(Profile::KeyBindings);
817

818
819
820
        if ( newTranslator->name() == currentTranslator )
        {
            _tempProfile->setProperty(Profile::KeyBindings,newTranslator->name());
821
        }
822
823
    }
}
824
825
826
827
828
void EditProfileDialog::newKeyBinding()
{
    showKeyBindingEditor(true);
}
void EditProfileDialog::editKeyBinding()
829
{
830
    showKeyBindingEditor(false);
831
}
Robert Knight's avatar
Robert Knight committed
832
void EditProfileDialog::setupCombo( ComboOption* options , const Profile* profile )
833
{
Robert Knight's avatar
Robert Knight committed
834
    while ( options->button != 0 )
835
    {
836
        options->button->setChecked(profile->property<bool>((Profile::Property)options->property));
Robert Knight's avatar
Robert Knight committed
837
838
839
840
841
842
843
844
845
846
847
        connect( options->button , SIGNAL(toggled(bool)) , this , options->slot );

        ++options;
    }
}
void EditProfileDialog::setupRadio( RadioOption* possible , int actual )
{
    while (possible->button != 0)
    {
        if ( possible->property == actual )
            possible->button->setChecked(true);
848
        else
Robert Knight's avatar
Robert Knight committed
849
850
851
852
            possible->button->setChecked(false);
   
        connect( possible->button , SIGNAL(clicked()) , this , possible->slot );

853
854
        ++possible;
    }
855
}
856
857

void EditProfileDialog::setupScrollingPage(const Profile* profile)
858
{
859
    // setup scrollbar radio
860
    int scrollBarPosition = profile->property<int>(Profile::ScrollBarPosition);
861
   
Robert Knight's avatar
Robert Knight committed
862
863
864
865
866
    RadioOption positions[] = { {_ui->scrollBarHiddenButton,Profile::ScrollBarHidden,SLOT(hideScrollBar())},
                                {_ui->scrollBarLeftButton,Profile::ScrollBarLeft,SLOT(showScrollBarLeft())},
                                {_ui->scrollBarRightButton,Profile::ScrollBarRight,SLOT(showScrollBarRight())},
                                {0,0,0} 
                              }; 
867

Robert Knight's avatar
Robert Knight committed
868
    setupRadio( positions , scrollBarPosition );
869
870
   
    // setup scrollback type radio
871
    int scrollBackType = profile->property<int>(Profile::HistoryMode);
872
    
Robert Knight's avatar
Robert Knight committed
873
874
875
876
877
    RadioOption types[] = { {_ui->disableScrollbackButton,Profile::DisableHistory,SLOT(noScrollBack())},
                            {_ui->fixedScrollbackButton,Profile::FixedSizeHistory,SLOT(fixedScrollBack())},
                            {_ui->unlimitedScrollbackButton,Profile::UnlimitedHistory,SLOT(unlimitedScrollBack())},
                            {0,0,0} };
    setupRadio( types , scrollBackType ); 
878
879
    
    // setup scrollback line count spinner
880
    _ui->scrollBackLinesSpinner->setValue( profile->property<int>(Profile::HistorySize) );
881
882
883
884

    // signals and slots
    connect( _ui->scrollBackLinesSpinner , SIGNAL(valueChanged(int)) , this , 
            SLOT(scrollBackLinesChanged(int)) );
885
886
}

887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
void EditProfileDialog::scrollBackLinesChanged(int lineCount)
{
    _tempProfile->setProperty(Profile::HistorySize , lineCount);
}
void EditProfileDialog::noScrollBack()
{
    _tempProfile->setProperty(Profile::HistoryMode , Profile::DisableHistory);
}
void EditProfileDialog::fixedScrollBack()
{
    _tempProfile->setProperty(Profile::HistoryMode , Profile::FixedSizeHistory);
}
void EditProfileDialog::unlimitedScrollBack()
{
    _tempProfile->setProperty(Profile::HistoryMode , Profile::UnlimitedHistory );
}
void EditProfileDialog::hideScrollBar()
{
    _tempProfile->setProperty(Profile::ScrollBarPosition , Profile::ScrollBarHidden );
}
void EditProfileDialog::showScrollBarLeft()
{
    _tempProfile->setProperty(Profile::ScrollBarPosition , Profile::ScrollBarLeft );
}
void EditProfileDialog::showScrollBarRight()
{
    _tempProfile->setProperty(Profile::ScrollBarPosition , Profile::ScrollBarRight );
}
void EditProfileDialog::setupAdvancedPage(const Profile* profile)
{
Robert Knight's avatar
Robert Knight committed
917
918
919
920
921
922
923
924
925
926
927
    ComboOption  options[] = { { _ui->enableBlinkingTextButton , Profile::BlinkingTextEnabled , 
                                 SLOT(toggleBlinkingText(bool)) },
                               { _ui->enableFlowControlButton , Profile::FlowControlEnabled ,
                                 SLOT(toggleFlowControl(bool)) },
                               { _ui->enableResizeWindowButton , Profile::AllowProgramsToResizeWindow ,
                                 SLOT(toggleResizeWindow(bool)) },
                               { _ui->enableBlinkingCursorButton , Profile::BlinkingCursorEnabled ,
                                 SLOT(toggleBlinkingCursor(bool)) },
                               { 0 , 0 , 0 }
                             };
    setupCombo( options , profile );
928
929

    // interaction options
930
    _ui->wordCharacterEdit->setText( profile->property<QString>(Profile::WordCharacters) );
931
932
933
934
935

    connect( _ui->wordCharacterEdit , SIGNAL(textChanged(const QString&)) , this , 
            SLOT(wordCharactersChanged(const QString&)) );

    // cursor options
936
    if ( profile->property<bool>(Profile::UseCustomCursorColor) )
937
938
939
940
        _ui->customCursorColorButton->setChecked(true);
    else
        _ui->autoCursorColorButton->setChecked(true);

941
    _ui->customColorSelectButton->setColor( profile->property<QColor>(Profile::CustomCursorColor) );
942
943
944
945
946
947

    connect( _ui->customCursorColorButton , SIGNAL(clicked()) , this , SLOT(customCursorColor()) );
    connect( _ui->autoCursorColorButton , SIGNAL(clicked()) , this , SLOT(autoCursorColor()) );
    connect( _ui->customColorSelectButton , SIGNAL(changed(const QColor&)) , 
            SLOT(customCursorColorChanged(const QColor&)) );

948
    int shape = profile->property<int>(Profile::CursorShape);
949
950
951
    _ui->cursorShapeCombo->setCurrentIndex(shape);

    connect( _ui->cursorShapeCombo , SIGNAL(activated(int)) , this , SLOT(setCursorShape(int)) ); 
952
953
954
955
956
957

    // encoding options
    QAction* codecAction = new KCodecAction(this);
    _ui->selectEncodingButton->setMenu( codecAction->menu() );
    connect( codecAction , SIGNAL(triggered(QTextCodec*)) , this , SLOT(setDefaultCodec(QTextCodec*)) );

958
    _ui->characterEncodingLabel->setText( profile->property<QString>(Profile::DefaultEncoding) );
959
960
961
962
963
964
965
966

}
void EditProfileDialog::setDefaultCodec(QTextCodec* codec)
{
    QString name = QString(codec->name());

    _tempProfile->setProperty(Profile::DefaultEncoding,name);
    _ui->characterEncodingLabel->setText(codec->name());
967
968
969
970
}
void EditProfileDialog::customCursorColorChanged(const QColor& color)
{
    _tempProfile->setProperty(Profile::CustomCursorColor,color);
971
972
973

    // ensure that custom cursor colors are enabled
    _ui->customCursorColorButton->click();
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
}
void EditProfileDialog::wordCharactersChanged(const QString& text)
{
    _tempProfile->setProperty(Profile::WordCharacters,text);
}
void EditProfileDialog::autoCursorColor()
{
    _tempProfile->setProperty(Profile::UseCustomCursorColor,false);
}
void EditProfileDialog::customCursorColor()
{
    _tempProfile->setProperty(Profile::UseCustomCursorColor,true);
}
void EditProfileDialog::setCursorShape(int index)
{
    _tempProfile->setProperty(Profile::CursorShape,index);
990
991
992
993
}
void EditProfileDialog::toggleBlinkingCursor(bool enable)
{
    _tempProfile->setProperty(Profile::BlinkingCursorEnabled,enable);
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
}
void EditProfileDialog::toggleBlinkingText(bool enable)
{
    _tempProfile->setProperty(Profile::BlinkingTextEnabled,enable);
}
void EditProfileDialog::toggleFlowControl(bool enable)
{
    _tempProfile->setProperty(Profile::FlowControlEnabled,enable);
}
void EditProfileDialog::toggleResizeWindow(bool enable)
{
    _tempProfile->setProperty(Profile::AllowProgramsToResizeWindow,enable);
}
1007
void EditProfileDialog::fontSelected(const QFont& font)
1008
{
1009
1010
	QFont previewFont = font;

1011
1012
1013
1014
   QSlider* slider = _ui->fontSizeSlider;
   _ui->fontSizeSlider->setRange( qMin(slider->minimum(),font.pointSize()) ,
                                  qMax(slider->maximum(),font.pointSize()) );
   _ui->fontSizeSlider->setValue(font.pointSize());
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025

	
   QFont::StyleStrategy strategy;
   if (_tempProfile->property<bool>(Profile::AntiAliasFonts))
   		strategy = QFont::PreferAntialias;
   else
   		strategy = QFont::NoAntialias;

   previewFont.setStyleStrategy(strategy);

   _ui->fontPreviewLabel->setFont(previewFont);
1026
   
1027
   _tempProfile->setProperty(Profile::Font,font);
1028

1029
   preview(Profile::Font,font);
1030
}
1031
void EditProfileDialog::showFontDialog()
1032
1033
{
    QFont currentFont = _ui->fontPreviewLabel->font();
1034
   
1035
1036
    KFontDialog* dialog = new KFontDialog(this, KFontChooser::FixedFontsOnly);
    dialog->setFont(currentFont, true);
1037

1038
    connect( dialog