EditProfileDialog.cpp 40.8 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
    const QFont& font = info->font();
414
415
	_ui->fontPreviewLabel->installEventFilter(this);
	_ui->fontPreviewLabel->setFont(font);
416
    _ui->fontSizeSlider->setValue( font.pointSize() );
417
    _ui->fontSizeSlider->setMinimum( KGlobalSettings::smallestReadableFont().pointSize() );
418
419
420
421
422

    connect( _ui->fontSizeSlider , SIGNAL(valueChanged(int)) , this ,
             SLOT(setFontSize(int)) );
    connect( _ui->editFontButton , SIGNAL(clicked()) , this ,
             SLOT(showFontDialog()) );
423
424
425
426
427
428
429
430
431
432

	// setup font smoothing 
	_ui->antialiasTextButton->setChecked(info->property<bool>(Profile::AntiAliasFonts));
	connect( _ui->antialiasTextButton , SIGNAL(toggled(bool)) , this , 
			 SLOT(setAntialiasText(bool)) );
}
void EditProfileDialog::setAntialiasText(bool enable)
{
	_tempProfile->setProperty(Profile::AntiAliasFonts,enable);
	preview(Profile::AntiAliasFonts,enable);
433
434
435
436
437
438
439
}
void EditProfileDialog::colorSchemeAnimationUpdate()
{
    QAbstractItemModel* model = _ui->colorSchemeList->model();

    for ( int i = model->rowCount() ; i >= 0 ; i-- )
        _ui->colorSchemeList->update( model->index(i,0) );
440
}
441
void EditProfileDialog::updateColorSchemeList(bool selectCurrentScheme)
442
{
Robert Knight's avatar
   
Robert Knight committed
443
444
    if (!_ui->colorSchemeList->model())
        _ui->colorSchemeList->setModel(new QStandardItemModel(this));
445

446
    const QString& name = lookupProfile()->colorScheme();
447
448
    const ColorScheme* currentScheme = ColorSchemeManager::instance()->findColorScheme(name);

Robert Knight's avatar
   
Robert Knight committed
449
450
451
452
453
454
    QStandardItemModel* model = qobject_cast<QStandardItemModel*>(_ui->colorSchemeList->model());

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

455
456
457
    QList<const ColorScheme*> schemeList = ColorSchemeManager::instance()->allColorSchemes();
    QListIterator<const ColorScheme*> schemeIter(schemeList);

458
459
    QStandardItem* selectedItem = 0;

460
461
462
463
464
    while (schemeIter.hasNext())
    {
        const ColorScheme* colors = schemeIter.next();
        QStandardItem* item = new QStandardItem(colors->description());
        item->setData( QVariant::fromValue(colors) ,  Qt::UserRole + 1);
465
        item->setFlags( item->flags() );
466
467
       
        if ( currentScheme == colors ) 
Robert Knight's avatar
   
Robert Knight committed
468
469
            selectedItem = item;  

470
471
472
        model->appendRow(item);
    }

473
474
    model->sort(0);

Robert Knight's avatar
   
Robert Knight committed
475
    if ( selectCurrentScheme && selectedItem )
476
477
478
479
    {
        _ui->colorSchemeList->updateGeometry();
        _ui->colorSchemeList->selectionModel()->setCurrentIndex( selectedItem->index() , 
                                                                 QItemSelectionModel::Select );
Robert Knight's avatar
   
Robert Knight committed
480
481
482

        // update transparency warning label
        updateTransparencyWarning();
483
    }
484
}
485
void EditProfileDialog::updateKeyBindingsList(bool selectCurrentTranslator)
486
{
Robert Knight's avatar
   
Robert Knight committed
487
488
    if (!_ui->keyBindingList->model())
        _ui->keyBindingList->setModel(new QStandardItemModel(this));
489

Robert Knight's avatar
   
Robert Knight committed
490
    KeyboardTranslatorManager* keyManager = KeyboardTranslatorManager::instance();
491

492
    const QString& name = lookupProfile()
493
                                    ->property<QString>(Profile::KeyBindings);
494

495
    const KeyboardTranslator* currentTranslator = keyManager->findTranslator(name);
496
    
Robert Knight's avatar
   
Robert Knight committed
497
498
499
500
501
    QStandardItemModel* model = qobject_cast<QStandardItemModel*>(_ui->keyBindingList->model());

    Q_ASSERT(model);

    model->clear();
502

503
504
    QStandardItem* selectedItem = 0;

505
    QList<QString> translatorNames = keyManager->allTranslators();
506
507
508
509
510
    QListIterator<QString> iter(translatorNames);
    while (iter.hasNext())
    {
        const QString& name = iter.next();

511
        const KeyboardTranslator* translator = keyManager->findTranslator(name);
512
513
514

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

        if ( translator == currentTranslator )
518
            selectedItem = item;
519
520
521
522

        model->appendRow(item);
    }

523
    model->sort(0);
524
    
Robert Knight's avatar
   
Robert Knight committed
525
    if ( selectCurrentTranslator && selectedItem )
526
527
528
529
    {
        _ui->keyBindingList->selectionModel()->setCurrentIndex( selectedItem->index() , 
                                                                  QItemSelectionModel::Select );
    }
530
}
531
532
533
534
bool EditProfileDialog::eventFilter( QObject* watched , QEvent* event )
{
    if ( watched == _ui->colorSchemeList && event->type() == QEvent::Leave )
    {
535
536
537
538
        if ( _tempProfile->isPropertySet(Profile::ColorScheme) )
            preview(Profile::ColorScheme,_tempProfile->colorScheme());
        else
            unpreview(Profile::ColorScheme);
539
    }
540
541
542
543
544
	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()));
	}
545
546
547

    return KDialog::eventFilter(watched,event);
}
548
void EditProfileDialog::unpreviewAll()
549
{
550
551
552
    _delayedPreviewTimer->stop();
    _delayedPreviewProperties.clear();

553
554
555
556
557
    QHash<Profile::Property,QVariant> map;
    QHashIterator<int,QVariant> iter(_previewedProperties);
    while ( iter.hasNext() )
    {
        iter.next();
558
        map.insert((Profile::Property)iter.key(),iter.value());
559
560
561
    }

    // undo any preview changes
562
    if ( !map.isEmpty() )
563
564
565
566
        SessionManager::instance()->changeProfile(_profileKey,map,false);
}
void EditProfileDialog::unpreview(int property)
{
567
568
    _delayedPreviewProperties.remove(property);
    
569
570
    if (!_previewedProperties.contains(property))
        return;
571
    
572
573
574
575
576
577
    QHash<Profile::Property,QVariant> map;
    map.insert((Profile::Property)property,_previewedProperties[property]);
    SessionManager::instance()->changeProfile(_profileKey,map,false); 

    _previewedProperties.remove(property);
}
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
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
598
void EditProfileDialog::preview(int property , const QVariant& value)
599
600
601
{
    QHash<Profile::Property,QVariant> map;
    map.insert((Profile::Property)property,value);
602
603
    
    _delayedPreviewProperties.remove(property);
604

605
    const Profile* original = lookupProfile();
606
607

    if (!_previewedProperties.contains(property))    
608
        _previewedProperties.insert(property , original->property<QVariant>((Profile::Property)property) );
609
610
611
612
613
614
615
616

    // 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();

617
    delayedPreview( Profile::ColorScheme , name );
618
}
619
620
void EditProfileDialog::removeColorScheme()
{
621
622
623
624
625
    QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes();

    if ( !selected.isEmpty() )
    {
        const QString& name = selected.first().data(Qt::UserRole+1).value<const ColorScheme*>()->name();
626
627
628
        
        if (ColorSchemeManager::instance()->deleteColorScheme(name))    
            _ui->colorSchemeList->model()->removeRow(selected.first().row());
629
    }
630
}
631
void EditProfileDialog::showColorSchemeEditor(bool isNewScheme)
632
633
634
{    
    QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes();

635
    QAbstractItemModel* model = _ui->colorSchemeList->model();
Robert Knight's avatar
   
Robert Knight committed
636
    const ColorScheme* colors = 0;
637
    if ( !selected.isEmpty() )
Robert Knight's avatar
   
Robert Knight committed
638
        colors = model->data(selected.first(),Qt::UserRole+1).value<const ColorScheme*>();
639
    else
Robert Knight's avatar
   
Robert Knight committed
640
        colors = ColorSchemeManager::instance()->defaultColorScheme();
641

Robert Knight's avatar
   
Robert Knight committed
642
    Q_ASSERT(colors);
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658

    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 )
659
    {
660
        ColorScheme* newScheme = new ColorScheme(*editor->colorScheme());
661

662
663
664
        // if this is a new color scheme, pick a name based on the description
        if ( isNewScheme )
            newScheme->setName(newScheme->description());
665

666
667
        ColorSchemeManager::instance()->addColorScheme( newScheme );
        
Robert Knight's avatar
   
Robert Knight committed
668
        updateColorSchemeList(true);
669

Robert Knight's avatar
   
Robert Knight committed
670
        preview(Profile::ColorScheme,newScheme->name());
671
672
673
674
675
676
677
678
679
680
    }
}
void EditProfileDialog::newColorScheme()
{
    showColorSchemeEditor(true);    
}
void EditProfileDialog::editColorScheme()
{
    showColorSchemeEditor(false);
}
681
682
683
684
685
686
687
void EditProfileDialog::colorSchemeSelected()
{
    QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes();

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

Robert Knight's avatar
   
Robert Knight committed
690
        kDebug() << "Setting temp profile color to" << colors->name();
691
692
693
        
		previewColorScheme(selected.first());
		_tempProfile->setProperty(Profile::ColorScheme,colors->name());
Robert Knight's avatar
   
Robert Knight committed
694
695
696

        updateTransparencyWarning();
    }
Robert Knight's avatar
   
Robert Knight committed
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712

    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
713
714
715
716
717
718
719
720
721
722
}
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)) );
723
724
    }
}
Robert Knight's avatar
   
Robert Knight committed
725
void EditProfileDialog::setupKeyboardPage(const Profile* /* info */)
726
727
{
    // setup translator list
728
    updateKeyBindingsList(true); 
729

730
731
732
    connect( _ui->keyBindingList->selectionModel() , 
                SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),
                SLOT(keyBindingSelected()) );
733
734
    connect( _ui->newKeyBindingsButton , SIGNAL(clicked()) , this ,
            SLOT(newKeyBinding()) );
Robert Knight's avatar
   
Robert Knight committed
735
736
737

    updateKeyBindingsButtons();

738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
    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
754
755

    updateKeyBindingsButtons();
756
757
758
759
760
761
762
763
}
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();
764
765
        if (KeyboardTranslatorManager::instance()->deleteTranslator(name))
            _ui->keyBindingList->model()->removeRow(selected.first().row());   
766
767
    }
}
768
void EditProfileDialog::showKeyBindingEditor(bool isNewTranslator)
769
770
{
    QModelIndexList selected = _ui->keyBindingList->selectionModel()->selectedIndexes();
771
    QAbstractItemModel* model = _ui->keyBindingList->model();
772

Robert Knight's avatar
   
Robert Knight committed
773
    const KeyboardTranslator* translator = 0;
774
    if ( !selected.isEmpty() )
Robert Knight's avatar
   
Robert Knight committed
775
        translator = model->data(selected.first(),Qt::UserRole+1).value<const KeyboardTranslator*>();
776
    else
Robert Knight's avatar
   
Robert Knight committed
777
        translator = KeyboardTranslatorManager::instance()->defaultTranslator();
778

Robert Knight's avatar
   
Robert Knight committed
779
    Q_ASSERT(translator);
780

781
    KDialog* dialog = new KDialog(this);
782

783
784
785
786
    if ( isNewTranslator )
        dialog->setCaption(i18n("New Key Binding List"));
    else
        dialog->setCaption(i18n("Edit Key Binding List"));
787

788
789
    KeyBindingEditor* editor = new KeyBindingEditor;
    dialog->setMainWidget(editor);
790
791
792
    
    if ( translator )
        editor->setup(translator);
793
794
795
796
797
798
799
800
801
802

    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());
803

804
        KeyboardTranslatorManager::instance()->addTranslator( newTranslator );
805

806
807
        updateKeyBindingsList();
        
808
        const QString& currentTranslator = lookupProfile()
809
                                        ->property<QString>(Profile::KeyBindings);
810

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

846
847
        ++possible;
    }
848
}
849
850

void EditProfileDialog::setupScrollingPage(const Profile* profile)
851
{
852
    // setup scrollbar radio
853
    int scrollBarPosition = profile->property<int>(Profile::ScrollBarPosition);
854
   
Robert Knight's avatar
Robert Knight committed
855
856
857
858
859
    RadioOption positions[] = { {_ui->scrollBarHiddenButton,Profile::ScrollBarHidden,SLOT(hideScrollBar())},
                                {_ui->scrollBarLeftButton,Profile::ScrollBarLeft,SLOT(showScrollBarLeft())},
                                {_ui->scrollBarRightButton,Profile::ScrollBarRight,SLOT(showScrollBarRight())},
                                {0,0,0} 
                              }; 
860

Robert Knight's avatar
Robert Knight committed
861
    setupRadio( positions , scrollBarPosition );
862
863
   
    // setup scrollback type radio
864
    int scrollBackType = profile->property<int>(Profile::HistoryMode);
865
    
Robert Knight's avatar
Robert Knight committed
866
867
868
869
870
    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 ); 
871
872
    
    // setup scrollback line count spinner
873
    _ui->scrollBackLinesSpinner->setValue( profile->property<int>(Profile::HistorySize) );
874
875
876
877

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

880
881
882
883
884
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
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
910
911
912
913
914
915
916
917
918
919
920
    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 );
921
922

    // interaction options
923
    _ui->wordCharacterEdit->setText( profile->property<QString>(Profile::WordCharacters) );
924
925
926
927
928

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

    // cursor options
929
    if ( profile->property<bool>(Profile::UseCustomCursorColor) )
930
931
932
933
        _ui->customCursorColorButton->setChecked(true);
    else
        _ui->autoCursorColorButton->setChecked(true);

934
    _ui->customColorSelectButton->setColor( profile->property<QColor>(Profile::CustomCursorColor) );
935
936
937
938
939
940

    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&)) );

941
    int shape = profile->property<int>(Profile::CursorShape);
942
943
944
    _ui->cursorShapeCombo->setCurrentIndex(shape);

    connect( _ui->cursorShapeCombo , SIGNAL(activated(int)) , this , SLOT(setCursorShape(int)) ); 
945
946
947
948
949
950

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

951
    _ui->characterEncodingLabel->setText( profile->property<QString>(Profile::DefaultEncoding) );
952
953
954
955
956
957
958
959

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

    _tempProfile->setProperty(Profile::DefaultEncoding,name);
    _ui->characterEncodingLabel->setText(codec->name());
960
961
962
963
}
void EditProfileDialog::customCursorColorChanged(const QColor& color)
{
    _tempProfile->setProperty(Profile::CustomCursorColor,color);
964
965
966

    // ensure that custom cursor colors are enabled
    _ui->customCursorColorButton->click();
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
}
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);
983
984
985
986
}
void EditProfileDialog::toggleBlinkingCursor(bool enable)
{
    _tempProfile->setProperty(Profile::BlinkingCursorEnabled,enable);
987
988
989
990
991
992
993
994
995
996
997
998
999
}
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);
}
1000
void EditProfileDialog::fontSelected(const QFont& font)
1001
{
1002
1003
1004
1005
1006
1007
   QSlider* slider = _ui->fontSizeSlider;
   
   _ui->fontSizeSlider->setRange( qMin(slider->minimum(),font.pointSize()) ,
                                  qMax(slider->maximum(),font.pointSize()) );
   _ui->fontSizeSlider->setValue(font.pointSize());
   _ui->fontPreviewLabel->setFont(font);
1008
   
1009
   _tempProfile->setProperty(Profile::Font,font);
1010

1011
   preview(Profile::Font,font);
1012
}
1013
void EditProfileDialog::showFontDialog()
1014
1015
{
    QFont currentFont = _ui->fontPreviewLabel->font();
1016
   
1017
1018
    KFontDialog* dialog = new KFontDialog(this, KFontChooser::FixedFontsOnly);
    dialog->setFont(currentFont, true);
1019

1020
    connect( dialog , SIGNAL(fontSelected(const QFont&)) , this , SLOT(fontSelected(const QFont&)) );
1021
1022
1023

    if (dialog->exec() == QDialog::Rejected)
		fontSelected(currentFont);
1024
}
1025
void EditProfileDialog::setFontSize(int pointSize)
1026
1027
1028
{
    QFont newFont = _ui->fontPreviewLabel->font();
    newFont.setPointSize(pointSize);
1029
	_ui->fontPreviewLabel->setFont(newFont);
1030
1031

    _tempProfile->setProperty(Profile::