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

    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"

Jekyll Wu's avatar
Jekyll Wu committed
23 24 25
// Standard
#include <cmath>

26
// Qt
Dirk Mueller's avatar
Dirk Mueller committed
27 28
#include <QtGui/QBrush>
#include <QtGui/QPainter>
29
#include <QStandardItem>
30
#include <QtCore/QTextCodec>
31 32
#include <QtGui/QLinearGradient>
#include <QtGui/QRadialGradient>
Michal Humpula's avatar
Michal Humpula committed
33
#include <QtGui/QIcon>
34
#include <QtCore/QTimer>
Kurt Hindenburg's avatar
Kurt Hindenburg committed
35
#include <QtCore/QUrl>
36
#include <QFontDialog>
37
#include <QFileDialog>
38
#include <QInputDialog>
39
#include <QDialog>
40
// KDE
41 42
#include <KCodecAction>

43
#include <KIconDialog>
44
#include <KWindowSystem>
45
#include <KMessageBox>
46
#include <KLocalizedString>
Laurent Montel's avatar
Laurent Montel committed
47 48 49
#include <QDialogButtonBox>
#include <QPushButton>
#include <QVBoxLayout>
50 51

// Konsole
52
#include "ColorSchemeManager.h"
53
#include "ui_EditProfileDialog.h"
54 55
#include "KeyBindingEditor.h"
#include "KeyboardTranslator.h"
56
#include "KeyboardTranslatorManager.h"
57
#include "ProfileManager.h"
58
#include "ShellCommand.h"
59
#include "WindowSystemInfo.h"
60

61 62
using namespace Konsole;

63
EditProfileDialog::EditProfileDialog(QWidget* aParent)
Laurent Montel's avatar
Laurent Montel committed
64
    : QDialog(aParent)
65
    , _delayedPreviewTimer(new QTimer(this))
66
    , _colorDialog(0)
67
{
Laurent Montel's avatar
Laurent Montel committed
68 69 70 71 72 73 74 75 76
    setWindowTitle(i18n("Edit Profile"));
    mButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel|QDialogButtonBox::Apply);
    QWidget *mainWidget = new QWidget(this);
    QVBoxLayout *mainLayout = new QVBoxLayout;
    setLayout(mainLayout);
    mainLayout->addWidget(mainWidget);
    QPushButton *okButton = mButtonBox->button(QDialogButtonBox::Ok);
    okButton->setDefault(true);
    okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
77 78
    connect(mButtonBox, &QDialogButtonBox::accepted, this, &Konsole::EditProfileDialog::accept);
    connect(mButtonBox, &QDialogButtonBox::rejected, this, &Konsole::EditProfileDialog::reject);
79

80
    // disable the apply button , since no modification has been made
Laurent Montel's avatar
Laurent Montel committed
81
    mButtonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
82

Laurent Montel's avatar
Laurent Montel committed
83
    connect(mButtonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, this, &Konsole::EditProfileDialog::save);
Jekyll Wu's avatar
Jekyll Wu committed
84

85
    connect(_delayedPreviewTimer, &QTimer::timeout, this, &Konsole::EditProfileDialog::delayedPreviewActivate);
Jekyll Wu's avatar
Jekyll Wu committed
86

87
    _ui = new Ui::EditProfileDialog();
Laurent Montel's avatar
Laurent Montel committed
88 89
    _ui->setupUi(mainWidget);
    mainLayout->addWidget(mButtonBox);
90

91 92 93 94 95 96 97 98 99 100
    // 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
Kurt Hindenburg's avatar
Kurt Hindenburg committed
101
    _pageNeedsUpdate.resize(_ui->tabWidget->count());
Laurent Montel's avatar
Laurent Montel committed
102
    connect(_ui->tabWidget, &QTabWidget::currentChanged, this, &Konsole::EditProfileDialog::preparePage);
103

104
    createTempProfile();
105
}
106
EditProfileDialog::~EditProfileDialog()
107 108
{
    delete _ui;
109
}
110
void EditProfileDialog::save()
111
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
112
    if (_tempProfile->isEmpty())
113
        return;
114

115
    ProfileManager::instance()->changeProfile(_profile, _tempProfile->setProperties());
116 117 118

    // ensure that these settings are not undone by a call
    // to unpreview()
Kurt Hindenburg's avatar
Kurt Hindenburg committed
119 120
    QHashIterator<Profile::Property, QVariant> iter(_tempProfile->setProperties());
    while (iter.hasNext()) {
121 122 123
        iter.next();
        _previewedProperties.remove(iter.key());
    }
124

125 126
    createTempProfile();

Laurent Montel's avatar
Laurent Montel committed
127
    mButtonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
128 129 130 131
}
void EditProfileDialog::reject()
{
    unpreviewAll();
Laurent Montel's avatar
Laurent Montel committed
132
    QDialog::reject();
133 134 135
}
void EditProfileDialog::accept()
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
136 137
    Q_ASSERT(_profile);
    Q_ASSERT(_tempProfile);
138

Kurt Hindenburg's avatar
Kurt Hindenburg committed
139 140 141
    if ((_tempProfile->isPropertySet(Profile::Name) &&
            _tempProfile->name().isEmpty())
            || (_profile->name().isEmpty() && _tempProfile->name().isEmpty())) {
142
        KMessageBox::sorry(this,
Kurt Hindenburg's avatar
Kurt Hindenburg committed
143 144
                           i18n("<p>Each profile must have a name before it can be saved "
                                "into disk.</p>"));
145 146
        return;
    }
147
    save();
148
    unpreviewAll();
Laurent Montel's avatar
Laurent Montel committed
149
    QDialog::accept();
150
}
151
QString EditProfileDialog::groupProfileNames(const ProfileGroup::Ptr group, int maxLength)
Robert Knight's avatar
 
Robert Knight committed
152
{
153 154
    QString caption;
    int count = group->profiles().count();
Kurt Hindenburg's avatar
Kurt Hindenburg committed
155
    for (int i = 0; i < count; i++) {
156
        caption += group->profiles()[i]->name();
Kurt Hindenburg's avatar
Kurt Hindenburg committed
157
        if (i < (count - 1)) {
158 159
            caption += ',';
            // limit caption length to prevent very long window titles
Kurt Hindenburg's avatar
Kurt Hindenburg committed
160
            if (maxLength > 0 && caption.length() > maxLength) {
161
                caption += QLatin1String("...");
162 163 164 165 166 167 168 169 170
                break;
            }
        }
    }
    return caption;
}
void EditProfileDialog::updateCaption(const Profile::Ptr profile)
{
    const int MAX_GROUP_CAPTION_LENGTH = 25;
Kurt Hindenburg's avatar
Kurt Hindenburg committed
171 172 173
    ProfileGroup::Ptr group = profile->asGroup();
    if (group && group->profiles().count() > 1) {
        QString caption = groupProfileNames(group, MAX_GROUP_CAPTION_LENGTH);
Laurent Montel's avatar
Laurent Montel committed
174
        setWindowTitle(i18np("Editing profile: %2",
Kurt Hindenburg's avatar
Kurt Hindenburg committed
175 176 177 178
                         "Editing %1 profiles: %2",
                         group->profiles().count(),
                         caption));
    } else {
Laurent Montel's avatar
Laurent Montel committed
179
        setWindowTitle(i18n("Edit Profile \"%1\"", profile->name()));
180
    }
Robert Knight's avatar
 
Robert Knight committed
181
}
182
void EditProfileDialog::setProfile(Profile::Ptr profile)
183
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
184
    Q_ASSERT(profile);
185

186 187
    _profile = profile;

188
    // update caption
189
    updateCaption(profile);
190

191 192 193 194 195
    // 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);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
196
    preparePage(_ui->tabWidget->currentIndex());
197

Kurt Hindenburg's avatar
Kurt Hindenburg committed
198
    if (_tempProfile) {
199
        createTempProfile();
200
    }
201
}
202
const Profile::Ptr EditProfileDialog::lookupProfile() const
203
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
204
    return _profile;
205
}
Robert Knight's avatar
 
Robert Knight committed
206
void EditProfileDialog::preparePage(int page)
207
{
Jekyll Wu's avatar
Jekyll Wu committed
208
    const Profile::Ptr profile = lookupProfile();
209

Kurt Hindenburg's avatar
Kurt Hindenburg committed
210
    Q_ASSERT(_pageNeedsUpdate.count() > page);
Jekyll Wu's avatar
Jekyll Wu committed
211
    Q_ASSERT(profile);
212

Robert Knight's avatar
 
Robert Knight committed
213
    QWidget* pageWidget = _ui->tabWidget->widget(page);
214

Kurt Hindenburg's avatar
Kurt Hindenburg committed
215 216
    if (_pageNeedsUpdate[page]) {
        if (pageWidget == _ui->generalTab)
Jekyll Wu's avatar
Jekyll Wu committed
217
            setupGeneralPage(profile);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
218
        else if (pageWidget == _ui->tabsTab)
Jekyll Wu's avatar
Jekyll Wu committed
219
            setupTabsPage(profile);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
220
        else if (pageWidget == _ui->appearanceTab)
Jekyll Wu's avatar
Jekyll Wu committed
221
            setupAppearancePage(profile);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
222
        else if (pageWidget == _ui->scrollingTab)
Jekyll Wu's avatar
Jekyll Wu committed
223
            setupScrollingPage(profile);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
224
        else if (pageWidget == _ui->keyboardTab)
Jekyll Wu's avatar
Jekyll Wu committed
225
            setupKeyboardPage(profile);
226 227
        else if (pageWidget == _ui->mouseTab)
            setupMousePage(profile);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
228
        else if (pageWidget == _ui->advancedTab)
Jekyll Wu's avatar
Jekyll Wu committed
229
            setupAdvancedPage(profile);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
230 231
        else
            Q_ASSERT(false);
232

233
        _pageNeedsUpdate[page] = false;
234
    }
Robert Knight's avatar
 
Robert Knight committed
235 236 237 238
}
void EditProfileDialog::selectProfileName()
{
    _ui->profileNameEdit->setFocus();
239
    _ui->profileNameEdit->selectAll();
240
}
Jekyll Wu's avatar
Jekyll Wu committed
241
void EditProfileDialog::setupGeneralPage(const Profile::Ptr profile)
242
{
243
    // basic profile options
244
    {
245 246 247 248
        _ui->emptyNameWarningWidget->setWordWrap(false);
        _ui->emptyNameWarningWidget->setCloseButtonVisible(false);
        _ui->emptyNameWarningWidget->setMessageType(KMessageWidget::Warning);

Jekyll Wu's avatar
Jekyll Wu committed
249
        ProfileGroup::Ptr group = profile->asGroup();
Kurt Hindenburg's avatar
Kurt Hindenburg committed
250
        if (!group || group->profiles().count() < 2) {
Jekyll Wu's avatar
Jekyll Wu committed
251
            _ui->profileNameEdit->setText(profile->name());
Kurt Hindenburg's avatar
Kurt Hindenburg committed
252
            _ui->profileNameEdit->setClearButtonEnabled(true);
253

Jekyll Wu's avatar
Jekyll Wu committed
254
            _ui->emptyNameWarningWidget->setVisible(profile->name().isEmpty());
255
            _ui->emptyNameWarningWidget->setText(i18n("Profile name is empty."));
Kurt Hindenburg's avatar
Kurt Hindenburg committed
256 257
        } else {
            _ui->profileNameEdit->setText(groupProfileNames(group, -1));
258
            _ui->profileNameEdit->setEnabled(false);
259
            _ui->profileNameLabel->setEnabled(false);
260 261

            _ui->emptyNameWarningWidget->setVisible(false);
262 263
        }
    }
264

Jekyll Wu's avatar
Jekyll Wu committed
265
    ShellCommand command(profile->command() , profile->arguments());
Kurt Hindenburg's avatar
Kurt Hindenburg committed
266
    _ui->commandEdit->setText(command.fullCommand());
267 268
    // If a "completion" is requested, consider changing this to KLineEdit
    // and using KCompletion.
269
    _ui->initialDirEdit->setText(profile->defaultWorkingDirectory());
Kurt Hindenburg's avatar
Kurt Hindenburg committed
270
    _ui->initialDirEdit->setClearButtonEnabled(true);
271

Michal Humpula's avatar
Michal Humpula committed
272 273
    _ui->dirSelectButton->setIcon(QIcon::fromTheme(QStringLiteral("folder-open")));
    _ui->iconSelectButton->setIcon(QIcon::fromTheme(profile->icon()));
274
    _ui->startInSameDirButton->setChecked(profile->startInCurrentSessionDir());
275

276 277 278 279
    // terminal options
    _ui->terminalColumnsEntry->setValue(profile->terminalColumns());
    _ui->terminalRowsEntry->setValue(profile->terminalRows());

280
    // window options
281
    _ui->showTerminalSizeHintButton->setChecked(profile->showTerminalSizeHint());
282 283

    // signals and slots
284 285
    connect(_ui->dirSelectButton, &QToolButton::clicked, this, &Konsole::EditProfileDialog::selectInitialDir);
    connect(_ui->iconSelectButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::selectIcon);
Laurent Montel's avatar
Laurent Montel committed
286 287 288 289 290 291
    connect(_ui->startInSameDirButton, &QCheckBox::toggled, this , &Konsole::EditProfileDialog::startInSameDir);
    connect(_ui->profileNameEdit, &QLineEdit::textChanged, this, &Konsole::EditProfileDialog::profileNameChanged);
    connect(_ui->initialDirEdit, &QLineEdit::textChanged, this, &Konsole::EditProfileDialog::initialDirChanged);
    connect(_ui->commandEdit, &QLineEdit::textChanged, this, &Konsole::EditProfileDialog::commandChanged);
    connect(_ui->environmentEditButton , &QPushButton::clicked, this, &Konsole::EditProfileDialog::showEnvironmentEditor);

Laurent Montel's avatar
Laurent Montel committed
292 293
    connect(_ui->terminalColumnsEntry, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::terminalColumnsEntryChanged);
    connect(_ui->terminalRowsEntry, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::terminalRowsEntryChanged);
Laurent Montel's avatar
Laurent Montel committed
294 295

    connect(_ui->showTerminalSizeHintButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::showTerminalSizeHint);
296 297 298
}
void EditProfileDialog::showEnvironmentEditor()
{
299
    bool ok;
Jekyll Wu's avatar
Jekyll Wu committed
300
    const Profile::Ptr profile = lookupProfile();
301
    QStringList currentEnvironment = profile->environment();
302

303 304 305
    QString text = QInputDialog::getMultiLineText(this, 
            i18n("Edit Environment"),
            i18n("One environment variable per line"),
306
            currentEnvironment.join(QStringLiteral("\n")),
307
            &ok);
308

309 310
    if (ok && !text.isEmpty()) {
        QStringList newEnvironment = text.split('\n');
Kurt Hindenburg's avatar
Kurt Hindenburg committed
311
        updateTempProfileProperty(Profile::Environment, newEnvironment);
312 313
    }
}
Jekyll Wu's avatar
Jekyll Wu committed
314
void EditProfileDialog::setupTabsPage(const Profile::Ptr profile)
315
{
316
    // tab title format
317 318 319
    _ui->renameTabWidget->setTabTitleText(profile->localTabTitleFormat());
    _ui->renameTabWidget->setRemoteTabTitleText(profile->remoteTabTitleFormat());

Laurent Montel's avatar
Laurent Montel committed
320 321
    connect(_ui->renameTabWidget, &Konsole::RenameTabWidget::tabTitleFormatChanged, this, &Konsole::EditProfileDialog::tabTitleFormatChanged);
    connect(_ui->renameTabWidget, &Konsole::RenameTabWidget::remoteTabTitleFormatChanged, this, &Konsole::EditProfileDialog::remoteTabTitleFormatChanged);
322

Jekyll Wu's avatar
Jekyll Wu committed
323
    // tab monitoring
Jekyll Wu's avatar
Jekyll Wu committed
324
    const int silenceSeconds = profile->silenceSeconds();
Jekyll Wu's avatar
Jekyll Wu committed
325
    _ui->silenceSecondsSpinner->setValue(silenceSeconds);
326
    _ui->silenceSecondsSpinner->setSuffix(ki18ncp("Unit of time", " second", " seconds"));
Jekyll Wu's avatar
Jekyll Wu committed
327

Laurent Montel's avatar
Laurent Montel committed
328
    connect(_ui->silenceSecondsSpinner, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Konsole::EditProfileDialog::silenceSecondsChanged);
329
}
330

331 332 333 334 335
void EditProfileDialog::terminalColumnsEntryChanged(int value)
{
    updateTempProfileProperty(Profile::TerminalColumns, value);
}
void EditProfileDialog::terminalRowsEntryChanged(int value)
336
{
337
    updateTempProfileProperty(Profile::TerminalRows, value);
338
}
339
void EditProfileDialog::showTerminalSizeHint(bool value)
340
{
341
    updateTempProfileProperty(Profile::ShowTerminalSizeHint, value);
342
}
343 344
void EditProfileDialog::tabTitleFormatChanged(const QString& format)
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
345
    updateTempProfileProperty(Profile::LocalTabTitleFormat, format);
346 347 348
}
void EditProfileDialog::remoteTabTitleFormatChanged(const QString& format)
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
349
    updateTempProfileProperty(Profile::RemoteTabTitleFormat, format);
350 351
}

352 353 354 355 356
void EditProfileDialog::silenceSecondsChanged(int seconds)
{
    updateTempProfileProperty(Profile::SilenceSeconds, seconds);
}

357 358
void EditProfileDialog::selectIcon()
{
Craig Drummond's avatar
Craig Drummond committed
359
    const QString& icon = KIconDialog::getIcon(KIconLoader::Desktop, KIconLoader::Application,
Kurt Hindenburg's avatar
Kurt Hindenburg committed
360 361
                          false, 0, false, this);
    if (!icon.isEmpty()) {
Michal Humpula's avatar
Michal Humpula committed
362
        _ui->iconSelectButton->setIcon(QIcon::fromTheme(icon));
Kurt Hindenburg's avatar
Kurt Hindenburg committed
363
        updateTempProfileProperty(Profile::Icon, icon);
364 365 366 367
    }
}
void EditProfileDialog::profileNameChanged(const QString& text)
{
368 369
    _ui->emptyNameWarningWidget->setVisible(text.isEmpty());

Kurt Hindenburg's avatar
Kurt Hindenburg committed
370
    updateTempProfileProperty(Profile::Name, text);
371
    updateTempProfileProperty(Profile::UntranslatedName, text);
372
    updateCaption(_tempProfile);
373
}
374 375
void EditProfileDialog::startInSameDir(bool sameDir)
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
376
    updateTempProfileProperty(Profile::StartInCurrentSessionDir, sameDir);
377
}
378 379
void EditProfileDialog::initialDirChanged(const QString& dir)
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
380
    updateTempProfileProperty(Profile::Directory, dir);
381 382 383
}
void EditProfileDialog::commandChanged(const QString& command)
{
384 385
    ShellCommand shellCommand(command);

Kurt Hindenburg's avatar
Kurt Hindenburg committed
386 387
    updateTempProfileProperty(Profile::Command, shellCommand.command());
    updateTempProfileProperty(Profile::Arguments, shellCommand.arguments());
388 389 390
}
void EditProfileDialog::selectInitialDir()
{
391 392 393
    const QUrl url = QFileDialog::getExistingDirectoryUrl(this,
                     i18n("Select Initial Directory"),
                     QUrl::fromUserInput(_ui->initialDirEdit->text()));
394

Kurt Hindenburg's avatar
Kurt Hindenburg committed
395
    if (!url.isEmpty())
396
        _ui->initialDirEdit->setText(url.path());
397
}
Jekyll Wu's avatar
Jekyll Wu committed
398
void EditProfileDialog::setupAppearancePage(const Profile::Ptr profile)
399
{
400
    ColorSchemeViewDelegate* delegate = new ColorSchemeViewDelegate(this);
401
    _ui->colorSchemeList->setItemDelegate(delegate);
402

Robert Knight's avatar
 
Robert Knight committed
403
    _ui->transparencyWarningWidget->setVisible(false);
404 405 406
    _ui->transparencyWarningWidget->setWordWrap(true);
    _ui->transparencyWarningWidget->setCloseButtonVisible(false);
    _ui->transparencyWarningWidget->setMessageType(KMessageWidget::Warning);
407

Robert Knight's avatar
 
Robert Knight committed
408 409 410
    _ui->editColorSchemeButton->setEnabled(false);
    _ui->removeColorSchemeButton->setEnabled(false);

411 412
    // setup color list
    updateColorSchemeList(true);
413

414 415
    _ui->colorSchemeList->setMouseTracking(true);
    _ui->colorSchemeList->installEventFilter(this);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
416
    _ui->colorSchemeList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
417

Laurent Montel's avatar
Laurent Montel committed
418 419
    connect(_ui->colorSchemeList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &Konsole::EditProfileDialog::colorSchemeSelected);
    connect(_ui->colorSchemeList, &QListView::entered, this, &Konsole::EditProfileDialog::previewColorScheme);
420

Robert Knight's avatar
 
Robert Knight committed
421
    updateColorSchemeButtons();
422

Laurent Montel's avatar
Laurent Montel committed
423 424 425
    connect(_ui->editColorSchemeButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::editColorScheme);
    connect(_ui->removeColorSchemeButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::removeColorScheme);
    connect(_ui->newColorSchemeButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::newColorScheme);
426

427
    // setup font preview
Jekyll Wu's avatar
Jekyll Wu committed
428
    const bool antialias = profile->antiAliasFonts();
429

430 431
    QFont profileFont = profile->font();
    profileFont.setStyleStrategy(antialias ? QFont::PreferAntialias : QFont::NoAntialias);
432

433
    _ui->fontPreviewLabel->installEventFilter(this);
434
    _ui->fontPreviewLabel->setFont(profileFont);
435
    setFontInputValue(profileFont);
436

437
    connect(_ui->fontSizeInput, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), this, &Konsole::EditProfileDialog::setFontSize);
Laurent Montel's avatar
Laurent Montel committed
438
    connect(_ui->selectFontButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::showFontDialog);
439

Kurt Hindenburg's avatar
Kurt Hindenburg committed
440
    // setup font smoothing
441
    _ui->antialiasTextButton->setChecked(antialias);
Laurent Montel's avatar
Laurent Montel committed
442
    connect(_ui->antialiasTextButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::setAntialiasText);
443

Jekyll Wu's avatar
Jekyll Wu committed
444
    _ui->boldIntenseButton->setChecked(profile->boldIntense());
Laurent Montel's avatar
Laurent Montel committed
445
    connect(_ui->boldIntenseButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::setBoldIntense);
446
    _ui->enableMouseWheelZoomButton->setChecked(profile->mouseWheelZoomEnabled());
Laurent Montel's avatar
Laurent Montel committed
447
    connect(_ui->enableMouseWheelZoomButton, &QCheckBox::toggled, this, &Konsole::EditProfileDialog::toggleMouseWheelZoom);
448 449 450
}
void EditProfileDialog::setAntialiasText(bool enable)
{
451 452
    QFont profileFont = _ui->fontPreviewLabel->font();
    profileFont.setStyleStrategy(enable ? QFont::PreferAntialias : QFont::NoAntialias);
453

454
    // update preview to reflect text smoothing state
455
    fontSelected(profileFont);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
456
    updateTempProfileProperty(Profile::AntiAliasFonts, enable);
457
}
458 459
void EditProfileDialog::setBoldIntense(bool enable)
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
460 461
    preview(Profile::BoldIntense, enable);
    updateTempProfileProperty(Profile::BoldIntense, enable);
462
}
463 464 465 466
void EditProfileDialog::toggleMouseWheelZoom(bool enable)
{
    updateTempProfileProperty(Profile::MouseWheelZoomEnabled, enable);
}
467
void EditProfileDialog::updateColorSchemeList(bool selectCurrentScheme)
468
{
Robert Knight's avatar
 
Robert Knight committed
469 470
    if (!_ui->colorSchemeList->model())
        _ui->colorSchemeList->setModel(new QStandardItemModel(this));
471

472
    const QString& name = lookupProfile()->colorScheme();
473 474
    const ColorScheme* currentScheme = ColorSchemeManager::instance()->findColorScheme(name);

Robert Knight's avatar
 
Robert Knight committed
475 476 477
    QStandardItemModel* model = qobject_cast<QStandardItemModel*>(_ui->colorSchemeList->model());

    Q_ASSERT(model);
478

Robert Knight's avatar
 
Robert Knight committed
479 480
    model->clear();

481 482
    QStandardItem* selectedItem = 0;

483 484
    QList<const ColorScheme*> schemeList = ColorSchemeManager::instance()->allColorSchemes();

Kurt Hindenburg's avatar
Kurt Hindenburg committed
485
    foreach(const ColorScheme* scheme, schemeList) {
486 487
        QStandardItem* item = new QStandardItem(scheme->description());
        item->setData(QVariant::fromValue(scheme) ,  Qt::UserRole + 1);
488
        item->setData(QVariant::fromValue(_profile->font()),  Qt::UserRole + 2);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
489
        item->setFlags(item->flags());
490

491
        if (currentScheme == scheme)
Kurt Hindenburg's avatar
Kurt Hindenburg committed
492
            selectedItem = item;
Robert Knight's avatar
 
Robert Knight committed
493

494 495 496
        model->appendRow(item);
    }

497 498
    model->sort(0);

Kurt Hindenburg's avatar
Kurt Hindenburg committed
499
    if (selectCurrentScheme && selectedItem) {
500
        _ui->colorSchemeList->updateGeometry();
Kurt Hindenburg's avatar
Kurt Hindenburg committed
501 502
        _ui->colorSchemeList->selectionModel()->setCurrentIndex(selectedItem->index() ,
                QItemSelectionModel::Select);
Robert Knight's avatar
 
Robert Knight committed
503 504 505

        // update transparency warning label
        updateTransparencyWarning();
506
    }
507
}
508
void EditProfileDialog::updateKeyBindingsList(bool selectCurrentTranslator)
509
{
Robert Knight's avatar
 
Robert Knight committed
510 511
    if (!_ui->keyBindingList->model())
        _ui->keyBindingList->setModel(new QStandardItemModel(this));
512

513
    const QString& name = lookupProfile()->keyBindings();
514

515
    KeyboardTranslatorManager* keyManager = KeyboardTranslatorManager::instance();
516
    const KeyboardTranslator* currentTranslator = keyManager->findTranslator(name);
517

Robert Knight's avatar
 
Robert Knight committed
518 519 520 521 522
    QStandardItemModel* model = qobject_cast<QStandardItemModel*>(_ui->keyBindingList->model());

    Q_ASSERT(model);

    model->clear();
523

524 525
    QStandardItem* selectedItem = 0;

Jekyll Wu's avatar
Jekyll Wu committed
526
    QStringList translatorNames = keyManager->allTranslators();
Kurt Hindenburg's avatar
Kurt Hindenburg committed
527
    foreach(const QString& translatorName, translatorNames) {
528
        const KeyboardTranslator* translator = keyManager->findTranslator(translatorName);
Laurent Montel's avatar
Laurent Montel committed
529
        if (!translator) continue;
530 531

        QStandardItem* item = new QStandardItem(translator->description());
532
        item->setEditable(false);
Kurt Hindenburg's avatar
Kurt Hindenburg committed
533
        item->setData(QVariant::fromValue(translator), Qt::UserRole + 1);
534
        item->setData(QVariant::fromValue(_profile->font()), Qt::UserRole + 2);
Michal Humpula's avatar
Michal Humpula committed
535
        item->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-keyboard")));
536

Kurt Hindenburg's avatar
Kurt Hindenburg committed
537
        if (translator == currentTranslator)
538
            selectedItem = item;
539 540 541 542

        model->appendRow(item);
    }

543
    model->sort(0);
544

Kurt Hindenburg's avatar
Kurt Hindenburg committed
545 546 547
    if (selectCurrentTranslator && selectedItem) {
        _ui->keyBindingList->selectionModel()->setCurrentIndex(selectedItem->index() ,
                QItemSelectionModel::Select);
548
    }
549
}
550
bool EditProfileDialog::eventFilter(QObject* watched , QEvent* aEvent)
551
{
552
    if (watched == _ui->colorSchemeList && aEvent->type() == QEvent::Leave) {
Kurt Hindenburg's avatar
Kurt Hindenburg committed
553 554
        if (_tempProfile->isPropertySet(Profile::ColorScheme))
            preview(Profile::ColorScheme, _tempProfile->colorScheme());
555 556
        else
            unpreview(Profile::ColorScheme);
557
    }
558
    if (watched == _ui->fontPreviewLabel && aEvent->type() == QEvent::FontChange) {
559
        const QFont& labelFont = _ui->fontPreviewLabel->font();
560
        _ui->fontPreviewLabel->setText(i18n("%1", labelFont.family()));
561
    }
562

Laurent Montel's avatar
Laurent Montel committed
563
    return QDialog::eventFilter(watched, aEvent);
564
}
565
void EditProfileDialog::unpreviewAll()
566
{
567 568 569
    _delayedPreviewTimer->stop();
    _delayedPreviewProperties.clear();

Kurt Hindenburg's avatar
Kurt Hindenburg committed
570 571 572
    QHash<Profile::Property, QVariant> map;
    QHashIterator<int, QVariant> iter(_previewedProperties);
    while (iter.hasNext()) {
573
        iter.next();
Kurt Hindenburg's avatar
Kurt Hindenburg committed
574
        map.insert((Profile::Property)iter.key(), iter.value());
575 576 577
    }

    // undo any preview changes
Kurt Hindenburg's avatar
Kurt Hindenburg committed
578
    if (!map.isEmpty())
579
        ProfileManager::instance()->changeProfile(_profile, map, false);
580
}
581
void EditProfileDialog::unpreview(int aProperty)
582
{
583
    _delayedPreviewProperties.remove(aProperty);
584

585
    if (!_previewedProperties.contains(aProperty))
586
        return;
587

Kurt Hindenburg's avatar
Kurt Hindenburg committed
588
    QHash<Profile::Property, QVariant> map;
589
    map.insert((Profile::Property)aProperty, _previewedProperties[aProperty]);
590
    ProfileManager::instance()->changeProfile(_profile, map, false);
591

592
    _previewedProperties.remove(aProperty);
593
}
594
void EditProfileDialog::delayedPreview(int aProperty , const QVariant& value)
595
{
596
    _delayedPreviewProperties.insert(aProperty, value);
597 598

    _delayedPreviewTimer->stop();
599
    _delayedPreviewTimer->start(300);
600 601 602
}
void EditProfileDialog::delayedPreviewActivate()
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
603
    Q_ASSERT(qobject_cast<QTimer*>(sender()));
604

Kurt Hindenburg's avatar
Kurt Hindenburg committed
605 606
    QMutableHashIterator<int, QVariant> iter(_delayedPreviewProperties);
    if (iter.hasNext()) {
607
        iter.next();
Kurt Hindenburg's avatar
Kurt Hindenburg committed
608
        preview(iter.key(), iter.value());
609 610
    }
}
611
void EditProfileDialog::preview(int aProperty , const QVariant& value)
612
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
613
    QHash<Profile::Property, QVariant> map;
614
    map.insert((Profile::Property)aProperty, value);
615

616
    _delayedPreviewProperties.remove(aProperty);
617

618
    const Profile::Ptr original = lookupProfile();
619

620 621 622 623 624 625
    // skip previews for profile groups if the profiles in the group
    // have conflicting original values for the property
    //
    // TODO - Save the original values for each profile and use to unpreview properties
    ProfileGroup::Ptr group = original->asGroup();
    if (group && group->profiles().count() > 1 &&
626
            original->property<QVariant>((Profile::Property)aProperty).isNull())
627 628
        return;

629 630
    if (!_previewedProperties.contains(aProperty)) {
        _previewedProperties.insert(aProperty , original->property<QVariant>((Profile::Property)aProperty));
631
    }
632 633

    // temporary change to color scheme
634
    ProfileManager::instance()->changeProfile(_profile , map , false);
635 636 637
}
void EditProfileDialog::previewColorScheme(const QModelIndex& index)
{
Kurt Hindenburg's avatar
Kurt Hindenburg committed
638
    const QString& name = index.data(Qt::UserRole + 1).value<const ColorScheme*>()->name();
639

Kurt Hindenburg's avatar
Kurt Hindenburg committed
640
    delayedPreview(Profile::ColorScheme , name);
641
}
642 643
void EditProfileDialog::removeColorScheme()
{
644 645
    QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes();

Kurt Hindenburg's avatar
Kurt Hindenburg committed
646 647
    if (!selected.isEmpty()) {
        const QString& name = selected.first().data(Qt::UserRole + 1).value<const ColorScheme*>()->name();
648

Kurt Hindenburg's avatar
Kurt Hindenburg committed
649
        if (ColorSchemeManager::instance()->deleteColorScheme(name))
650