<commit_before>/*
  This file is part of KOrganizer.

  Copyright (c) 2007 <NAME> <<EMAIL>>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "themeimporter.h"
#include "theme.h"

#include <KLocale>

using namespace KOrg;

ThemeImporter::ThemeImporter() : QXmlStreamReader()
{
}

ThemeImporter::ThemeImporter( QIODevice* device ) : QXmlStreamReader( device )
{
  ThemeImporter();
  read( device );
}

ThemeImporter::~ThemeImporter()
{
  qDeleteAll( mPerViewConfigGroups );
  mPerViewConfigGroups.clear();
}

///////////////////////////////////////////////////////////////////////////////

bool ThemeImporter::read( QIODevice* device )
{
  setDevice( device );

  while ( !atEnd() ) {
    readNext();

    if ( isStartElement() ) {
      if ( name( ) == "korganizer-theme"
           && attributes().value("version") == "1.0" )
        readThemeXml();
      else
        raiseError( i18n("This file is not a KOrganizer theme file.") );
    }
  }

  return !error();
}

void ThemeImporter::readThemeXml()
{
  Q_ASSERT( isStartElement() && name() == "korganizer-theme" );

  kDebug() << "Reading theme XML." << endl;
  
  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
        readElement();
    }
  }
}

///////////////////////////////////////////////////////////////////////////////

void ThemeImporter::readElement( const QString &viewType,
                                 const int year, const int month,
                                 const int day )
{
  if ( name() == "view" )
    readView( viewType, year, month, day );
/***** TODO: Date-dependent themes disabled for now ******
  else if ( name() == "year" || name() == "month" || name() == "day" )
    readDate( viewType, year, month, day );
*/

  else if ( name() == "grid" )
    readGrid( viewType, year, month, day );
  else if ( name() == "time-labels" )
    readTimeLabels( viewType, year, month, day );
  else if ( name() == "calendar-items" )
    readCalendarItems( viewType, year, month, day );
  else if ( name() == "marcus-bains-line" )
    readMarcusBainsLine( viewType, year, month, day );
  else if ( name() == "holidays" )
    readHolidays( viewType, year, month, day );

  else
    readUnknownElement();
}

void ThemeImporter::readDate( const QString &viewType,
                              const int year, const int month,
                              const int day )
{
  Q_ASSERT( isStartElement() && ( name() == "year" || name() == "month"
      || name() == "day" ) );

  int y = year;
  int m = month;
  int d = day;

  if ( name() == "year" ) {
    y = attributes().value("value").toString().toInt();
  }
  else if ( name() == "month" ) {
    m = attributes().value("value").toString().toInt();
  }
  else if ( name() == "day" ) {
    d = attributes().value("value").toString().toInt();
  }

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      if ( name() == "year" || name() == "month" || name() == "day" ) {
        readDate( viewType, y, m, d );
      }
      else {
        readElement( viewType, y, m, d );
      }
      kDebug() << "date: " << y << "-" << m << "-" << d << endl;
    }
  }
}

void ThemeImporter::readView( const QString &viewType,
                              const int year, const int month,
                              const int day )
{
  Q_ASSERT( isStartElement() && name() == "view" );

  QString v = viewType;
  v = attributes().value("type").toString();
  kDebug() << "viewType: " << v << endl;

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      readElement( v, year, month, day );
    }
  }
}

void ThemeImporter::readUnknownElement()
{
  Q_ASSERT( isStartElement() );

  kWarning() << "ThemeImporter: Unknown element found at line " << lineNumber()
             << ", ending at column " << columnNumber() << ": "
             << name().toString() << endl;

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() ) {
      break;
    }

    if ( isStartElement() )
      readUnknownElement();
  }
}

///////////////////////////////////////////////////////////////////////////////

void ThemeImporter::readCalendarItems( const QString &viewType,
                                       const int year, const int month,
                                       const int day )
{
  Q_ASSERT( isStartElement() && name() == "calendar-items" );

  // As the available settings are the same for the various calendar items
  // types, we use a "stack" to keep in mind where we are in the hierarchy
  // while having the possibility of using the same methods to read the
  // settings' tags.
  QList< QPair<QString, QString> > stack;
  stack.append( qMakePair( QString(), QString("CalendarItems") ) );

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() ) {
      if ( stack.count() > 1 ) {
        stack.removeLast();  // We are going down one level
      }
      else {
        break;
      }
    }

    if ( isStartElement() ) {
      /* Item type tags: first level */
      if ( stack.count() == 1 && name() == "events" ) {
        stack.append( qMakePair( QString("events"),
                                 QString("CalendarItemsEvents") ) );
      }
      else if ( stack.count() == 1 && name() == "to-dos" ) {
        stack.append( qMakePair( QString("to-dos"),
                                 QString("CalendarItemsToDos") ) );
      }
      /* Sub-elements of to-dos (second level) */
      else if ( stack.count() == 2 && stack.last().first == "to-dos"
                && name() == "overdue" ) {
        stack.append( qMakePair( QString("to-dos/overdue"),
                      QString("CalendarItemsToDosOverdue")
                               ) );
      }
      else if ( stack.count() == 2 && stack.last().first == "to-dos"
                && name() == "due-today" ) {
        stack.append( qMakePair( QString("to-dos/due-today"),
                      QString("CalendarItemsToDosDueToday")
                               ) );
      }
      /* The sub-elements of these tags allow free text */
      else if ( stack.count() == 1 && name() == "categories" ) {
        stack.append( qMakePair( QString("categories"),
                                 // When a setting applies to all categories,
                                 // it applies to all items.
                                 QString("CalendarItems") ) );
      }
      else if ( stack.count() == 1 && name() == "resources" ) {
        stack.append( qMakePair( QString("resources"),
                                 // When a setting applies to all resources,
                                 // it applies to all items.
                                 QString("CalendarItems") ) );
      }
      /* The said sub-elements */
      else if ( stack.count() == 2 && stack.last().first == "categories"
                && name() == "category" ) {
        QString n = attributes().value("name").toString();
        stack.append( qMakePair( QString("categories/" + n),
                                 QString("CalendarItemsCategories" + n)
                               ) );
      }
      else if ( stack.count() == 2 && stack.last().first == "resources"
                && name() == "resource" ) {
        QString n = attributes().value("name").toString();
        stack.append( qMakePair( QString("resources/" + n),
                                 QString("CalendarItemsResources" + n)
                               ) );
      }
      /* Settings' tags */
      else if ( name() == "background" ) {
        setColor( viewType, year, month, day,
                  stack.last().second + "BackgroundColor",
                  attributes().value("color").toString() );
        setPath( viewType, year, month, day,
                 stack.last().second + "BackgroundImage",
                 attributes().value("src").toString() );
        readNext();
      }
      else if ( name() == "font" ) {
        setFont( viewType, year, month, day,
                 stack.last().second + "Font",
                 attributes().value("family").toString(),
                 attributes().value("style-hint").toString(),
                 attributes().value("point-size").toString().toInt(),
                 attributes().value("weight").toString().toInt(),
                 attributes().value("style").toString(),
                 attributes().value("stretch-factor").toString().toInt() );
        readNext();
      }
      else if ( name() == "frame" ) {
        setColor( viewType, year, month, day,
                  stack.last().second + "FrameColor",
                  attributes().value("color").toString() );
        readNext();
      }
      else if ( name() == "icon" ) {
        setString( viewType, year, month, day,
                   stack.last().second + "Icon",
                   attributes().value("name").toString() );
        setPath( viewType, year, month, day,
                 stack.last().second + "IconFile",
                 attributes().value("src").toString() );
        readNext();
      }
      /* Unknown elements */
      else {
        readUnknownElement();
      }
    }
  }
}

void ThemeImporter::readGrid( const QString &viewType,
                              const int year, const int month,
                              const int day )
{
  Q_ASSERT( isStartElement() && name() == "grid" );

  QString cfg = "Grid";

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      if ( name() == "background" ) {
        setColor( viewType, year, month, day,
                  cfg + "BackgroundColor",
                  attributes().value("color").toString() );
        setPath( viewType, year, month, day,
                 cfg + "BackgroundImage",
                 attributes().value("src").toString() );
        readNext();
      }
      else if ( name() == "highlight" ) {
        setColor( viewType, year, month, day,
                  cfg + "HighlightColor",
                  attributes().value("color").toString() );
        readNext();
      }
      else if ( name() == "work-hours" ) {
        while ( !atEnd() ) {
          readNext();

          if ( isEndElement() )
            break;

          if ( isStartElement() ) {
            if ( name() == "background" ) {
              setColor( viewType, year, month, day,
                        cfg + "WorkHoursBackgroundColor",
                        attributes().value("color").toString() );
              setPath( viewType, year, month, day,
                       cfg + "WorkHoursBackgroundImage",
                       attributes().value("src").toString() );
              readNext();
            }
            else {
              readUnknownElement();
            }
          }
        }
      }
      else {
        readUnknownElement();
      }
    }
  }
}

void ThemeImporter::readHolidays( const QString &viewType,
                                  const int year, const int month,
                                  const int day )
{
  Q_ASSERT( isStartElement() && name() == "holidays" );

  QString cfg = "Holidays";

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      if ( name() == "background" ) {
        setColor( viewType, year, month, day,
                  cfg + "BackgroundColor",
                  attributes().value("color").toString() );
        setPath( viewType, year, month, day,
                 cfg + "BackgroundImage",
                 attributes().value("src").toString() );
        readNext();
      }
      else {
        readUnknownElement();
      }
    }
  }
}

void ThemeImporter::readMarcusBainsLine( const QString &viewType,
                                         const int year, const int month,
                                         const int day )
{
  Q_ASSERT( isStartElement() && name() == "marcus-bains-line" );

  QString cfg = "MarcusBainsLine";

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      if ( name() == "font" ) {
        setFont( viewType, year, month, day,
                 cfg + "Font",
                 attributes().value("family").toString(),
                 attributes().value("style-hint").toString(),
                 attributes().value("point-size").toString().toInt(),
                 attributes().value("weight").toString().toInt(),
                 attributes().value("style").toString(),
                 attributes().value("stretch-factor").toString().toInt() );
        readNext();
      }
      else if ( name() == "line" ) {
        setColor( viewType, year, month, day,
                  cfg + "LineColor",
                  attributes().value("color").toString() );
        readNext();
      }
      else {
        readUnknownElement();
      }
    }
  }
}

void ThemeImporter::readTimeLabels( const QString &viewType,
                                    const int year, const int month,
                                    const int day )
{
  Q_ASSERT( isStartElement() && name() == "time-labels" );

  QString cfg = "TimeLabels";

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      if ( name() == "font" ) {
        setFont( viewType, year, month, day,
                 cfg + "Font",
                 attributes().value("family").toString(),
                 attributes().value("style-hint").toString(),
                 attributes().value("point-size").toString().toInt(),
                 attributes().value("weight").toString().toInt(),
                 attributes().value("style").toString(),
                 attributes().value("stretch-factor").toString().toInt() );
        readNext();
      }
      else {
        readUnknownElement();
      }
    }
  }
}

///////////////////////////////////////////////////////////////////////////////

void ThemeImporter::setColor( const QString &viewType,
                              const int year, const int month,
                              const int day,
                              const QString &key, const QString &value )
{
  QString htmlColor = value.toUpper();
  if ( ( htmlColor.count( QRegExp("^#[0-9A-F]{6}$") ) == 1 )
       || ( htmlColor.count( QRegExp("^#[0-9A-F]{8}$") ) == 1 ) ) {<commit_msg>Theme importer class: Adapt to settings readability changes<commit_after>/*
  This file is part of KOrganizer.

  Copyright (c) 2007 <NAME> <<EMAIL>>

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "themeimporter.h"
#include "theme.h"

#include <KLocale>

using namespace KOrg;

ThemeImporter::ThemeImporter() : QXmlStreamReader()
{
}

ThemeImporter::ThemeImporter( QIODevice* device ) : QXmlStreamReader( device )
{
  ThemeImporter();
  read( device );
}

ThemeImporter::~ThemeImporter()
{
  qDeleteAll( mPerViewConfigGroups );
  mPerViewConfigGroups.clear();
}

///////////////////////////////////////////////////////////////////////////////

bool ThemeImporter::read( QIODevice* device )
{
  setDevice( device );

  while ( !atEnd() ) {
    readNext();

    if ( isStartElement() ) {
      if ( name( ) == "korganizer-theme"
           && attributes().value("version") == "1.0" )
        readThemeXml();
      else
        raiseError( i18n("This file is not a KOrganizer theme file.") );
    }
  }

  return !error();
}

void ThemeImporter::readThemeXml()
{
  Q_ASSERT( isStartElement() && name() == "korganizer-theme" );

  kDebug() << "Reading theme XML." << endl;
  
  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
        readElement();
    }
  }
}

///////////////////////////////////////////////////////////////////////////////

void ThemeImporter::readElement( const QString &viewType,
                                 const int year, const int month,
                                 const int day )
{
  if ( name() == "view" )
    readView( viewType, year, month, day );
/***** TODO: Date-dependent themes disabled for now ******
  else if ( name() == "year" || name() == "month" || name() == "day" )
    readDate( viewType, year, month, day );
*/

  else if ( name() == "grid" )
    readGrid( viewType, year, month, day );
  else if ( name() == "time-labels" )
    readTimeLabels( viewType, year, month, day );
  else if ( name() == "calendar-items" )
    readCalendarItems( viewType, year, month, day );
  else if ( name() == "marcus-bains-line" )
    readMarcusBainsLine( viewType, year, month, day );
  else if ( name() == "holidays" )
    readHolidays( viewType, year, month, day );

  else
    readUnknownElement();
}

void ThemeImporter::readDate( const QString &viewType,
                              const int year, const int month,
                              const int day )
{
  Q_ASSERT( isStartElement() && ( name() == "year" || name() == "month"
      || name() == "day" ) );

  int y = year;
  int m = month;
  int d = day;

  if ( name() == "year" ) {
    y = attributes().value("value").toString().toInt();
  }
  else if ( name() == "month" ) {
    m = attributes().value("value").toString().toInt();
  }
  else if ( name() == "day" ) {
    d = attributes().value("value").toString().toInt();
  }

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      if ( name() == "year" || name() == "month" || name() == "day" ) {
        readDate( viewType, y, m, d );
      }
      else {
        readElement( viewType, y, m, d );
      }
      kDebug() << "date: " << y << "-" << m << "-" << d << endl;
    }
  }
}

void ThemeImporter::readView( const QString &viewType,
                              const int year, const int month,
                              const int day )
{
  Q_ASSERT( isStartElement() && name() == "view" );

  QString v = viewType;
  v = attributes().value("type").toString();
  kDebug() << "viewType: " << v << endl;

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      readElement( v, year, month, day );
    }
  }
}

void ThemeImporter::readUnknownElement()
{
  Q_ASSERT( isStartElement() );

  kWarning() << "ThemeImporter: Unknown element found at line " << lineNumber()
             << ", ending at column " << columnNumber() << ": "
             << name().toString() << endl;

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() ) {
      break;
    }

    if ( isStartElement() )
      readUnknownElement();
  }
}

///////////////////////////////////////////////////////////////////////////////

void ThemeImporter::readCalendarItems( const QString &viewType,
                                       const int year, const int month,
                                       const int day )
{
  Q_ASSERT( isStartElement() && name() == "calendar-items" );

  // As the available settings are the same for the various calendar items
  // types, we use a "stack" to keep in mind where we are in the hierarchy
  // while having the possibility of using the same methods to read the
  // settings' tags.
  QList< QPair<QString, QString> > stack;
  stack.append( qMakePair( QString(), QString("CalendarItems") ) );

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() ) {
      if ( stack.count() > 1 ) {
        stack.removeLast();  // We are going down one level
      }
      else {
        break;
      }
    }

    if ( isStartElement() ) {
      /* Item type tags: first level */
      if ( stack.count() == 1 && name() == "events" ) {
        stack.append( qMakePair( QString("events"),
                                 QString("CalendarItems Events") ) );
      }
      else if ( stack.count() == 1 && name() == "to-dos" ) {
        stack.append( qMakePair( QString("to-dos"),
                                 QString("CalendarItems ToDos") ) );
      }
      /* Sub-elements of to-dos (second level) */
      else if ( stack.count() == 2 && stack.last().first == "to-dos"
                && name() == "overdue" ) {
        stack.append( qMakePair( QString("to-dos/overdue"),
                      QString("CalendarItems ToDos Overdue")
                               ) );
      }
      else if ( stack.count() == 2 && stack.last().first == "to-dos"
                && name() == "due-today" ) {
        stack.append( qMakePair( QString("to-dos/due-today"),
                      QString("CalendarItems ToDos DueToday")
                               ) );
      }
      /* The sub-elements of these tags allow free text */
      else if ( stack.count() == 1 && name() == "categories" ) {
        stack.append( qMakePair( QString("categories"),
                                 // When a setting applies to all categories,
                                 // it applies to all items.
                                 QString("CalendarItems") ) );
      }
      else if ( stack.count() == 1 && name() == "resources" ) {
        stack.append( qMakePair( QString("resources"),
                                 // When a setting applies to all resources,
                                 // it applies to all items.
                                 QString("CalendarItems") ) );
      }
      /* The said sub-elements */
      else if ( stack.count() == 2 && stack.last().first == "categories"
                && name() == "category" ) {
        QString n = attributes().value("name").toString();
        stack.append( qMakePair( QString("categories/" + n),
                                 QString("CalendarItems Categories" + n)
                               ) );
      }
      else if ( stack.count() == 2 && stack.last().first == "resources"
                && name() == "resource" ) {
        QString n = attributes().value("name").toString();
        stack.append( qMakePair( QString("resources/" + n),
                                 QString("CalendarItems Resources" + n)
                               ) );
      }
      /* Settings' tags */
      else if ( name() == "background" ) {
        setColor( viewType, year, month, day,
                  stack.last().second + " Background Color",
                  attributes().value("color").toString() );
        setPath( viewType, year, month, day,
                 stack.last().second + " Background Image",
                 attributes().value("src").toString() );
        readNext();
      }
      else if ( name() == "font" ) {
        setFont( viewType, year, month, day,
                 stack.last().second + " Font",
                 attributes().value("family").toString(),
                 attributes().value("style-hint").toString(),
                 attributes().value("point-size").toString().toInt(),
                 attributes().value("weight").toString().toInt(),
                 attributes().value("style").toString(),
                 attributes().value("stretch-factor").toString().toInt() );
        readNext();
      }
      else if ( name() == "frame" ) {
        setColor( viewType, year, month, day,
                  stack.last().second + " Frame Color",
                  attributes().value("color").toString() );
        readNext();
      }
      else if ( name() == "icon" ) {
        setString( viewType, year, month, day,
                   stack.last().second + " Icon",
                   attributes().value("name").toString() );
        setPath( viewType, year, month, day,
                 stack.last().second + " IconFile",
                 attributes().value("src").toString() );
        readNext();
      }
      /* Unknown elements */
      else {
        readUnknownElement();
      }
    }
  }
}

void ThemeImporter::readGrid( const QString &viewType,
                              const int year, const int month,
                              const int day )
{
  Q_ASSERT( isStartElement() && name() == "grid" );

  QString cfg = "Grid";

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      if ( name() == "background" ) {
        setColor( viewType, year, month, day,
                  cfg + " Background Color",
                  attributes().value("color").toString() );
        setPath( viewType, year, month, day,
                 cfg + " Background Image",
                 attributes().value("src").toString() );
        readNext();
      }
      else if ( name() == "highlight" ) {
        setColor( viewType, year, month, day,
                  cfg + " Highlight Color",
                  attributes().value("color").toString() );
        readNext();
      }
      else if ( name() == "work-hours" ) {
        while ( !atEnd() ) {
          readNext();

          if ( isEndElement() )
            break;

          if ( isStartElement() ) {
            if ( name() == "background" ) {
              setColor( viewType, year, month, day,
                        cfg + " WorkHours Background Color",
                        attributes().value("color").toString() );
              setPath( viewType, year, month, day,
                       cfg + " WorkHours Background Image",
                       attributes().value("src").toString() );
              readNext();
            }
            else {
              readUnknownElement();
            }
          }
        }
      }
      else {
        readUnknownElement();
      }
    }
  }
}

void ThemeImporter::readHolidays( const QString &viewType,
                                  const int year, const int month,
                                  const int day )
{
  Q_ASSERT( isStartElement() && name() == "holidays" );

  QString cfg = "Holidays";

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      if ( name() == "background" ) {
        setColor( viewType, year, month, day,
                  cfg + " Background Color",
                  attributes().value("color").toString() );
        setPath( viewType, year, month, day,
                 cfg + " Background Image",
                 attributes().value("src").toString() );
        readNext();
      }
      else {
        readUnknownElement();
      }
    }
  }
}

void ThemeImporter::readMarcusBainsLine( const QString &viewType,
                                         const int year, const int month,
                                         const int day )
{
  Q_ASSERT( isStartElement() && name() == "marcus-bains-line" );

  QString cfg = "MarcusBainsLine";

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      if ( name() == "font" ) {
        setFont( viewType, year, month, day,
                 cfg + " Font",
                 attributes().value("family").toString(),
                 attributes().value("style-hint").toString(),
                 attributes().value("point-size").toString().toInt(),
                 attributes().value("weight").toString().toInt(),
                 attributes().value("style").toString(),
                 attributes().value("stretch-factor").toString().toInt() );
        readNext();
      }
      else if ( name() == "line" ) {
        setColor( viewType, year, month, day,
                  cfg + " Line Color",
                  attributes().value("color").toString() );
        readNext();
      }
      else {
        readUnknownElement();
      }
    }
  }
}

void ThemeImporter::readTimeLabels( const QString &viewType,
                                    const int year, const int month,
                                    const int day )
{
  Q_ASSERT( isStartElement() && name() == "time-labels" );

  QString cfg = "TimeLabels";

  while ( !atEnd() ) {
    readNext();

    if ( isEndElement() )
      break;

    if ( isStartElement() ) {
      if ( name() == "font" ) {
        setFont( viewType, year, month, day,
                 cfg + " Font",
                 attributes().value("family").toString(),
                 attributes().value("style-hint").toString(),
                 attributes().value("point-size").toString().toInt(),
                 attributes().value("weight").toString().toInt(),
                 attributes().value("style").toString(),
                 attributes().value("stretch-factor").toString().toInt() );
        readNext();
      }
      else {
        readUnknownElement();
      }
    }
  }
}

///////////////////////////////////////////////////////////////////////////////

void ThemeImporter::setColor( const QString &viewType,
                              const int year, const int month,
                              const int day,
                              const QString &key, const QString &value )
{
  QString htmlColor = value.toUpper();
  if ( ( htmlColor.count( QRegExp("^#[0-9A-F]{6}$") ) == 1 )
       || ( htmlColor.count( QRegExp("^#[0-9A-F]{8}$") ) == 1 ) ) {
{'fraction_non_alphanumeric': 0.1669695667977398, 'fraction_numerical': 0.0024452301490268647, 'mean_word_length': 1.6742069453035258, 'pattern_counts': {'":': 2, '<': 91, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 48, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1656263', 'n_tokens_mistral': 8249, 'n_tokens_neox': 8044, 'n_words': 2096}