1 /*
2  For general Scribus (>=1.3.2) copyright and licensing information please refer
3  to the COPYING file provided with the program. Following this notice may exist
4  a copyright and/or license notice that predates the release of Scribus 1.3.2
5  for which a new license (GPL+exception) is in place.
6  */
7 /***************************************************************************
8 *                                                                         *
9 *   This program is free software; you can redistribute it and/or modify  *
10 *   it under the terms of the GNU General Public License as published by  *
11 *   the Free Software Foundation; either version 2 of the License, or     *
12 *   (at your option) any later version.                                   *
13 *                                                                         *
14 ***************************************************************************/
15 
16 
17 #ifndef STYLE_H
18 #define STYLE_H
19 
20 #include <cassert>
21 #include <QString>
22 #include "scfonts.h"
23 #include "scribusapi.h"
24 #include "styles/stylecontext.h"
25 #include "desaxe/saxio.h"
26 
27 /**
28  *  This is the base class for all style-like objects: CharStyles,
29  *  ParagraphStyles, LineStyles, FrameStyles, CellStyles,
30  *  FlowStyles,...
31  *  It provides a name and an inheritance mechanism which uses a Stylecontext.
32  *  Before any attribute is queried, you have to call validate(), which checks
33  *  the stored m_contextversion against the StyleContext's version and updates all
34  *  attributes if they are different.
35  */
36 class SCRIBUS_API BaseStyle : public SaxIO
37 {
38 protected:
39 	bool m_isDefaultStyle;
40 	QString m_name;
41 	const StyleContext* m_context;
42 	int m_contextversion;
43 	QString m_parent;
44 	QString m_shortcut;
45 
46 public:
47 //	static const short NOVALUE = -16000;
48 
BaseStyle()49 	BaseStyle(): m_isDefaultStyle(false), m_name(""), m_context(nullptr), m_contextversion(-1), m_parent(""), m_shortcut() {}
50 
BaseStyle(StyleContext * b,QString n)51 	BaseStyle(StyleContext* b, QString n): m_isDefaultStyle(false), m_name(n), m_context(b), m_contextversion(-1), m_parent(""), m_shortcut() {}
52 
53 	BaseStyle& operator=(const BaseStyle& o)
54 	{ //assert(typeinfo() == o.typeinfo());
55 		m_isDefaultStyle = o.m_isDefaultStyle;
56 		m_name = o.m_name;
57 //		m_context = o.m_context;
58 		m_contextversion = -1;
59 		m_parent = o.m_parent;
60 		m_shortcut = o.m_shortcut;
61 		return *this;
62 	}
63 
BaseStyle(const BaseStyle & o)64 	BaseStyle(const BaseStyle& o) : SaxIO(), m_isDefaultStyle(o.m_isDefaultStyle),m_name(o.m_name),
65 		m_context(o.m_context), m_contextversion(o.m_contextversion), m_parent(o.m_parent), m_shortcut(o.m_shortcut) {}
66 
~BaseStyle()67 	virtual ~BaseStyle()                 {}
68 
69 
70 	// this is an abstract class, so:
71 	// static const Xml_string saxxDefaultElem;
72 	template<class SUBSTYLE>
73 		static void  desaxeRules(const Xml_string& prefixPattern, desaxe::Digester& ruleset, const Xml_string& elemtag);
74 
75 	void saxxAttributes(Xml_attr& attr) const;
76 	//virtual void saxx(SaxHandler& handler, const Xml_string& elemtag) const;
77 	//virtual void saxx(SaxHandler& handler)                     const { saxx(handler, saxxDefaultElem); }
78 
79 	void setDefaultStyle(bool ids);
isDefaultStyle()80 	bool isDefaultStyle() const      { return m_isDefaultStyle; }
81 
name()82 	QString name() const             { return m_name; }
setName(const QString & n)83 	void setName(const QString& n)   { m_name = n.isEmpty() ? "" : n; }
hasName()84 	bool hasName() const             { return ! m_name.isEmpty(); }
85 
86 	QString baseName() const;
87 
88 	virtual QString displayName() const = 0;
89 
parent()90 	QString parent() const           { return m_parent; }
91 	void setParent(const QString& p);
hasParent()92 	bool hasParent() const           { return ! m_parent.isEmpty(); }
93 	const BaseStyle* parentStyle() const;
94 
95 	bool canInherit(const QString& parentName) const;
96 
97 	static const QString INHERIT_PARENT;
98 
99 	virtual void setContext(const StyleContext* context);
context()100 	const StyleContext* context() const        { return m_context; }
101 
102 	/**
103 		sets a new StyleContext if b is not nullptr and then uses the StyleContext
104 		to set all inherited attributes to their valid value.
105 	 */
106 	virtual void update(const StyleContext* b = nullptr);
107 
108 	/**
109 		Checks if this BaseStyle needs an update
110 	 */
validate()111 	inline void validate() const {
112 		if (m_context && m_contextversion != m_context->version()) {
113 			const_cast<BaseStyle*>(this)->update(m_context);
114 			assert( m_context->checkConsistency() );
115 		}
116 	}
117 
shortcut()118 	QString shortcut() const { return m_shortcut; }
setShortcut(const QString & shortcut)119 	void setShortcut(const QString &shortcut) { m_shortcut = shortcut; }
120 
121 	/**
122 		returns true if both Styles are of the same type, inherit the same attributes,
123 	    have the same parent, and agree on all attributes which are not inherited.
124 	    The StyleContext, the name and any inherited attrinutes may be different.
125 	 */
126 	virtual bool equiv(const BaseStyle& other) const = 0;
127 	/**
128 		returns true if both Styles are equivalent and have the same name.
129 	    Since the context is not tested, this does *not* ensure they will return
130 	    the same values for all attributes.
131 	 */
132 	virtual bool operator==(const BaseStyle& other) const { return name() == other.name() && equiv(other); }
133 	virtual bool operator!=(const BaseStyle& other) const { return ! ( (*this) == other ); }
134 
135 	/**
136 		resets all attributes to their defaults and makes them inherited.
137 	    name and parent are not affected.
138 	 */
139 	virtual void erase() = 0;
140 	/**
141 		if other has a parent, replace this parent with the other ones
142 	 */
applyStyle(const BaseStyle & other)143 	void applyStyle(const BaseStyle& other) {
144 		if (other.hasParent())
145 			setParent( other.parent() == INHERIT_PARENT? "" :other.parent());
146 		m_contextversion = -1;
147 	}
148 	/**
149 		if other has the same parent, remove this parent
150 	 */
eraseStyle(const BaseStyle & other)151 	void eraseStyle(const BaseStyle& other) {
152 		if (other.parent() == parent())
153 			setParent("");
154 		m_contextversion = -1;
155 	}
156 };
157 
158 #endif
159