From 065689478cdded03c94655822cbfb38bf311cc61 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= <thorbjorn.lindeijer@nokia.com>
Date: Tue, 7 Jul 2009 16:07:40 +0200
Subject: [PATCH] Introduced a ColorSchemeReader class for reading color scheme
 files

---
 share/qtcreator/styles/default.xml          |  27 +++++
 src/plugins/texteditor/colorscheme.cpp      | 111 +++++++++++++++++++-
 src/plugins/texteditor/fontsettings.cpp     |  64 ++++++++++-
 src/plugins/texteditor/fontsettings.h       |  31 ++----
 src/plugins/texteditor/fontsettingspage.cpp |  43 ++++++++
 src/plugins/texteditor/fontsettingspage.h   |   4 +
 6 files changed, 252 insertions(+), 28 deletions(-)
 create mode 100644 share/qtcreator/styles/default.xml

diff --git a/share/qtcreator/styles/default.xml b/share/qtcreator/styles/default.xml
new file mode 100644
index 00000000000..3e441fbce14
--- /dev/null
+++ b/share/qtcreator/styles/default.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<style-scheme version="1.0">
+  <style name="AddedLine" foreground="#00aa00"/>
+  <style name="Comment" foreground="#008000"/>
+  <style name="CurrentLine" background="#fef2da"/>
+  <style name="CurrentLineNumber" foreground="#808080" bold="true"/>
+  <style name="DiffFile" foreground="#000080"/>
+  <style name="DiffLocation" foreground="#0000ff"/>
+  <style name="DisabledCode" foreground="#a0a0a4"/>
+  <style name="Doxygen.Comment" foreground="#000080"/>
+  <style name="Doxygen.Tag" foreground="#0000ff"/>
+  <style name="Keyword" foreground="#808000"/>
+  <style name="Label" foreground="#800000"/>
+  <style name="LineNumber" foreground="#c7c4c1" background="#efebe7"/>
+  <style name="Link" foreground="#0000ff"/>
+  <style name="Number" foreground="#000080"/>
+  <style name="Operator" foreground="#000000"/>
+  <style name="Parentheses" foreground="#ff0000" background="#b4eeb4"/>
+  <style name="Preprocessor" foreground="#000080"/>
+  <style name="RemovedLine" foreground="#ff0000"/>
+  <style name="SearchResult" background="#ffef0b"/>
+  <style name="SearchScope" background="#fdedce"/>
+  <style name="Selection" background="#fad184"/>
+  <style name="String" foreground="#008000"/>
+  <style name="Text" foreground="#000000" background="#ffffff"/>
+  <style name="Type" foreground="#800080"/>
+</style-scheme>
diff --git a/src/plugins/texteditor/colorscheme.cpp b/src/plugins/texteditor/colorscheme.cpp
index 364342904ed..c6299df216d 100644
--- a/src/plugins/texteditor/colorscheme.cpp
+++ b/src/plugins/texteditor/colorscheme.cpp
@@ -29,6 +29,8 @@
 
 #include "colorscheme.h"
 
+#include "texteditorconstants.h"
+
 #include <QtCore/QFile>
 #include <QtXml/QXmlStreamWriter>
 
@@ -161,12 +163,15 @@ bool ColorScheme::save(const QString &fileName)
     w.writeStartElement(QLatin1String("style-scheme"));
     w.writeAttribute(QLatin1String("version"), QLatin1String("1.0"));
 
+    Format textFormat = formatFor(QLatin1String(Constants::C_TEXT));
+
     QMapIterator<QString, Format> i(m_formats);
     while (i.hasNext()) {
         const Format &format = i.next().value();
         w.writeStartElement(QLatin1String("style"));
         w.writeAttribute(QLatin1String("name"), i.key());
-        w.writeAttribute(QLatin1String("foreground"), format.foreground().name().toLower());
+        if (i.key() == QLatin1String(Constants::C_TEXT) || format.foreground() != textFormat.foreground())
+            w.writeAttribute(QLatin1String("foreground"), format.foreground().name().toLower());
         if (format.background().isValid())
             w.writeAttribute(QLatin1String("background"), format.background().name().toLower());
         if (format.bold())
@@ -182,8 +187,108 @@ bool ColorScheme::save(const QString &fileName)
     return true;
 }
 
+namespace {
+
+class ColorSchemeReader : public QXmlStreamReader
+{
+public:
+    ColorSchemeReader(ColorScheme *scheme) :
+        m_scheme(scheme)
+    {}
+
+    bool read(const QString &fileName);
+
+private:
+    void readUnknownElement();
+    void readStyleScheme();
+    void readStyle();
+
+    ColorScheme *m_scheme;
+};
+
+bool ColorSchemeReader::read(const QString &fileName)
+{
+    m_scheme->clear();
+
+    QFile file(fileName);
+    if (!file.open(QFile::ReadOnly | QFile::Text))
+        return false;
+
+    setDevice(&file);
+
+    while (readNext() != Invalid) {
+        if (isStartElement()) {
+            if (name() == QLatin1String("style-scheme"))
+                readStyleScheme();
+            else
+                raiseError(QObject::tr("Not a color scheme file."));
+        }
+    }
+
+    return true;
+}
+
+void ColorSchemeReader::readUnknownElement()
+{
+    Q_ASSERT(isStartElement());
+
+    while (!atEnd()) {
+        readNext();
+        if (isEndElement())
+            break;
+        else if (isStartElement())
+            readUnknownElement();
+    }
+}
+
+void ColorSchemeReader::readStyleScheme()
+{
+    Q_ASSERT(isStartElement() && name() == QLatin1String("style-scheme"));
+
+    while (readNext() != Invalid) {
+        if (isEndElement()) {
+            break;
+        } else if (isStartElement()) {
+            if (name() == QLatin1String("style"))
+                readStyle();
+            else
+                readUnknownElement();
+        }
+    }
+}
+
+void ColorSchemeReader::readStyle()
+{
+    Q_ASSERT(isStartElement() && name() == QLatin1String("style"));
+
+    const QXmlStreamAttributes attr = attributes();
+    QString name = attr.value(QLatin1String("name")).toString();
+    QString foreground = attr.value(QLatin1String("foreground")).toString();
+    QString background = attr.value(QLatin1String("background")).toString();
+    bool bold = attr.value(QLatin1String("bold")) == QLatin1String(trueString);
+    bool italic = attr.value(QLatin1String("italic")) == QLatin1String(trueString);
+
+    Format format;
+    format.setForeground(stringToColor(foreground));
+    format.setBackground(stringToColor(background));
+    format.setBold(bold);
+    format.setItalic(italic);
+
+    m_scheme->setFormatFor(name, format);
+
+    while (readNext() != Invalid) {
+        if (isEndElement())
+            break;
+        else if (isStartElement())
+            readUnknownElement();
+    }
+}
+
+} // anonymous namespace
+
+
 bool ColorScheme::load(const QString &fileName)
 {
-    Q_UNUSED(fileName)
-    return false;
+    ColorSchemeReader reader(this);
+    return reader.read(fileName) && !reader.hasError();
 }
diff --git a/src/plugins/texteditor/fontsettings.cpp b/src/plugins/texteditor/fontsettings.cpp
index cd0fd2586c9..23a8f52dede 100644
--- a/src/plugins/texteditor/fontsettings.cpp
+++ b/src/plugins/texteditor/fontsettings.cpp
@@ -31,6 +31,7 @@
 #include "fontsettingspage.h"
 
 #include <utils/qtcassert.h>
+#include <coreplugin/icore.h>
 
 #include <QtCore/QSettings>
 #include <QtGui/QTextCharFormat>
@@ -38,6 +39,7 @@
 static const char *fontFamilyKey = "FontFamily";
 static const char *fontSizeKey = "FontSize";
 static const char *antialiasKey = "FontAntialias";
+static const char *schemeFileNameKey = "ColorScheme";
 
 namespace {
 static const bool DEFAULT_ANTIALIAS = true;
@@ -88,6 +90,9 @@ void FontSettings::toSettings(const QString &category,
     if (m_antialias != DEFAULT_ANTIALIAS || s->contains(QLatin1String(antialiasKey)))
         s->setValue(QLatin1String(antialiasKey), m_antialias);
 
+    if (m_schemeFileName != defaultSchemeFileName() || s->contains(QLatin1String(schemeFileNameKey)))
+        s->setValue(QLatin1String(schemeFileNameKey), m_schemeFileName);
+#if 0
     const Format defaultFormat;
 
     foreach (const FormatDescription &desc, descriptions) {
@@ -98,6 +103,7 @@ void FontSettings::toSettings(const QString &category,
                 s->setValue(name, f.toString());
         }
     }
+#endif
     s->endGroup();
 }
 
@@ -116,7 +122,10 @@ bool FontSettings::fromSettings(const QString &category,
     m_family = s->value(group + QLatin1String(fontFamilyKey), defaultFixedFontFamily()).toString();
     m_fontSize = s->value(group + QLatin1String(fontSizeKey), m_fontSize).toInt();
     m_antialias = s->value(group + QLatin1String(antialiasKey), DEFAULT_ANTIALIAS).toBool();
+    m_schemeFileName = s->value(group + QLatin1String(schemeFileNameKey), defaultSchemeFileName()).toString();
 
+    m_scheme.load(m_schemeFileName);
+#if 0
     foreach (const FormatDescription &desc, descriptions) {
         const QString name = desc.name();
         const QString fmt = s->value(group + name, QString()).toString();
@@ -131,17 +140,22 @@ bool FontSettings::fromSettings(const QString &category,
         }
         m_scheme.setFormatFor(name, format);
     }
+#endif
     return true;
 }
 
 bool FontSettings::equals(const FontSettings &f) const
 {
     return m_family == f.m_family
+            && m_schemeFileName == f.m_schemeFileName
             && m_fontSize == f.m_fontSize
             && m_antialias == f.m_antialias
             && m_scheme == f.m_scheme;
 }
 
+/**
+ * Returns the QTextCharFormat of the given format category.
+ */
 QTextCharFormat FontSettings::toTextCharFormat(const QString &category) const
 {
     const Format &f = m_scheme.formatFor(category);
@@ -164,6 +178,10 @@ QTextCharFormat FontSettings::toTextCharFormat(const QString &category) const
     return tf;
 }
 
+/**
+ * Returns the list of QTextCharFormats that corresponds to the list of
+ * requested format categories.
+ */
 QVector<QTextCharFormat> FontSettings::toTextCharFormats(const QVector<QString> &categories) const
 {
     QVector<QTextCharFormat> rc;
@@ -174,6 +192,9 @@ QVector<QTextCharFormat> FontSettings::toTextCharFormats(const QVector<QString>
     return rc;
 }
 
+/**
+ * Returns the configured font family.
+ */
 QString FontSettings::family() const
 {
     return m_family;
@@ -184,6 +205,9 @@ void FontSettings::setFamily(const QString &family)
     m_family = family;
 }
 
+/**
+ * Returns the configured font size.
+ */
 int FontSettings::fontSize() const
 {
     return m_fontSize;
@@ -194,6 +218,9 @@ void FontSettings::setFontSize(int size)
     m_fontSize = size;
 }
 
+/**
+ * Returns the configured antialiasing behavior.
+ */
 bool FontSettings::antialias() const
 {
     return m_antialias;
@@ -204,12 +231,40 @@ void FontSettings::setAntialias(bool antialias)
     m_antialias = antialias;
 }
 
-
+/**
+ * Returns the format for the given font category.
+ */
 Format &FontSettings::formatFor(const QString &category)
 {
     return m_scheme.formatFor(category);
 }
 
+/**
+ * Returns the file name of the currently selected color scheme.
+ */
+QString FontSettings::colorSchemeFileName() const
+{
+    return m_schemeFileName;
+}
+
+void FontSettings::setColorSchemeFileName(const QString &fileName)
+{
+    m_schemeFileName = fileName;
+}
+
+/**
+ * Returns the currently active color scheme.
+ */
+ColorScheme FontSettings::colorScheme() const
+{
+    return m_scheme;
+}
+
+void FontSettings::setColorScheme(const ColorScheme &scheme)
+{
+    m_scheme = scheme;
+}
+
 QString FontSettings::defaultFixedFontFamily()
 {
     static QString rc;
@@ -226,4 +281,11 @@ int FontSettings::defaultFontSize()
     return DEFAULT_FONT_SIZE;
 }
 
+QString FontSettings::defaultSchemeFileName()
+{
+    QString fileName = Core::ICore::instance()->resourcePath();
+    fileName += QLatin1String("/styles/default.xml");
+    return fileName;
+}
+
 } // namespace TextEditor
diff --git a/src/plugins/texteditor/fontsettings.h b/src/plugins/texteditor/fontsettings.h
index c74524b618c..918f075d394 100644
--- a/src/plugins/texteditor/fontsettings.h
+++ b/src/plugins/texteditor/fontsettings.h
@@ -69,45 +69,25 @@ public:
                       const FormatDescriptions &descriptions,
                       const QSettings *s);
 
-    /**
-     * Returns the list of QTextCharFormats that corresponds to the list of
-     * requested format categories.
-     */
     QVector<QTextCharFormat> toTextCharFormats(const QVector<QString> &categories) const;
-
-    /**
-     * Returns the QTextCharFormat of the given format category.
-     */
     QTextCharFormat toTextCharFormat(const QString &category) const;
 
-    /**
-     * Returns the configured font family.
-     */
     QString family() const;
     void setFamily(const QString &family);
 
-    /**
-     * Returns the configured font size.
-     */
     int fontSize() const;
     void setFontSize(int size);
 
-    /**
-     * Returns the configured antialiasing behavior.
-     */
     bool antialias() const;
     void setAntialias(bool antialias);
 
-    /**
-     * Returns the format for the given font category.
-     */
     Format &formatFor(const QString &category);
 
-    ColorScheme colorScheme() const
-    { return m_scheme; }
+    QString colorSchemeFileName() const;
+    void setColorSchemeFileName(const QString &fileName);
 
-    void setColorScheme(const ColorScheme &scheme)
-    { m_scheme = scheme; }
+    ColorScheme colorScheme() const;
+    void setColorScheme(const ColorScheme &scheme);
 
     bool equals(const FontSettings &f) const;
 
@@ -115,7 +95,10 @@ public:
     static int defaultFontSize();
 
 private:
+    static QString defaultSchemeFileName();
+
     QString m_family;
+    QString m_schemeFileName;
     int m_fontSize;
     bool m_antialias;
     ColorScheme m_scheme;
diff --git a/src/plugins/texteditor/fontsettingspage.cpp b/src/plugins/texteditor/fontsettingspage.cpp
index 6d5a5f4e2f7..b411101f5c2 100644
--- a/src/plugins/texteditor/fontsettingspage.cpp
+++ b/src/plugins/texteditor/fontsettingspage.cpp
@@ -41,6 +41,7 @@
 #include <QtCore/QTimer>
 #include <QtGui/QCheckBox>
 #include <QtGui/QComboBox>
+#include <QtGui/QFileDialog>
 #include <QtGui/QFontDatabase>
 #include <QtGui/QListWidget>
 #include <QtGui/QPalette>
@@ -222,6 +223,7 @@ QWidget *FontSettingsPage::createPage(QWidget *parent)
 
     d_ptr->ui.schemeListWidget->addItem(tr("Default"));
     d_ptr->ui.schemeListWidget->setCurrentIndex(d_ptr->ui.schemeListWidget->model()->index(0, 0));
+    d_ptr->ui.exportButton->setEnabled(true);
     d_ptr->ui.editButton->setEnabled(true);
 
     QFontDatabase db;
@@ -233,9 +235,11 @@ QWidget *FontSettingsPage::createPage(QWidget *parent)
     d_ptr->ui.antialias->setChecked(d_ptr->m_value.antialias());
 
     connect(d_ptr->ui.familyComboBox, SIGNAL(activated(int)), this, SLOT(updatePointSizes()));
+    connect(d_ptr->ui.exportButton, SIGNAL(clicked()), this, SLOT(exportColorScheme()));
     connect(d_ptr->ui.editButton, SIGNAL(clicked()), this, SLOT(editColorScheme()));
 
     updatePointSizes();
+    refreshColorSchemeList();
     d_ptr->m_lastValue = d_ptr->m_value;
     return w;
 }
@@ -264,6 +268,28 @@ void FontSettingsPage::updatePointSizes()
         d_ptr->ui.sizeComboBox->setCurrentIndex(idx);
 }
 
+void FontSettingsPage::importColorScheme()
+{
+    QString fn = QFileDialog::getOpenFileName(d_ptr->ui.importButton->window(),
+                                              tr("Import Color Scheme"),
+                                              QString(),
+                                              tr("Color Schemes (*.xml)"));
+    if (fn.isEmpty())
+        return;
+
+    // Open color scheme and save it in the schemes directory
+}
+
+void FontSettingsPage::exportColorScheme()
+{
+    QString fn = QFileDialog::getSaveFileName(d_ptr->ui.exportButton->window(),
+                                              tr("Export Color Scheme"),
+                                              QString(),
+                                              tr("Color Schemes (*.xml)"));
+    if (!fn.isEmpty())
+        d_ptr->m_value.colorScheme().save(fn);
+}
+
 void FontSettingsPage::editColorScheme()
 {
     d_ptr->m_value.setFamily(d_ptr->ui.familyComboBox->currentText());
@@ -283,6 +309,23 @@ void FontSettingsPage::editColorScheme()
         d_ptr->m_value.setColorScheme(dialog.colorScheme());
 }
 
+void FontSettingsPage::refreshColorSchemeList()
+{
+    d_ptr->ui.schemeListWidget->clear();
+
+    QString resourcePath = Core::ICore::instance()->resourcePath();
+    QDir styleDir(resourcePath + QLatin1String("/styles"));
+    styleDir.setNameFilters(QStringList() << QLatin1String("*.xml"));
+    styleDir.setFilter(QDir::Files);
+
+    foreach (const QString &file, styleDir.entryList()) {
+        // TODO: Read the name of the style
+        QListWidgetItem *item = new QListWidgetItem(file);
+        item->setData(Qt::UserRole, styleDir.absoluteFilePath(file));
+        d_ptr->ui.schemeListWidget->addItem(item);
+    }
+}
+
 void FontSettingsPage::delayedChange()
 {
     emit changed(d_ptr->m_value);
diff --git a/src/plugins/texteditor/fontsettingspage.h b/src/plugins/texteditor/fontsettingspage.h
index 17e00a0f2d4..bdda4e7fbfc 100644
--- a/src/plugins/texteditor/fontsettingspage.h
+++ b/src/plugins/texteditor/fontsettingspage.h
@@ -110,9 +110,13 @@ signals:
 private slots:
     void delayedChange();
     void updatePointSizes();
+    void importColorScheme();
+    void exportColorScheme();
     void editColorScheme();
 
 private:
+    void refreshColorSchemeList();
+
     Internal::FontSettingsPagePrivate *d_ptr;
 };
 
-- 
GitLab