/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 *
 * Date        : 2004-08-02
 * Description : theme engine methods 
 * 
 * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
 * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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.
 * 
 * ============================================================ */

// TQt includes.

#include <tqdict.h>
#include <tqptrlist.h>
#include <tqfileinfo.h>
#include <tqfile.h>
#include <tqapplication.h>
#include <tqpalette.h>
#include <tqtimer.h>
#include <tqtextstream.h>

// KDE includes.

#include <tdeglobal.h>
#include <tdelocale.h>
#include <kstandarddirs.h>
#include <kuser.h>
#include <tdeapplication.h>
#include <tdeglobalsettings.h>

// Local includes.

#include "ddebug.h"
#include "theme.h"
#include "texture.h"
#include "themeengine.h"
#include "themeengine.moc"

namespace Digikam
{

class ThemeEnginePriv
{
public:

    ThemeEnginePriv()
    {
       defaultTheme      = 0;
       currTheme         = 0;
       themeInitiallySet = false;
    }

    TQPalette         defaultPalette;

    TQPtrList<Theme>  themeList;
    TQDict<Theme>     themeDict;

    Theme           *currTheme;
    Theme           *defaultTheme;
    bool             themeInitiallySet;
};

ThemeEngine* ThemeEngine::m_instance = 0;

ThemeEngine* ThemeEngine::instance()
{
    if (!m_instance)
    { 
        new ThemeEngine();
    }
    return m_instance;
}

ThemeEngine::ThemeEngine()
{
    m_instance = this;
    TDEGlobal::dirs()->addResourceType("themes",
                                     TDEGlobal::dirs()->kde_default("data")
                                     + "digikam/themes");

    d = new ThemeEnginePriv;

    d->themeList.setAutoDelete(false);
    d->themeDict.setAutoDelete(false);
    d->defaultTheme = new Theme(i18n("Default"), TQString());
    d->themeList.append(d->defaultTheme);
    d->themeDict.insert(i18n("Default"), d->defaultTheme);
    d->currTheme = d->defaultTheme;

    buildDefaultTheme();
}

ThemeEngine::~ThemeEngine()
{
    d->themeList.setAutoDelete(true);
    d->themeList.clear();
    delete d;
    m_instance = 0;
}

TQColor ThemeEngine::baseColor() const
{
    return d->currTheme->baseColor;
}

TQColor ThemeEngine::thumbSelColor() const
{
    return d->currTheme->thumbSelColor;
}

TQColor ThemeEngine::thumbRegColor() const
{
    return d->currTheme->thumbRegColor;
}

TQColor ThemeEngine::textRegColor() const
{
    return d->currTheme->textRegColor;
}

TQColor ThemeEngine::textSelColor() const
{
    return d->currTheme->textSelColor;
}

TQColor ThemeEngine::textSpecialRegColor() const
{
    return d->currTheme->textSpecialRegColor;
}

TQColor ThemeEngine::textSpecialSelColor() const
{
    return d->currTheme->textSpecialSelColor;
}

TQPixmap ThemeEngine::bannerPixmap(int w, int h)
{
    Texture tex(w, h, d->currTheme->bannerColor, d->currTheme->bannerColorTo,
                d->currTheme->bannerBevel, d->currTheme->bannerGrad,
                d->currTheme->bannerBorder, d->currTheme->bannerBorderColor);
    return tex.renderPixmap();
}

TQPixmap ThemeEngine::thumbRegPixmap(int w, int h)
{
    Texture tex(w, h, d->currTheme->thumbRegColor, d->currTheme->thumbRegColorTo,
                d->currTheme->thumbRegBevel, d->currTheme->thumbRegGrad,
                d->currTheme->thumbRegBorder, d->currTheme->thumbRegBorderColor);
    return tex.renderPixmap();
}

TQPixmap ThemeEngine::thumbSelPixmap(int w, int h)
{
    Texture tex(w, h, d->currTheme->thumbSelColor, d->currTheme->thumbSelColorTo,
                d->currTheme->thumbSelBevel, d->currTheme->thumbSelGrad,
                d->currTheme->thumbSelBorder, d->currTheme->thumbSelBorderColor);
    return tex.renderPixmap();
}

TQPixmap ThemeEngine::listRegPixmap(int w, int h)
{
    Texture tex(w, h, d->currTheme->listRegColor, d->currTheme->listRegColorTo,
                d->currTheme->listRegBevel, d->currTheme->listRegGrad,
                d->currTheme->listRegBorder, d->currTheme->listRegBorderColor);
    return tex.renderPixmap();
}

TQPixmap ThemeEngine::listSelPixmap(int w, int h)
{
    Texture tex(w, h, d->currTheme->listSelColor, d->currTheme->listSelColorTo,
                d->currTheme->listSelBevel, d->currTheme->listSelGrad,
                d->currTheme->listSelBorder, d->currTheme->listSelBorderColor);
    return tex.renderPixmap();
}

void ThemeEngine::scanThemes()
{
    d->themeList.remove(d->defaultTheme);
    d->themeList.setAutoDelete(true);
    d->themeList.clear();
    d->themeDict.clear();
    d->currTheme = 0;

    TQStringList themes = TDEGlobal::dirs()->findAllResources( "themes", TQString(), false, true );

    for (TQStringList::iterator it=themes.begin(); it != themes.end();
         ++it)
    {
        TQFileInfo fi(*it);
        Theme* theme = new Theme(fi.fileName(), *it);
        d->themeList.append(theme);
        d->themeDict.insert(fi.fileName(), theme);
    }

    d->themeList.append(d->defaultTheme);
    d->themeDict.insert(i18n("Default"), d->defaultTheme);
    d->currTheme = d->defaultTheme;
}

TQStringList ThemeEngine::themeNames() const
{
    TQStringList names;
    for (Theme *t = d->themeList.first(); t; t = d->themeList.next())
    {
        names << t->name;
    }
    names.sort();
    return names;
}

void ThemeEngine::slotChangeTheme(const TQString& name)
{
    setCurrentTheme(name);
}

void ThemeEngine::setCurrentTheme(const TQString& name)
{
    Theme* theme = d->themeDict.find(name);
    if (!theme)
    {
        d->currTheme = d->defaultTheme;
        return;
    }

    if (d->currTheme == theme && d->themeInitiallySet)
        return;

    d->currTheme = theme;
    loadTheme();

    // this is only to ensure that even if the chosen theme is the default theme,
    // the signalThemeChanged is emitted when themes are loaded in DigikamApp
    d->themeInitiallySet = true;

    changePalette();

    TQTimer::singleShot(0, this, TQ_SIGNAL(signalThemeChanged()));
}

void ThemeEngine::setCurrentTheme(const Theme& theme, const TQString& name, bool loadFromDisk)
{
    Theme* t = d->themeDict.find(name);
    if (t)
    {
        d->themeDict.remove(name);
        d->themeList.remove(t);
    }

    t = new Theme(theme);
    t->filePath = theme.filePath;
    d->themeDict.insert(name, t);
    d->themeList.append(t);

    d->currTheme = t;
    if (loadFromDisk)
        loadTheme();

    changePalette();

    TQTimer::singleShot(0, this, TQ_SIGNAL(signalThemeChanged()));
}

void ThemeEngine::changePalette()
{
    // Make palette for all widgets.
    TQPalette plt;

    if (d->currTheme == d->defaultTheme)
        plt = d->defaultPalette;
    else
    {
        plt = kapp->palette();
        int h, s, v;
        const TQColor fg(ThemeEngine::instance()->textRegColor());
        const TQColor bg(ThemeEngine::instance()->baseColor());
        TQColorGroup cg(plt.active());

    /*    bg.hsv(&h, &s, &v);
        v += (v < 128) ? +50 : -50;
        v &= 255; //ensures 0 <= v < 256
        d->currTheme->altBase = TQColor(h, s, v, TQColor::Hsv);
    */
        fg.hsv(&h, &s, &v);
        v += (v < 128) ? +150 : -150;
        v &= 255; //ensures 0 <= v < 256
        const TQColor highlight(h, s, v, TQColor::Hsv);

        cg.setColor(TQColorGroup::Base,            bg);
        cg.setColor(TQColorGroup::Background,      bg.dark(115));
        cg.setColor(TQColorGroup::Foreground,      ThemeEngine::instance()->textRegColor());
        cg.setColor(TQColorGroup::Highlight,       highlight);
        cg.setColor(TQColorGroup::HighlightedText, ThemeEngine::instance()->textSelColor());
        cg.setColor(TQColorGroup::Dark,            TQt::darkGray);

        cg.setColor(TQColorGroup::Button,          bg);
        cg.setColor(TQColorGroup::ButtonText,      ThemeEngine::instance()->textRegColor());

        cg.setColor(TQColorGroup::Text,            ThemeEngine::instance()->textRegColor());
        cg.setColor(TQColorGroup::Link,            ThemeEngine::instance()->textSpecialRegColor());
        cg.setColor(TQColorGroup::LinkVisited,     ThemeEngine::instance()->textSpecialSelColor());

        /*
        cg.setColor(TQColorGroup::Light,           ThemeEngine::instance()->textRegColor());
        cg.setColor(TQColorGroup::Midlight,        ThemeEngine::instance()->textRegColor());
        cg.setColor(TQColorGroup::Mid,             ThemeEngine::instance()->textRegColor());
        cg.setColor(TQColorGroup::Shadow,          ThemeEngine::instance()->textRegColor());
        */

        plt.setActive(cg);
        plt.setInactive(cg);
        plt.setDisabled(cg);
    }

    kapp->setPalette(plt, true);
}

Theme* ThemeEngine::getCurrentTheme() const
{
    return d->currTheme;
}

TQString ThemeEngine::getCurrentThemeName() const
{
    return d->currTheme->name;
}

void ThemeEngine::buildDefaultTheme()
{
    Theme* t = d->defaultTheme;

    d->defaultPalette      = kapp->palette();
    TQColorGroup cg         = d->defaultPalette.active();

    t->baseColor           = cg.base();
    t->textRegColor        = cg.text();
    t->textSelColor        = cg.highlightedText();
    t->textSpecialRegColor = TQColor("#0000EF");
    t->textSpecialSelColor = cg.highlightedText();

    t->bannerColor         = cg.highlight();
    t->bannerColorTo       = cg.highlight().dark(120);
    t->bannerBevel         = Theme::FLAT;
    t->bannerGrad          = Theme::SOLID;
    t->bannerBorder        = false;
    t->bannerBorderColor   = TQt::black;

    t->thumbRegColor       = cg.base();
    t->thumbRegColorTo     = cg.base();
    t->thumbRegBevel       = Theme::FLAT;
    t->thumbRegGrad        = Theme::SOLID;
    t->thumbRegBorder      = true;
    t->thumbRegBorderColor = TQColor("#E0E0EF");

    t->thumbSelColor       = cg.highlight();
    t->thumbSelColorTo     = cg.highlight();
    t->thumbSelBevel       = Theme::FLAT;
    t->thumbSelGrad        = Theme::SOLID;
    t->thumbSelBorder      = true;
    t->thumbSelBorderColor = TQColor("#E0E0EF");

    t->listRegColor        = cg.base();
    t->listRegColorTo      = cg.base();
    t->listRegBevel        = Theme::FLAT;
    t->listRegGrad         = Theme::SOLID;
    t->listRegBorder       = false;
    t->listRegBorderColor  = TQt::black;

    t->listSelColor        = cg.highlight();
    t->listSelColorTo      = cg.highlight();
    t->listSelBevel        = Theme::FLAT;
    t->listSelGrad         = Theme::SOLID;
    t->listSelBorder       = true;
    t->listSelBorderColor  = TQt::black;
}

bool ThemeEngine::loadTheme()
{
    Q_ASSERT( d->currTheme );
    if (!d->currTheme || d->currTheme == d->defaultTheme)
        return false;

    Theme *t = d->currTheme;

    // use the default theme as base template to build the themes
    *(t) = *(d->defaultTheme);

    TQFile themeFile(t->filePath);

    if (!themeFile.open(IO_ReadOnly))
        return false;

    TQDomDocument xmlDoc;
    TQString error;
    int row, col;
    if (!xmlDoc.setContent(&themeFile, true, &error, &row, &col))
    {
        DDebug() << "Theme file: " << t->filePath << endl;
        DDebug() << error << " :: row=" << row << " , col=" << col << endl; 
        return false;
    }

    TQDomElement rootElem = xmlDoc.documentElement();
    if (rootElem.tagName() != TQString::fromLatin1("digikamtheme"))
        return false;

    TQString resource;

    // -- base ------------------------------------------------------------------------

    resource = resourceValue(rootElem, "BaseColor");
    if (!resource.isEmpty())
        t->baseColor = resource;

    resource = resourceValue(rootElem, "TextRegularColor");
    if (!resource.isEmpty())
        t->textRegColor = resource;

    resource = resourceValue(rootElem, "TextSelectedColor");
    if (!resource.isEmpty())
        t->textSelColor = resource;

    resource = resourceValue(rootElem, "TextSpecialRegularColor");
    if (!resource.isEmpty())
        t->textSpecialRegColor = resource;

    resource = resourceValue(rootElem, "TextSpecialSelectedColor");
    if (!resource.isEmpty())
        t->textSpecialSelColor = resource;

    // -- banner ------------------------------------------------------------------------

    resource = resourceValue(rootElem, "BannerColor");
    if (!resource.isEmpty())
        t->bannerColor = resource;

    resource = resourceValue(rootElem, "BannerColorTo");
    if (!resource.isEmpty())
        t->bannerColorTo = resource;

    resource = resourceValue(rootElem, "BannerBevel");
    if (!resource.isEmpty())
    {
        if (resource.contains("flat", false))
            t->bannerBevel = Theme::FLAT;
        else if (resource.contains("sunken", false))
            t->bannerBevel = Theme::SUNKEN;
        else if (resource.contains("raised", false))
            t->bannerBevel = Theme::RAISED;
    }

    resource = resourceValue(rootElem, "BannerGradient");
    if (!resource.isEmpty())
    {
        if (resource.contains("solid", false))
            t->bannerGrad = Theme::SOLID;
        else if (resource.contains("horizontal", false))
            t->bannerGrad = Theme::HORIZONTAL;
        else if (resource.contains("vertical", false))
            t->bannerGrad = Theme::VERTICAL;
        else if (resource.contains("diagonal", false))
            t->bannerGrad = Theme::DIAGONAL;
    }

    resource = resourceValue(rootElem, "BannerBorder");
    if (!resource.isEmpty())
    {
        t->bannerBorder = resource.contains("true", false);
    }

    resource = resourceValue(rootElem, "BannerBorderColor");
    if (!resource.isEmpty())
    {
        t->bannerBorderColor = resource;
    }

    // -- thumbnail view ----------------------------------------------------------------

    resource = resourceValue(rootElem, "ThumbnailRegularColor");
    if (!resource.isEmpty())
        t->thumbRegColor = resource;

    resource = resourceValue(rootElem, "ThumbnailRegularColorTo");
    if (!resource.isEmpty())
        t->thumbRegColorTo = resource;

    resource = resourceValue(rootElem, "ThumbnailRegularBevel");
    if (!resource.isEmpty())
    {
        if (resource.contains("flat", false))
            t->thumbRegBevel = Theme::FLAT;
        else if (resource.contains("sunken", false))
            t->thumbRegBevel = Theme::SUNKEN;
        else if (resource.contains("raised", false))
            t->thumbRegBevel = Theme::RAISED;
    }

    resource = resourceValue(rootElem, "ThumbnailRegularGradient");
    if (!resource.isEmpty())
    {
        if (resource.contains("solid", false))
            t->thumbRegGrad = Theme::SOLID;
        else if (resource.contains("horizontal", false))
            t->thumbRegGrad = Theme::HORIZONTAL;
        else if (resource.contains("vertical", false))
            t->thumbRegGrad = Theme::VERTICAL;
        else if (resource.contains("diagonal", false))
            t->thumbRegGrad = Theme::DIAGONAL;
    }

    resource = resourceValue(rootElem, "ThumbnailRegularBorder");
    if (!resource.isEmpty())
    {
        t->thumbRegBorder = resource.contains("true", false);
    }

    resource = resourceValue(rootElem, "ThumbnailRegularBorderColor");
    if (!resource.isEmpty())
    {
        t->thumbRegBorderColor = resource;
    }

    resource = resourceValue(rootElem, "ThumbnailSelectedColor");
    if (!resource.isEmpty())
        t->thumbSelColor = resource;

    resource = resourceValue(rootElem, "ThumbnailSelectedColorTo");
    if (!resource.isEmpty())
        t->thumbSelColorTo = resource;

    resource = resourceValue(rootElem, "ThumbnailSelectedBevel");
    if (!resource.isEmpty())
    {
        if (resource.contains("flat", false))
            t->thumbSelBevel = Theme::FLAT;
        else if (resource.contains("sunken", false))
            t->thumbSelBevel = Theme::SUNKEN;
        else if (resource.contains("raised", false))
            t->thumbSelBevel = Theme::RAISED;
    }

    resource = resourceValue(rootElem, "ThumbnailSelectedGradient");
    if (!resource.isEmpty())
    {
        if (resource.contains("solid", false))
            t->thumbSelGrad = Theme::SOLID;
        else if (resource.contains("horizontal", false))
            t->thumbSelGrad = Theme::HORIZONTAL;
        else if (resource.contains("vertical", false))
            t->thumbSelGrad = Theme::VERTICAL;
        else if (resource.contains("diagonal", false))
            t->thumbSelGrad = Theme::DIAGONAL;
    }

    resource = resourceValue(rootElem, "ThumbnailSelectedBorder");
    if (!resource.isEmpty())
    {
        t->thumbSelBorder = resource.contains("true", false);
    }

    resource = resourceValue(rootElem, "ThumbnailSelectedBorderColor");
    if (!resource.isEmpty())
    {
        t->thumbSelBorderColor = resource;
    }

    // -- listview view ----------------------------------------------------------------

    resource = resourceValue(rootElem, "ListviewRegularColor");
    if (!resource.isEmpty())
        t->listRegColor = resource;

    resource = resourceValue(rootElem, "ListviewRegularColorTo");
    if (!resource.isEmpty())
        t->listRegColorTo = resource;

    resource = resourceValue(rootElem, "ListviewRegularBevel");
    if (!resource.isEmpty())
    {
        if (resource.contains("flat", false))
            t->listRegBevel = Theme::FLAT;
        else if (resource.contains("sunken", false))
            t->listRegBevel = Theme::SUNKEN;
        else if (resource.contains("raised", false))
            t->listRegBevel = Theme::RAISED;
    }

    resource = resourceValue(rootElem, "ListviewRegularGradient");
    if (!resource.isEmpty())
    {
        if (resource.contains("solid", false))
            t->listRegGrad = Theme::SOLID;
        else if (resource.contains("horizontal", false))
            t->listRegGrad = Theme::HORIZONTAL;
        else if (resource.contains("vertical", false))
            t->listRegGrad = Theme::VERTICAL;
        else if (resource.contains("diagonal", false))
            t->listRegGrad = Theme::DIAGONAL;
    }

    resource = resourceValue(rootElem, "ListviewRegularBorder");
    if (!resource.isEmpty())
    {
        t->listRegBorder = resource.contains("true", false);
    }

    resource = resourceValue(rootElem, "ListviewRegularBorderColor");
    if (!resource.isEmpty())
    {
        t->listRegBorderColor = resource;
    }

    resource = resourceValue(rootElem, "ListviewSelectedColor");
    if (!resource.isEmpty())
        t->listSelColor = resource;

    resource = resourceValue(rootElem, "ListviewSelectedColorTo");
    if (!resource.isEmpty())
        t->listSelColorTo = resource;

    resource = resourceValue(rootElem, "ListviewSelectedBevel");
    if (!resource.isEmpty())
    {
        if (resource.contains("flat", false))
            t->listSelBevel = Theme::FLAT;
        else if (resource.contains("sunken", false))
            t->listSelBevel = Theme::SUNKEN;
        else if (resource.contains("raised", false))
            t->listSelBevel = Theme::RAISED;
    }

    resource = resourceValue(rootElem, "ListviewSelectedGradient");
    if (!resource.isEmpty())
    {
        if (resource.contains("solid", false))
            t->listSelGrad = Theme::SOLID;
        else if (resource.contains("horizontal", false))
            t->listSelGrad = Theme::HORIZONTAL;
        else if (resource.contains("vertical", false))
            t->listSelGrad = Theme::VERTICAL;
        else if (resource.contains("diagonal", false))
            t->listSelGrad = Theme::DIAGONAL;
    }

    resource = resourceValue(rootElem, "ListviewSelectedBorder");
    if (!resource.isEmpty())
    {
        t->listSelBorder = resource.contains("true", false);
    }

    resource = resourceValue(rootElem, "ListviewSelectedBorderColor");
    if (!resource.isEmpty())
    {
        t->listSelBorderColor = resource;
    }

    DDebug() << "Theme file loaded: " << t->filePath << endl;
    return true;
}

TQString ThemeEngine::resourceValue(const TQDomElement &rootElem, const TQString& key)
{
    for (TQDomNode node = rootElem.firstChild();
         !node.isNull(); node = node.nextSibling()) 
    {
        TQDomElement e = node.toElement();
        TQString name  = e.tagName(); 
        TQString val   = e.attribute(TQString::fromLatin1("value")); 

        if (key == name)
        {
            return val;
        } 
    }

    return TQString("");
}

bool ThemeEngine::saveTheme()
{
    Q_ASSERT( d->currTheme );
    if (!d->currTheme)
        return false;

    Theme *t = d->currTheme;

    TQFileInfo fi(t->filePath);

    TQFile themeFile(fi.filePath());

    if (!themeFile.open(IO_WriteOnly))
        return false;

    KUser        user;
    TQDomDocument xmlDoc;
    TQDomElement  e;
    TQString      val;

    // header ------------------------------------------------------------------

    xmlDoc.appendChild(xmlDoc.createProcessingInstruction(TQString::fromLatin1("xml"),
                       TQString::fromLatin1("version=\"1.0\" encoding=\"UTF-8\"")));

    TQString banner = TQString("\n/* ============================================================"
                             "\n *"
                             "\n * This file is a part of digiKam project"
                             "\n * http://www.digikam.org"
                             "\n *"
                             "\n * Date        : %1-%2-%3"
                             "\n * Description : %4 colors theme."
                             "\n *"
                             "\n * Copyright (C) %5 by %6"
                             "\n *"
                             "\n * This program is free software; you can redistribute it"
                             "\n * and/or modify it under the terms of the GNU General"
                             "\n * Public License as published by the Free Software Foundation;"
                             "\n * either version 2, or (at your option)"
                             "\n * any later version."
                             "\n * "
                             "\n * This program is distributed in the hope that it will be useful,"
                             "\n * but WITHOUT ANY WARRANTY; without even the implied warranty of"
                             "\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the"
                             "\n * GNU General Public License for more details."
                             "\n *"
                             "\n * ============================================================ */\n")
                    .arg(TQDate::currentDate().year())
                    .arg(TQDate::currentDate().month())
                    .arg(TQDate::currentDate().day())
                    .arg(fi.fileName())
                    .arg(TQDate::currentDate().year())
                    .arg(user.fullName());

    xmlDoc.appendChild(xmlDoc.createComment(banner));

    TQDomElement themeElem = xmlDoc.createElement(TQString::fromLatin1("digikamtheme")); 
    xmlDoc.appendChild(themeElem);

    // base props --------------------------------------------------------------

    e = xmlDoc.createElement(TQString::fromLatin1("name"));
    e.setAttribute(TQString::fromLatin1("value"), fi.fileName());
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("BaseColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->baseColor.name()).upper());
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("TextRegularColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->textRegColor.name()).upper());
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("TextSelectedColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->textSelColor.name()).upper());
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("TextSpecialRegularColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->textSpecialRegColor.name()).upper());
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("TextSpecialSelectedColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->textSpecialSelColor.name()).upper());
    themeElem.appendChild(e);

    // banner props ------------------------------------------------------------

    e = xmlDoc.createElement(TQString::fromLatin1("BannerColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->bannerColor.name()).upper());
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("BannerColorTo"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->bannerColorTo.name()).upper());
    themeElem.appendChild(e);

    switch(t->bannerBevel)
    {
        case(Theme::FLAT):
        {
            val = TQString("FLAT");
            break;
        }
        case(Theme::RAISED):
        {
            val = TQString("RAISED");
            break;
        }
        case(Theme::SUNKEN):
        {
            val = TQString("SUNKEN");
            break;
        }
    };

    e = xmlDoc.createElement(TQString::fromLatin1("BannerBevel"));
    e.setAttribute(TQString::fromLatin1("value"), val);
    themeElem.appendChild(e);

    switch(t->bannerGrad)
    {
        case(Theme::SOLID):
        {
            val = TQString("SOLID");
            break;
        }
        case(Theme::HORIZONTAL):
        {
            val = TQString("HORIZONTAL");
            break;
        }
        case(Theme::VERTICAL):
        {
            val = TQString("VERTICAL");
            break;
        }
        case(Theme::DIAGONAL):
        {
            val = TQString("DIAGONAL");
            break;
        }
    };

    e = xmlDoc.createElement(TQString::fromLatin1("BannerGradient"));
    e.setAttribute(TQString::fromLatin1("value"), val);
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("BannerBorder"));
    e.setAttribute(TQString::fromLatin1("value"), (t->bannerBorder ? "true" : "false"));
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("BannerBorderColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->bannerBorderColor.name()).upper());
    themeElem.appendChild(e);

    // thumbnail.regular props -------------------------------------------------

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailRegularColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->thumbRegColor.name()).upper());
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailRegularColorTo"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->thumbRegColorTo.name()).upper());
    themeElem.appendChild(e);

    switch(t->thumbRegBevel)
    {
        case(Theme::FLAT):
        {
            val = TQString("FLAT");
            break;
        }
        case(Theme::RAISED):
        {
            val = TQString("RAISED");
            break;
        }
        case(Theme::SUNKEN):
        {
            val = TQString("SUNKEN");
            break;
        }
    };

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailRegularBevel"));
    e.setAttribute(TQString::fromLatin1("value"), val);
    themeElem.appendChild(e);

    switch(t->thumbRegGrad)
    {
        case(Theme::SOLID):
        {
            val = TQString("SOLID");
            break;
        }
        case(Theme::HORIZONTAL):
        {
            val = TQString("HORIZONTAL");
            break;
        }
        case(Theme::VERTICAL):
        {
            val = TQString("VERTICAL");
            break;
        }
        case(Theme::DIAGONAL):
        {
            val = TQString("DIAGONAL");
            break;
        }
    };

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailRegularGradient"));
    e.setAttribute(TQString::fromLatin1("value"), val);
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailRegularBorder"));
    e.setAttribute(TQString::fromLatin1("value"), (t->thumbRegBorder ? "true" : "false"));
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailRegularBorderColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->thumbRegBorderColor.name()).upper());
    themeElem.appendChild(e);

    // thumbnail.selected props -------------------------------------------------

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailSelectedColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->thumbSelColor.name()).upper());
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailSelectedColorTo"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->thumbSelColorTo.name()).upper());
    themeElem.appendChild(e);

    switch(t->thumbSelBevel)
    {
        case(Theme::FLAT):
        {
            val = TQString("FLAT");
            break;
        }
        case(Theme::RAISED):
        {
            val = TQString("RAISED");
            break;
        }
        case(Theme::SUNKEN):
        {
            val = TQString("SUNKEN");
            break;
        }
    };

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailSelectedBevel"));
    e.setAttribute(TQString::fromLatin1("value"), val);
    themeElem.appendChild(e);

    switch(t->thumbSelGrad)
    {
        case(Theme::SOLID):
        {
            val = TQString("SOLID");
            break;
        }
        case(Theme::HORIZONTAL):
        {
            val = TQString("HORIZONTAL");
            break;
        }
        case(Theme::VERTICAL):
        {
            val = TQString("VERTICAL");
            break;
        }
        case(Theme::DIAGONAL):
        {
            val = TQString("DIAGONAL");
            break;
        }
    };

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailSelectedGradient"));
    e.setAttribute(TQString::fromLatin1("value"), val);
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailSelectedBorder"));
    e.setAttribute(TQString::fromLatin1("value"), (t->thumbSelBorder ? "true" : "false"));
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ThumbnailSelectedBorderColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->thumbSelBorderColor.name()).upper());
    themeElem.appendChild(e);

    // listview.regular props -------------------------------------------------

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewRegularColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->listRegColor.name()).upper());
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewRegularColorTo"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->listRegColorTo.name()).upper());
    themeElem.appendChild(e);

    switch(t->listRegBevel)
    {
        case(Theme::FLAT):
        {
            val = TQString("FLAT");
            break;
        }
        case(Theme::RAISED):
        {
            val = TQString("RAISED");
            break;
        }
        case(Theme::SUNKEN):
        {
            val = TQString("SUNKEN");
            break;
        }
    };

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewRegularBevel"));
    e.setAttribute(TQString::fromLatin1("value"), val);
    themeElem.appendChild(e);

    switch(t->listRegGrad)
    {
        case(Theme::SOLID):
        {
            val = TQString("SOLID");
            break;
        }
        case(Theme::HORIZONTAL):
        {
            val = TQString("HORIZONTAL");
            break;
        }
        case(Theme::VERTICAL):
        {
            val = TQString("VERTICAL");
            break;
        }
        case(Theme::DIAGONAL):
        {
            val = TQString("DIAGONAL");
            break;
        }
    };

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewRegularGradient"));
    e.setAttribute(TQString::fromLatin1("value"), val);
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewRegularBorder"));
    e.setAttribute(TQString::fromLatin1("value"), (t->listRegBorder ? "true" : "false"));
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewRegularBorderColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->listRegBorderColor.name()).upper());
    themeElem.appendChild(e);

    // listview.selected props -------------------------------------------------

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewSelectedColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->listSelColor.name()).upper());
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewSelectedColorTo"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->listSelColorTo.name()).upper());
    themeElem.appendChild(e);

    switch(t->listSelBevel)
    {
        case(Theme::FLAT):
        {
            val = TQString("FLAT");
            break;
        }
        case(Theme::RAISED):
        {
            val = TQString("RAISED");
            break;
        }
        case(Theme::SUNKEN):
        {
            val = TQString("SUNKEN");
            break;
        }
    };

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewSelectedBevel"));
    e.setAttribute(TQString::fromLatin1("value"), val);
    themeElem.appendChild(e);

    switch(t->listSelGrad)
    {
        case(Theme::SOLID):
        {
            val = TQString("SOLID");
            break;
        }
        case(Theme::HORIZONTAL):
        {
            val = TQString("HORIZONTAL");
            break;
        }
        case(Theme::VERTICAL):
        {
            val = TQString("VERTICAL");
            break;
        }
        case(Theme::DIAGONAL):
        {
            val = TQString("DIAGONAL");
            break;
        }
    };

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewSelectedGradient"));
    e.setAttribute(TQString::fromLatin1("value"), val);
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewSelectedBorder"));
    e.setAttribute(TQString::fromLatin1("value"), (t->listSelBorder ? "true" : "false"));
    themeElem.appendChild(e);

    e = xmlDoc.createElement(TQString::fromLatin1("ListviewSelectedBorderColor"));
    e.setAttribute(TQString::fromLatin1("value"), TQString(t->listSelBorderColor.name()).upper());
    themeElem.appendChild(e);

    // -------------------------------------------------------------------------

    TQTextStream stream(&themeFile);
    stream.setEncoding(TQTextStream::UnicodeUTF8);
    stream << xmlDoc.toString();
    themeFile.close();

    return true;
}

}  // NameSpace Digikam
