1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "fontsettingspage.h"
27 
28 #include "fontsettings.h"
29 #include "texteditorsettings.h"
30 #include "ui_fontsettingspage.h"
31 
32 #include <coreplugin/icore.h>
33 #include <utils/fileutils.h>
34 #include <utils/stringutils.h>
35 #include <utils/qtcassert.h>
36 #include <utils/theme/theme.h>
37 
38 #include <QFileDialog>
39 #include <QFontDatabase>
40 #include <QInputDialog>
41 #include <QMessageBox>
42 #include <QPalette>
43 #include <QPointer>
44 #include <QSettings>
45 #include <QTimer>
46 #include <QDebug>
47 
48 using namespace TextEditor::Internal;
49 
50 namespace TextEditor {
51 namespace Internal {
52 
53 struct ColorSchemeEntry
54 {
ColorSchemeEntryTextEditor::Internal::ColorSchemeEntry55     ColorSchemeEntry(const QString &fileName,
56                      bool readOnly):
57         fileName(fileName),
58         name(ColorScheme::readNameOfScheme(fileName)),
59         readOnly(readOnly)
60     { }
61 
62     QString fileName;
63     QString name;
64     QString id;
65     bool readOnly;
66 };
67 
68 
69 class SchemeListModel : public QAbstractListModel
70 {
71 public:
SchemeListModel(QObject * parent=nullptr)72     SchemeListModel(QObject *parent = nullptr):
73         QAbstractListModel(parent)
74     {
75     }
76 
rowCount(const QModelIndex & parent) const77     int rowCount(const QModelIndex &parent) const override
78     { return parent.isValid() ? 0 : m_colorSchemes.size(); }
79 
data(const QModelIndex & index,int role) const80     QVariant data(const QModelIndex &index, int role) const override
81     {
82         if (role == Qt::DisplayRole)
83             return m_colorSchemes.at(index.row()).name;
84 
85         return QVariant();
86     }
87 
removeColorScheme(int index)88     void removeColorScheme(int index)
89     {
90         beginRemoveRows(QModelIndex(), index, index);
91         m_colorSchemes.removeAt(index);
92         endRemoveRows();
93     }
94 
setColorSchemes(const QList<ColorSchemeEntry> & colorSchemes)95     void setColorSchemes(const QList<ColorSchemeEntry> &colorSchemes)
96     {
97         beginResetModel();
98         m_colorSchemes = colorSchemes;
99         endResetModel();
100     }
101 
colorSchemeAt(int index) const102     const ColorSchemeEntry &colorSchemeAt(int index) const
103     { return m_colorSchemes.at(index); }
104 
105 private:
106     QList<ColorSchemeEntry> m_colorSchemes;
107 };
108 
109 class FontSettingsPageWidget : public Core::IOptionsPageWidget
110 {
111     Q_DECLARE_TR_FUNCTIONS(TextEditor::FontSettingsPageWidget)
112 
113 public:
FontSettingsPageWidget(FontSettingsPage * q,const FormatDescriptions & fd,FontSettings * fontSettings)114     FontSettingsPageWidget(FontSettingsPage *q, const FormatDescriptions &fd, FontSettings *fontSettings)
115         : q(q),
116           m_value(*fontSettings),
117           m_descriptions(fd)
118     {
119         m_lastValue = m_value;
120 
121         m_ui.setupUi(this);
122         m_ui.colorSchemeGroupBox->setTitle(
123                     tr("Color Scheme for Theme \"%1\"")
124                     .arg(Utils::creatorTheme()->displayName()));
125         m_ui.schemeComboBox->setModel(&m_schemeListModel);
126 
127         m_ui.fontComboBox->setCurrentFont(m_value.family());
128 
129         m_ui.antialias->setChecked(m_value.antialias());
130         m_ui.zoomSpinBox->setValue(m_value.fontZoom());
131 
132         m_ui.schemeEdit->setFormatDescriptions(fd);
133         m_ui.schemeEdit->setBaseFont(m_value.font());
134         m_ui.schemeEdit->setColorScheme(m_value.colorScheme());
135 
136         auto sizeValidator = new QIntValidator(m_ui.sizeComboBox);
137         sizeValidator->setBottom(0);
138         m_ui.sizeComboBox->setValidator(sizeValidator);
139 
140         connect(m_ui.fontComboBox, &QFontComboBox::currentFontChanged,
141                 this, &FontSettingsPageWidget::fontSelected);
142         connect(m_ui.sizeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
143                 this, &FontSettingsPageWidget::fontSizeSelected);
144         connect(m_ui.zoomSpinBox, QOverload<int>::of(&QSpinBox::valueChanged),
145                 this, &FontSettingsPageWidget::fontZoomChanged);
146         connect(m_ui.antialias, &QCheckBox::toggled,
147                 this, &FontSettingsPageWidget::antialiasChanged);
148         connect(m_ui.schemeComboBox,
149                 QOverload<int>::of(&QComboBox::currentIndexChanged),
150                 this, &FontSettingsPageWidget::colorSchemeSelected);
151         connect(m_ui.copyButton, &QPushButton::clicked,
152                 this, &FontSettingsPageWidget::openCopyColorSchemeDialog);
153         connect(m_ui.schemeEdit, &ColorSchemeEdit::copyScheme,
154                 this, &FontSettingsPageWidget::openCopyColorSchemeDialog);
155         connect(m_ui.deleteButton, &QPushButton::clicked,
156                 this, &FontSettingsPageWidget::confirmDeleteColorScheme);
157 
158         updatePointSizes();
159         refreshColorSchemeList();
160     }
161 
162     void apply() final;
163     void finish() final;
164 
165     void saveSettings();
166     void fontSelected(const QFont &font);
167     void fontSizeSelected(int index);
168     void fontZoomChanged();
169     void antialiasChanged();
170     void colorSchemeSelected(int index);
171     void openCopyColorSchemeDialog();
172     void copyColorScheme(const QString &name);
173     void confirmDeleteColorScheme();
174     void deleteColorScheme();
175 
176     void maybeSaveColorScheme();
177     void updatePointSizes();
178     QList<int> pointSizesForSelectedFont() const;
179     void refreshColorSchemeList();
180 
181     FontSettingsPage *q;
182     Ui::FontSettingsPage m_ui;
183     bool m_refreshingSchemeList = false;
184     FontSettings &m_value;
185     FontSettings m_lastValue;
186     SchemeListModel m_schemeListModel;
187     FormatDescriptions m_descriptions;
188 };
189 
190 } // namespace Internal
191 
customStylesPath()192 static Utils::FilePath customStylesPath()
193 {
194     return Core::ICore::userResourcePath("styles");
195 }
196 
createColorSchemeFileName(const QString & pattern)197 static Utils::FilePath createColorSchemeFileName(const QString &pattern)
198 {
199     const Utils::FilePath stylesPath = customStylesPath();
200 
201     // Find an available file name
202     int i = 1;
203     Utils::FilePath filePath;
204     do {
205         filePath = stylesPath.pathAppended(pattern.arg((i == 1) ? QString() : QString::number(i)));
206         ++i;
207     } while (filePath.exists());
208 
209     // Create the base directory when it doesn't exist
210     if (!stylesPath.exists() && !stylesPath.createDir()) {
211         qWarning() << "Failed to create color scheme directory:" << stylesPath;
212         return {};
213     }
214 
215     return filePath;
216 }
217 
218 // ------- FormatDescription
FormatDescription(TextStyle id,const QString & displayName,const QString & tooltipText,const QColor & foreground,FormatDescription::ShowControls showControls)219 FormatDescription::FormatDescription(TextStyle id,
220                                      const QString &displayName,
221                                      const QString &tooltipText,
222                                      const QColor &foreground,
223                                      FormatDescription::ShowControls showControls)
224     : m_id(id),
225       m_displayName(displayName),
226       m_tooltipText(tooltipText),
227       m_showControls(showControls)
228 {
229     m_format.setForeground(foreground);
230     m_format.setBackground(defaultBackground(id));
231 }
232 
FormatDescription(TextStyle id,const QString & displayName,const QString & tooltipText,const Format & format,FormatDescription::ShowControls showControls)233 FormatDescription::FormatDescription(TextStyle id,
234                                      const QString &displayName,
235                                      const QString &tooltipText,
236                                      const Format &format,
237                                      FormatDescription::ShowControls showControls)
238     : m_id(id),
239       m_format(format),
240       m_displayName(displayName),
241       m_tooltipText(tooltipText),
242       m_showControls(showControls)
243 {
244 }
245 
FormatDescription(TextStyle id,const QString & displayName,const QString & tooltipText,const QColor & underlineColor,const QTextCharFormat::UnderlineStyle underlineStyle,FormatDescription::ShowControls showControls)246 FormatDescription::FormatDescription(TextStyle id,
247                                      const QString &displayName,
248                                      const QString &tooltipText,
249                                      const QColor &underlineColor,
250                                      const QTextCharFormat::UnderlineStyle underlineStyle,
251                                      FormatDescription::ShowControls showControls)
252     : m_id(id),
253       m_displayName(displayName),
254       m_tooltipText(tooltipText),
255       m_showControls(showControls)
256 {
257     m_format.setForeground(defaultForeground(id));
258     m_format.setBackground(defaultBackground(id));
259     m_format.setUnderlineColor(underlineColor);
260     m_format.setUnderlineStyle(underlineStyle);
261 }
262 
FormatDescription(TextStyle id,const QString & displayName,const QString & tooltipText,FormatDescription::ShowControls showControls)263 FormatDescription::FormatDescription(TextStyle id,
264                                      const QString &displayName,
265                                      const QString &tooltipText,
266                                      FormatDescription::ShowControls showControls)
267     : m_id(id),
268       m_displayName(displayName),
269       m_tooltipText(tooltipText),
270       m_showControls(showControls)
271 {
272     m_format.setForeground(defaultForeground(id));
273     m_format.setBackground(defaultBackground(id));
274 }
275 
defaultForeground(TextStyle id)276 QColor FormatDescription::defaultForeground(TextStyle id)
277 {
278     if (id == C_TEXT) {
279         return Qt::black;
280     } else if (id == C_LINE_NUMBER) {
281         const QPalette palette = Utils::Theme::initialPalette();
282         const QColor bg = palette.window().color();
283         if (bg.value() < 128)
284             return palette.windowText().color();
285         else
286             return palette.dark().color();
287     } else if (id == C_CURRENT_LINE_NUMBER) {
288         const QPalette palette = Utils::Theme::initialPalette();
289         const QColor bg = palette.window().color();
290         if (bg.value() < 128)
291             return palette.windowText().color();
292         else
293             return QColor();
294     } else if (id == C_PARENTHESES) {
295         return QColor(Qt::red);
296     } else if (id == C_AUTOCOMPLETE) {
297         return QColor(Qt::darkBlue);
298     } else if (id == C_SEARCH_RESULT_ALT1) {
299         return QColor(0x00, 0x00, 0x33);
300     } else if (id == C_SEARCH_RESULT_ALT2) {
301         return QColor(0x33, 0x00, 0x00);
302     }
303     return QColor();
304 }
305 
defaultBackground(TextStyle id)306 QColor FormatDescription::defaultBackground(TextStyle id)
307 {
308     if (id == C_TEXT) {
309         return Qt::white;
310     } else if (id == C_LINE_NUMBER) {
311         return Utils::Theme::initialPalette().window().color();
312     } else if (id == C_SEARCH_RESULT) {
313         return QColor(0xffef0b);
314     } else if (id == C_SEARCH_RESULT_ALT1) {
315         return QColor(0xb6, 0xcc, 0xff);
316     } else if (id == C_SEARCH_RESULT_ALT2) {
317         return QColor(0xff, 0xb6, 0xcc);
318     } else if (id == C_PARENTHESES) {
319         return QColor(0xb4, 0xee, 0xb4);
320     } else if (id == C_PARENTHESES_MISMATCH) {
321         return QColor(Qt::magenta);
322     } else if (id == C_AUTOCOMPLETE) {
323         return QColor(192, 192, 255);
324     } else if (id == C_CURRENT_LINE || id == C_SEARCH_SCOPE) {
325         const QPalette palette = Utils::Theme::initialPalette();
326         const QColor &fg = palette.color(QPalette::Highlight);
327         const QColor &bg = palette.color(QPalette::Base);
328 
329         qreal smallRatio;
330         qreal largeRatio;
331         if (id == C_CURRENT_LINE) {
332             smallRatio = .3;
333             largeRatio = .6;
334         } else {
335             smallRatio = .05;
336             largeRatio = .4;
337         }
338         const qreal ratio = ((palette.color(QPalette::Text).value() < 128)
339                              ^ (palette.color(QPalette::HighlightedText).value() < 128)) ? smallRatio : largeRatio;
340 
341         const QColor &col = QColor::fromRgbF(fg.redF() * ratio + bg.redF() * (1 - ratio),
342                                              fg.greenF() * ratio + bg.greenF() * (1 - ratio),
343                                              fg.blueF() * ratio + bg.blueF() * (1 - ratio));
344         return col;
345     } else if (id == C_SELECTION) {
346         return Utils::Theme::initialPalette().color(QPalette::Highlight);
347     } else if (id == C_OCCURRENCES) {
348         return QColor(180, 180, 180);
349     } else if (id == C_OCCURRENCES_RENAME) {
350         return QColor(255, 100, 100);
351     } else if (id == C_DISABLED_CODE) {
352         return QColor(239, 239, 239);
353     }
354     return QColor(); // invalid color
355 }
356 
showControl(FormatDescription::ShowControls showControl) const357 bool FormatDescription::showControl(FormatDescription::ShowControls showControl) const
358 {
359     return m_showControls & showControl;
360 }
361 
fontSelected(const QFont & font)362 void FontSettingsPageWidget::fontSelected(const QFont &font)
363 {
364     m_value.setFamily(font.family());
365     m_ui.schemeEdit->setBaseFont(font);
366     updatePointSizes();
367 }
368 
369 namespace Internal {
370 
updatePointSizes()371 void FontSettingsPageWidget::updatePointSizes()
372 {
373     // Update point sizes
374     const int oldSize = m_value.fontSize();
375     m_ui.sizeComboBox->clear();
376     const QList<int> sizeLst = pointSizesForSelectedFont();
377     int idx = -1;
378     int i = 0;
379     for (; i < sizeLst.count(); ++i) {
380         if (idx == -1 && sizeLst.at(i) >= oldSize) {
381             idx = i;
382             if (sizeLst.at(i) != oldSize)
383                 m_ui.sizeComboBox->addItem(QString::number(oldSize));
384         }
385         m_ui.sizeComboBox->addItem(QString::number(sizeLst.at(i)));
386     }
387     if (idx != -1)
388         m_ui.sizeComboBox->setCurrentIndex(idx);
389 }
390 
pointSizesForSelectedFont() const391 QList<int> FontSettingsPageWidget::pointSizesForSelectedFont() const
392 {
393     QFontDatabase db;
394     const QString familyName = m_ui.fontComboBox->currentFont().family();
395     QList<int> sizeLst = db.pointSizes(familyName);
396     if (!sizeLst.isEmpty())
397         return sizeLst;
398 
399     QStringList styles = db.styles(familyName);
400     if (!styles.isEmpty())
401         sizeLst = db.pointSizes(familyName, styles.first());
402     if (sizeLst.isEmpty())
403         sizeLst = QFontDatabase::standardSizes();
404 
405     return sizeLst;
406 }
407 
fontSizeSelected(int index)408 void FontSettingsPageWidget::fontSizeSelected(int index)
409 {
410     const QString sizeString = m_ui.sizeComboBox->itemText(index);
411     bool ok = true;
412     const int size = sizeString.toInt(&ok);
413     if (ok) {
414         m_value.setFontSize(size);
415         m_ui.schemeEdit->setBaseFont(m_value.font());
416     }
417 }
418 
fontZoomChanged()419 void FontSettingsPageWidget::fontZoomChanged()
420 {
421     m_value.setFontZoom(m_ui.zoomSpinBox->value());
422 }
423 
antialiasChanged()424 void FontSettingsPageWidget::antialiasChanged()
425 {
426     m_value.setAntialias(m_ui.antialias->isChecked());
427     m_ui.schemeEdit->setBaseFont(m_value.font());
428 }
429 
colorSchemeSelected(int index)430 void FontSettingsPageWidget::colorSchemeSelected(int index)
431 {
432     bool readOnly = true;
433     if (index != -1) {
434         // Check whether we're switching away from a changed color scheme
435         if (!m_refreshingSchemeList)
436             maybeSaveColorScheme();
437 
438         const ColorSchemeEntry &entry = m_schemeListModel.colorSchemeAt(index);
439         readOnly = entry.readOnly;
440         m_value.loadColorScheme(entry.fileName, m_descriptions);
441         m_ui.schemeEdit->setColorScheme(m_value.colorScheme());
442     }
443     m_ui.copyButton->setEnabled(index != -1);
444     m_ui.deleteButton->setEnabled(!readOnly);
445     m_ui.schemeEdit->setReadOnly(readOnly);
446 }
447 
openCopyColorSchemeDialog()448 void FontSettingsPageWidget::openCopyColorSchemeDialog()
449 {
450     QInputDialog *dialog = new QInputDialog(m_ui.copyButton->window());
451     dialog->setAttribute(Qt::WA_DeleteOnClose);
452     dialog->setInputMode(QInputDialog::TextInput);
453     dialog->setWindowTitle(tr("Copy Color Scheme"));
454     dialog->setLabelText(tr("Color scheme name:"));
455     dialog->setTextValue(tr("%1 (copy)").arg(m_value.colorScheme().displayName()));
456 
457     connect(dialog, &QInputDialog::textValueSelected, this, &FontSettingsPageWidget::copyColorScheme);
458     dialog->open();
459 }
460 
copyColorScheme(const QString & name)461 void FontSettingsPageWidget::copyColorScheme(const QString &name)
462 {
463     int index = m_ui.schemeComboBox->currentIndex();
464     if (index == -1)
465         return;
466 
467     const ColorSchemeEntry &entry = m_schemeListModel.colorSchemeAt(index);
468 
469     QString baseFileName = QFileInfo(entry.fileName).completeBaseName();
470     baseFileName += QLatin1String("_copy%1.xml");
471     Utils::FilePath fileName = createColorSchemeFileName(baseFileName);
472 
473     if (!fileName.isEmpty()) {
474         // Ask about saving any existing modifactions
475         maybeSaveColorScheme();
476 
477         // Make sure we're copying the current version
478         m_value.setColorScheme(m_ui.schemeEdit->colorScheme());
479 
480         ColorScheme scheme = m_value.colorScheme();
481         scheme.setDisplayName(name);
482         if (scheme.save(fileName.path(), Core::ICore::dialogParent()))
483             m_value.setColorSchemeFileName(fileName.path());
484 
485         refreshColorSchemeList();
486     }
487 }
488 
confirmDeleteColorScheme()489 void FontSettingsPageWidget::confirmDeleteColorScheme()
490 {
491     const int index = m_ui.schemeComboBox->currentIndex();
492     if (index == -1)
493         return;
494 
495     const ColorSchemeEntry &entry = m_schemeListModel.colorSchemeAt(index);
496     if (entry.readOnly)
497         return;
498 
499     QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
500                                               tr("Delete Color Scheme"),
501                                               tr("Are you sure you want to delete this color scheme permanently?"),
502                                               QMessageBox::Discard | QMessageBox::Cancel,
503                                               m_ui.deleteButton->window());
504 
505     // Change the text and role of the discard button
506     auto deleteButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
507     deleteButton->setText(tr("Delete"));
508     messageBox->addButton(deleteButton, QMessageBox::AcceptRole);
509     messageBox->setDefaultButton(deleteButton);
510 
511     connect(messageBox, &QDialog::accepted, this, &FontSettingsPageWidget::deleteColorScheme);
512     messageBox->setAttribute(Qt::WA_DeleteOnClose);
513     messageBox->open();
514 }
515 
deleteColorScheme()516 void FontSettingsPageWidget::deleteColorScheme()
517 {
518     const int index = m_ui.schemeComboBox->currentIndex();
519     QTC_ASSERT(index != -1, return);
520 
521     const ColorSchemeEntry &entry = m_schemeListModel.colorSchemeAt(index);
522     QTC_ASSERT(!entry.readOnly, return);
523 
524     if (QFile::remove(entry.fileName))
525         m_schemeListModel.removeColorScheme(index);
526 }
527 
maybeSaveColorScheme()528 void FontSettingsPageWidget::maybeSaveColorScheme()
529 {
530     if (m_value.colorScheme() == m_ui.schemeEdit->colorScheme())
531         return;
532 
533     QMessageBox messageBox(QMessageBox::Warning,
534                                               tr("Color Scheme Changed"),
535                                               tr("The color scheme \"%1\" was modified, do you want to save the changes?")
536                                                   .arg(m_ui.schemeEdit->colorScheme().displayName()),
537                                               QMessageBox::Discard | QMessageBox::Save,
538                                               m_ui.schemeComboBox->window());
539 
540     // Change the text of the discard button
541     auto discardButton = static_cast<QPushButton*>(messageBox.button(QMessageBox::Discard));
542     discardButton->setText(tr("Discard"));
543     messageBox.addButton(discardButton, QMessageBox::DestructiveRole);
544     messageBox.setDefaultButton(QMessageBox::Save);
545 
546     if (messageBox.exec() == QMessageBox::Save) {
547         const ColorScheme &scheme = m_ui.schemeEdit->colorScheme();
548         scheme.save(m_value.colorSchemeFileName(), Core::ICore::dialogParent());
549     }
550 }
551 
refreshColorSchemeList()552 void FontSettingsPageWidget::refreshColorSchemeList()
553 {
554     QList<ColorSchemeEntry> colorSchemes;
555 
556     QDir styleDir(Core::ICore::resourcePath("styles").toDir());
557     styleDir.setNameFilters(QStringList() << QLatin1String("*.xml"));
558     styleDir.setFilter(QDir::Files);
559 
560     int selected = 0;
561 
562     QStringList schemeList = styleDir.entryList();
563     QString defaultScheme = Utils::FilePath::fromString(FontSettings::defaultSchemeFileName()).fileName();
564     if (schemeList.removeAll(defaultScheme))
565         schemeList.prepend(defaultScheme);
566     foreach (const QString &file, schemeList) {
567         const QString fileName = styleDir.absoluteFilePath(file);
568         if (m_value.colorSchemeFileName() == fileName)
569             selected = colorSchemes.size();
570         colorSchemes.append(ColorSchemeEntry(fileName, true));
571     }
572 
573     if (colorSchemes.isEmpty())
574         qWarning() << "Warning: no color schemes found in path:" << styleDir.path();
575 
576     styleDir.setPath(customStylesPath().path());
577 
578     foreach (const QString &file, styleDir.entryList()) {
579         const QString fileName = styleDir.absoluteFilePath(file);
580         if (m_value.colorSchemeFileName() == fileName)
581             selected = colorSchemes.size();
582         colorSchemes.append(ColorSchemeEntry(fileName, false));
583     }
584 
585     m_refreshingSchemeList = true;
586     m_schemeListModel.setColorSchemes(colorSchemes);
587     m_ui.schemeComboBox->setCurrentIndex(selected);
588     m_refreshingSchemeList = false;
589 }
590 
apply()591 void FontSettingsPageWidget::apply()
592 {
593     if (m_value.colorScheme() != m_ui.schemeEdit->colorScheme()) {
594         // Update the scheme and save it under the name it already has
595         m_value.setColorScheme(m_ui.schemeEdit->colorScheme());
596         const ColorScheme &scheme = m_value.colorScheme();
597         scheme.save(m_value.colorSchemeFileName(), Core::ICore::dialogParent());
598     }
599 
600     bool ok;
601     int fontSize = m_ui.sizeComboBox->currentText().toInt(&ok);
602     if (ok && m_value.fontSize() != fontSize) {
603         m_value.setFontSize(fontSize);
604         m_ui.schemeEdit->setBaseFont(m_value.font());
605     }
606 
607     int index = m_ui.schemeComboBox->currentIndex();
608     if (index != -1) {
609         const ColorSchemeEntry &entry = m_schemeListModel.colorSchemeAt(index);
610         if (entry.fileName != m_value.colorSchemeFileName())
611             m_value.loadColorScheme(entry.fileName, m_descriptions);
612     }
613 
614     saveSettings();
615 }
616 
saveSettings()617 void FontSettingsPageWidget::saveSettings()
618 {
619     m_lastValue = m_value;
620     m_value.toSettings(Core::ICore::settings());
621     emit TextEditorSettings::instance()->fontSettingsChanged(m_value);
622 }
623 
finish()624 void FontSettingsPageWidget::finish()
625 {
626     // If changes were applied, these are equal. Otherwise restores last value.
627     m_value = m_lastValue;
628 }
629 
630 } // namespace Internal
631 
632 // FontSettingsPage
633 
FontSettingsPage(FontSettings * fontSettings,const FormatDescriptions & fd)634 FontSettingsPage::FontSettingsPage(FontSettings *fontSettings, const FormatDescriptions &fd)
635 {
636     QSettings *settings = Core::ICore::settings();
637     if (settings)
638        fontSettings->fromSettings(fd, settings);
639 
640     if (fontSettings->colorSchemeFileName().isEmpty())
641        fontSettings->loadColorScheme(FontSettings::defaultSchemeFileName(), fd);
642 
643     setId(Constants::TEXT_EDITOR_FONT_SETTINGS);
644     setDisplayName(FontSettingsPageWidget::tr("Font && Colors"));
645     setCategory(TextEditor::Constants::TEXT_EDITOR_SETTINGS_CATEGORY);
646     setDisplayCategory(QCoreApplication::translate("TextEditor", "Text Editor"));
647     setCategoryIconPath(TextEditor::Constants::TEXT_EDITOR_SETTINGS_CATEGORY_ICON_PATH);
648     setWidgetCreator([this, fontSettings, fd] { return new FontSettingsPageWidget(this, fd, fontSettings); });
649 }
650 
setFontZoom(int zoom)651 void FontSettingsPage::setFontZoom(int zoom)
652 {
653     if (m_widget)
654         static_cast<FontSettingsPageWidget *>(m_widget.data())->m_ui.zoomSpinBox->setValue(zoom);
655 }
656 
657 } // TextEditor
658