Commit 3a6b7bd6 authored by Lisbeth Probst's avatar Lisbeth Probst
Browse files

Added svg theme and svg theme manager classes

svn path=/branches/work/soc-stepui/step/; revision=832299
parent 9ee54343
set(step_GUI
dynrestrictions.cpp
set(stepgui_SRCS
svgtheme.cpp
svgthememanager.cpp
)
find_package(KDE4 REQUIRED)
include_directories( ${KDE4_INCLUDES} )
add_definitions( ${KDE4_DEFINITIONS} )
SET( QT_USE_QTXML TRUE )
SET( QT_USE_QTSVG TRUE )
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
kde4_add_library(stepgui STATIC ${stepgui_SRCS} )
target_link_libraries( stepgui ${QT_LIBRARIES} )
#include "svgtheme.hpp"
#include <QDomDocument>
#include <QDomElement>
namespace StepGui
{
SvgTheme::SvgTheme() :
m_itemsTable(),
m_renderer( 0 )
{
//
}
SvgTheme::~SvgTheme()
{
if( this->m_renderer )
{
delete this->m_renderer;
}
}
bool SvgTheme::load( const QString& p_path2svgFile, const QString& p_itemGroupId )
{
QFile svgThemeFile( p_path2svgFile );
return this->_parseSvgFile( svgThemeFile, p_itemGroupId );
}
bool SvgTheme::_parseSvgFile(
QFile& p_themeFile, const QString& p_itemGroupId,
const bool p_processNamespaces,
QString* p_errorMsg, int* p_errorLine, int* p_errorCol )
{
//ToDo : Make the following "fit" for namespace'd svg files (e.g.
// provide branches for calling the xxNS variants
// of the DOM class member methods
if( !p_themeFile.open( QIODevice::ReadOnly ) )
{
return false;
}
QDomDocument svgDoc;
//Transfer the content of the given svg theme file to the DOM instance
if( !svgDoc.setContent( &p_themeFile, p_processNamespaces, p_errorMsg, p_errorLine, p_errorCol ) )
{
return false;
}
//Check whether the item Group Id is an valid string
if( p_itemGroupId.isEmpty() )
{
return false;
}
//using the elementById() Method, as of Qt 4.4 one gets the
//"elementById() is not implemented and always returns a null Node"
//error message. Hence, the short, oneliner from below is commented out
//and for the time being replaced by an explicit search for the
//group item with the proper id :
//QDomElement itemsEnclosingElement( svgDoc.elementById( p_itemGroupId ) );
QDomElement itemsEnclosingElement;
static const QString enclosingTagName( "g" );
static const QString enclosingIdName( "id" );
{
QDomNodeList allGroupElements( svgDoc.elementsByTagName( enclosingTagName ) );
const uint cnt( allGroupElements.length() );
for( uint i = 0 ; i < cnt ; ++i )
{
QDomNode node( allGroupElements.item( i ) );
//That seems to be a bit redundant: If one node with the tag name
//enclosingTagName is an element, it should hold true for all of
//them -> probably change that !
if( node.isElement() )
{
QString nodeId( node.toElement().attribute( enclosingIdName, QString() ) );
if( nodeId == p_itemGroupId )
{
itemsEnclosingElement = node.toElement();
break;
}
}
}
}
if( itemsEnclosingElement.isNull() )
{
return false;
}
//If we are here, the following holds true :
// - There is a readable (XML) File
// - There is at least one element available with id given by p_itemGroupId
// and tagname "g" available.
static const QString itemTagName( enclosingTagName );
static const QString itemIdName( enclosingIdName );
// Remove all found elements from the lookup table, in case it is not
// empty :
this->m_itemsTable.clear();
// Free the currently used QSvgRenderer and allocate a new one :
if( this->m_renderer )
{
delete this->m_renderer;
}
this->m_renderer = new QSvgRenderer( p_themeFile.fileName() );
//Check whether the allocation was successfull -> pure paranoia
if( !this->m_renderer )
{
return false;
}
for(
QDomNode next( itemsEnclosingElement.firstChild() ) ;
!next.isNull() ; next = next.nextSibling())
{
//Next check whether the next sibling is an element itself,
//has an group tag name and has any attribute
if( ( next.isElement() ) && ( next.nodeName() == itemTagName ) &&
( next.hasAttributes() ) )
{
//the content of the variable next has already passed the isElement()
//test, hence it is safe to access it via an QDomElement*. Upward
//casting is done using static_cast.
QString nextId( next.toElement().attribute( itemIdName, QString() ) );
if( !nextId.isEmpty() )
{
//Use Qt's append rather than the STL style push_back():
this->m_itemsTable.append( nextId );
}
}
}
//It is the responsibility of the calling method to close the QFile
//object properly !!
return true;
}
}
//end stegui/svgtheme.cpp
/* This file is part of Step.
Copyright (C) 2008 Lisbeth Probst <probst.lisbeth@gmail.com>
Step is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Step is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Step; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SVG_THEME_MANAGER_CLASS_HEADER_FILE_
#define _SVG_THEME_MANAGER_CLASS_HEADER_FILE_
#include <QVector>
#include <QSvgRenderer>
#include <QString>
#include <QObject>
#include <QList>
#include <QFile>
namespace StepGui
{
/** \name SvgTheme
* \brief contains a list of all items in a theme and a pointer to the renderer
*
* \todo add fields for meta information (author, licensing, description, etc.)
*/
class SvgTheme
{
private:
typedef QVector< QString > svgThemeContainer;
public:
//STL Style Typedefs
typedef svgThemeContainer::pointer pointer;
typedef svgThemeContainer::const_pointer const_pointer;
typedef svgThemeContainer::iterator iterator;
typedef svgThemeContainer::const_iterator const_iterator;
typedef svgThemeContainer::reference reference;
typedef svgThemeContainer::const_reference const_reference;
typedef svgThemeContainer::difference_type difference_type;
typedef svgThemeContainer::size_type size_type;
typedef svgThemeContainer::value_type value_type;
//Qt Style Typedefs
typedef svgThemeContainer::Iterator Iterator;
typedef svgThemeContainer::ConstIterator ConstIterator;
/** \brief Default Constructor */
SvgTheme();
/** \brief Destructor
* \note Since SvgTheme is not a Sub Class of QObject,
* dynamically allocated parts are not handled automatically.
*
* \todo Handle svg namespaces properly (e.g. inkscapes extensions, etc).
*/
~SvgTheme();
/** \brief STL style accessor for the begin of the themes TOC */
iterator begin() { return this->m_itemsTable.begin(); }
/** \brief STL style accessor for the end of the themes TOC */
iterator end() { return this->m_itemsTable.end(); }
/** \brief STL style accessor for the begin of the themes TOC in a const context */
const_iterator begin() const { return this->m_itemsTable.begin(); }
/** \brief STL style accessor for the end of the themes TOC in a const context */
const_iterator end() const { return this->m_itemsTable.end(); }
/** \brief Returns a pointer to the themes SVG Renderer */
QSvgRenderer* renderer() const { return this->m_renderer; }
/** \brief Discard all items and free the SvgRenderer*/
void clear();
/** \brief Check whether the theme contains no elements */
bool isEmpty() const { return ( ( !this->m_renderer ) || ( this->m_itemsTable.isEmpty() ) ); }
/** \brief load a svg file for parsing */
bool load( const QString&, const QString& = QString( "items" ) );
private:
/** \brief search the contents of the svg file for theme items and store them in a list*/
bool _parseSvgFile( QFile&,
const QString& = QString( "items" ), const bool = false,
QString* = 0, int* = 0, int* = 0 );
svgThemeContainer m_itemsTable; ///< Table for storing the id of all themeable items
QSvgRenderer* m_renderer; ///< pointer to associated Svg Renderer on the free-store
};
}
#endif
//end stepgui/svgtheme.hpp
#include "svgthememanager.hpp"
#include <algorithm>
/* This file is part of Step.
Copyright (C) 2008 Lisbeth Probst <probst.lisbeth@gmail.com>
Step is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Step is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Step; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
namespace StepGui
{
SvgThemeManager::SvgThemeManager( QObject* p_parent ) :
QObject( p_parent ),
m_itemsTable(),
m_themesList()
{
//
}
bool SvgThemeManager::add( StepGui::SvgTheme& p_svgTheme )
{
//Check if the theme with the current address &p_svgTheme
//has already been indexed.
//ToDo : Find some better (and more secure) way to do this, e.g.
// avoid dangling pointers after deletion / copy operations
// by using shared pointers to the SvgTheme instead !
if( p_svgTheme.isEmpty() )
{
return false;
}
if( ( this->m_themesList.isEmpty() ) || (
( std::find( this->m_themesList.begin(), this->m_themesList.end(), &p_svgTheme ) == this->m_themesList.end() ) ) )
{
//Either no theme is currently handled by the manager, or
//the current address is not already fetched, hence it is save to proceed.
this->m_themesList.append( &p_svgTheme );
for( StepGui::SvgTheme::iterator it( p_svgTheme.begin() ) ;
it != p_svgTheme.end() ; ++it )
{
this->m_itemsTable.insert( *it, &p_svgTheme );
}
return true;
}
return false;
}
StepGui::SvgTheme* SvgThemeManager::theme( const QString& p_itemId ) const
{
if( this->m_itemsTable.contains( p_itemId ) )
{
return this->m_itemsTable.value( p_itemId );
}
return static_cast< SvgTheme* >( 0 );
}
QList< StepGui::SvgTheme* > SvgThemeManager::themes( const QString& p_itemId ) const
{
if( this->m_itemsTable.contains( p_itemId ) )
{
return this->m_itemsTable.values( p_itemId );
}
return QList< StepGui::SvgTheme* >();
}
SvgThemeManager::const_items_iterator SvgThemeManager::itemsBegin() const
{
return this->m_itemsTable.begin();
}
SvgThemeManager::const_items_iterator SvgThemeManager::itemsEnd() const
{
return this->m_itemsTable.end();
}
SvgThemeManager::const_items_iterator
SvgThemeManager::itemsBegin( const QString& p_itemId ) const
{
if( this->m_itemsTable.contains( p_itemId )
{
return this->m_itemsTable.lowerBound( p_itemId );
}
else
{
return this->m_itemsTable.end();
}
}
SvgThemeManager::const_items_iterator
SvgThemeManager::itemsEnd( const QString& p_itemId ) const
{
if( this->m_itemsTable.contains( p_itemId )
{
return this->m_itemsTable.upperBound( p_itemId );
}
else
{
return this->m_itemsTable.end();
}
}
SvgThemeManager::const_themes_iterator SvgThemeManager::themesBegin() const
{
return this->m_themesList.begin();
}
SvgThemeManager::const_themes_iterator SvgThemeManager::themesEnd() const
{
return this->m_themesList.end();
}
bool SvgThemeManager::isEmpty() const
{
return ( ( this->m_themesList.isEmpty() ) || ( this->m_itemsTable.isEmpty() ) );
}
void SvgThemeManager::clear()
{
this->m_itemsTable.clear();
this->m_themesList.clear();
}
}
//
/* This file is part of Step.
Copyright (C) 2008 Lisbeth Probst <probst.lisbeth@gmail.com>
Step is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Step is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Step; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SVG_THEME_MANAGER_HEADER_FILE_
#define _SVG_THEME_MANAGER_HEADER_FILE_
#include <QMultiMap>
#include <QList>
#include <QSvgRenderer>
#include <QObject>
#include "svgtheme.hpp"
namespace StepGui
{
/** \brief manages multiple svg dressings / themes for step items
*/
class SvgThemeManager : public QObject
{
private:
//QHash would be nicer from a performanc pov, but iterators to
//items stored in the hash would be invalidated by insertion operations.
//Hence, we use the QMap, which is slower at lookups, but keeps
//iterators valid (cf. Qt 4.4 documentation, http://doc.trolltech.com/4.4/qmap-iterator.html)
//Since the whole point of this class is to allow the mix'n match
//of different themes, we use the slightly more convenient QMultiMap
//variant:
typedef QMultiMap< QString, StepGui::SvgTheme* > itemsContainer;
typedef QList< StepGui::SvgTheme* > themesContainer;
public:
//STL style typedefs :
typedef itemsContainer::iterator items_iterator;
typedef itemsContainer::const_iterator const_items_iterator;
typedef themesContainer::iterator themes_iterator;
typedef themesContainer::const_iterator const_themes_iterator;
/** \brief Default Constructor*/
SvgThemeManager( QObject* = 0 );
/** \brief Adds the content of a new SvgTheme to the list of available items*/
bool add( SvgTheme& );
/** \brief Retrieves the latest theme associated with a certain item*/
SvgTheme* theme( const QString& ) const;
/** \brief Retrieves a list of all themes associated with a certain item */
QList< SvgTheme* > themes( const QString& ) const;
/** \brief STL style begin of all item / theme pairs */
const_items_iterator itemsBegin() const;
/** \brief STL style end of all item / theme pairs */
const_items_iterator itemsEnd() const;
/** \brief return iterator to the first theme associated with the given item
\note If no theme is associated with the given item, return an iterator to
the end of the map*/
const_items_iterator itemsBegin( const QString& ) const;
/** \brief return iterator to the (last + 1) theme associated with the given item
\note If no theme is associated with the given item, return an iterator to
the end of the map*/
const_items_iterator itemsEnd( const QString& ) const;
/** \brief STL style iterator to the first element in the themes list */
const_themes_iterator themesBegin() const;
/** \brief STL style iterator to the last element in the themes list */
const_themes_iterator themesEnd() const;
/** \brief check whether the theme manager hosts any items / themes */
bool isEmpty() const;
/** \brief purge all items and themes from the ThemeManager
* \note the SvgTheme instances themselves are not scraped!
*/
void clear();
private:
itemsContainer m_itemsTable; ///< Contains a list of all item -> theme pairs
themesContainer m_themesList; ///< Contains a list of all themes
};
}
#endif
//end stepgui/svgthememanager.hpp
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment