|
1 /****************************************************************************** |
|
2 * |
|
3 * $Id: mainhandler.cpp 645 2008-08-19 13:23:22Z dimitri $ |
|
4 * |
|
5 * |
|
6 * Copyright (C) 1997-2006 by Dimitri van Heesch. |
|
7 * |
|
8 * Permission to use, copy, modify, and distribute this software and its |
|
9 * documentation under the terms of the GNU General Public License is hereby |
|
10 * granted. No representations are made about the suitability of this software |
|
11 * for any purpose. It is provided "as is" without express or implied warranty. |
|
12 * See the GNU General Public License for more details. |
|
13 * |
|
14 */ |
|
15 |
|
16 #include <qxml.h> |
|
17 #include "mainhandler.h" |
|
18 #include "compoundhandler.h" |
|
19 #include "sectionhandler.h" |
|
20 #include "graphhandler.h" |
|
21 #include "dochandler.h" |
|
22 #include "memberhandler.h" |
|
23 #include "debug.h" |
|
24 |
|
25 |
|
26 class ErrorHandler : public QXmlErrorHandler |
|
27 { |
|
28 public: |
|
29 virtual ~ErrorHandler() {} |
|
30 bool warning( const QXmlParseException & ) |
|
31 { |
|
32 return FALSE; |
|
33 } |
|
34 bool error( const QXmlParseException & ) |
|
35 { |
|
36 return FALSE; |
|
37 } |
|
38 bool fatalError( const QXmlParseException &exception ) |
|
39 { |
|
40 debug(1,"Fatal error at line %d column %d: %s\n", |
|
41 exception.lineNumber(),exception.columnNumber(), |
|
42 exception.message().data()); |
|
43 return FALSE; |
|
44 } |
|
45 QString errorString() { return ""; } |
|
46 |
|
47 private: |
|
48 QString errorMsg; |
|
49 }; |
|
50 |
|
51 //-------------------------------------------------------------------------- |
|
52 |
|
53 class CompoundEntryIterator : public ICompoundIterator, |
|
54 public QListIterator<CompoundEntry> |
|
55 { |
|
56 public: |
|
57 CompoundEntryIterator(const MainHandler *m,const QList<CompoundEntry> &list) : |
|
58 QListIterator<CompoundEntry>(list), m_mainHandler(m) {} |
|
59 virtual ~CompoundEntryIterator() {} |
|
60 |
|
61 virtual void toFirst() |
|
62 { |
|
63 QListIterator<CompoundEntry>::toFirst(); |
|
64 } |
|
65 virtual void toLast() |
|
66 { |
|
67 QListIterator<CompoundEntry>::toLast(); |
|
68 } |
|
69 virtual void toNext() |
|
70 { |
|
71 QListIterator<CompoundEntry>::operator++(); |
|
72 } |
|
73 virtual void toPrev() |
|
74 { |
|
75 QListIterator<CompoundEntry>::operator--(); |
|
76 } |
|
77 virtual ICompound *current() const |
|
78 { |
|
79 CompoundEntry *ch = QListIterator<CompoundEntry>::current(); |
|
80 return ch ? m_mainHandler->compoundById(ch->id) : 0; |
|
81 } |
|
82 virtual void release() |
|
83 { delete this; } |
|
84 |
|
85 private: |
|
86 const MainHandler *m_mainHandler; |
|
87 }; |
|
88 |
|
89 //-------------------------------------------------------------------------- |
|
90 |
|
91 MainHandler::MainHandler() : m_compoundDict(2999), m_compoundNameDict(2999), |
|
92 m_memberDict(12251), m_memberNameDict(12251), |
|
93 m_compoundsLoaded(1009) |
|
94 { |
|
95 m_compounds.setAutoDelete(TRUE); |
|
96 m_memberNameDict.setAutoDelete(TRUE); |
|
97 addStartHandler("doxygenindex"); |
|
98 addEndHandler("doxygenindex"); |
|
99 addStartHandler("compound",this,&MainHandler::startCompound); |
|
100 addEndHandler("compound"); |
|
101 addStartHandler("member",this,&MainHandler::startMember); |
|
102 addEndHandler("member",this,&MainHandler::endMember); |
|
103 addStartHandler("name",this,&MainHandler::startName); |
|
104 addEndHandler("name",this,&MainHandler::endName); |
|
105 m_curCompound = 0; |
|
106 m_insideMember = FALSE; |
|
107 } |
|
108 |
|
109 MainHandler::~MainHandler() |
|
110 { |
|
111 debug(2,"MainHandler::~MainHandler()\n"); |
|
112 } |
|
113 |
|
114 void MainHandler::startCompound(const QXmlAttributes& attrib) |
|
115 { |
|
116 m_curCompound = new CompoundEntry(257); |
|
117 m_curCompound->id = attrib.value("refid"); |
|
118 m_compounds.append(m_curCompound); |
|
119 m_compoundDict.insert(m_curCompound->id,m_curCompound); |
|
120 } |
|
121 |
|
122 void MainHandler::startName(const QXmlAttributes& /*attrib*/) |
|
123 { |
|
124 m_curString = ""; |
|
125 } |
|
126 |
|
127 void MainHandler::endName() |
|
128 { |
|
129 if (m_insideMember) |
|
130 { |
|
131 m_curMember->name = m_curString; |
|
132 } |
|
133 else |
|
134 { |
|
135 m_curCompound->name = m_curString; |
|
136 m_compoundNameDict.insert(m_curString,m_curCompound); |
|
137 } |
|
138 } |
|
139 |
|
140 void MainHandler::startMember(const QXmlAttributes& attrib) |
|
141 { |
|
142 m_insideMember = TRUE; |
|
143 m_curMember = new MemberEntry; |
|
144 m_curMember->id = attrib.value("refid"); |
|
145 m_curMember->compound = m_curCompound; |
|
146 m_memberDict.insert(m_curMember->id,m_curMember); |
|
147 } |
|
148 |
|
149 void MainHandler::endMember() |
|
150 { |
|
151 m_curCompound->memberDict.insert(m_curMember->name,m_curMember); |
|
152 QList<CompoundEntry> *cel=0; |
|
153 if ((cel=m_memberNameDict.find(m_curMember->name))==0) |
|
154 { |
|
155 cel = new QList<CompoundEntry>; |
|
156 m_memberNameDict.insert(m_curMember->name,cel); |
|
157 } |
|
158 cel->append(m_curCompound); |
|
159 m_insideMember = FALSE; |
|
160 } |
|
161 |
|
162 void MainHandler::setDebugLevel(int level) |
|
163 { |
|
164 ::setDebugLevel(level); |
|
165 } |
|
166 |
|
167 void MainHandler::dump() |
|
168 { |
|
169 QListIterator<CompoundEntry> cli(m_compounds); |
|
170 CompoundEntry *ce; |
|
171 for (cli.toFirst();(ce=cli.current());++cli) |
|
172 { |
|
173 debug(2,"compound id=`%s' name=`%s'\n",ce->id.data(),ce->name.data()); |
|
174 QDictIterator<MemberEntry> mdi(ce->memberDict); |
|
175 MemberEntry *me; |
|
176 for (mdi.toFirst();(me=mdi.current());++mdi) |
|
177 { |
|
178 debug(2," member id=`%s' name=`%s'\n",me->id.data(),me->name.data()); |
|
179 } |
|
180 } |
|
181 } |
|
182 |
|
183 bool MainHandler::readXMLDir(const char * xmlDirName) |
|
184 { |
|
185 m_xmlDirName = xmlDirName; |
|
186 QString xmlFileName=m_xmlDirName+"/index.xml"; |
|
187 QFile xmlFile(xmlFileName); |
|
188 //printf("Trying %s xmlFile.exists()=%d isReadable()=%d\n", |
|
189 // xmlFileName.data(),xmlFile.exists(),xmlFile.isReadable()); |
|
190 if (xmlFile.exists()) |
|
191 { |
|
192 ErrorHandler errorHandler; |
|
193 QXmlInputSource source( xmlFile ); |
|
194 QXmlSimpleReader reader; |
|
195 reader.setContentHandler( this ); |
|
196 reader.setErrorHandler( &errorHandler ); |
|
197 reader.parse( source ); |
|
198 dump(); |
|
199 return TRUE; |
|
200 } |
|
201 return FALSE; |
|
202 } |
|
203 |
|
204 ICompoundIterator *MainHandler::compounds() const |
|
205 { |
|
206 return new CompoundEntryIterator(this,m_compounds); |
|
207 } |
|
208 |
|
209 ICompound *MainHandler::compoundById(const char *id) const |
|
210 { |
|
211 QString ids = id; |
|
212 if (ids.isEmpty()) return 0; |
|
213 CompoundHandler *ch = m_compoundsLoaded[ids]; |
|
214 if (ch) // compound already in memory |
|
215 { |
|
216 ch->addref(); // returning alias -> increase reference counter |
|
217 return ch->toICompound(); |
|
218 } |
|
219 CompoundEntry *ce = m_compoundDict.find(ids); |
|
220 if (ce==0) return 0; // id not found |
|
221 // create and load a new compound |
|
222 ch = new CompoundHandler(m_xmlDirName); |
|
223 if (!ch->parseXML(id)) |
|
224 { |
|
225 // compound could not be initialized. |
|
226 delete ch; |
|
227 return 0; |
|
228 } |
|
229 |
|
230 // we disregard the constness here, because the object stays conceptually |
|
231 // unchanged. |
|
232 MainHandler *that = (MainHandler *)this; |
|
233 ch->initialize(that); |
|
234 //printf("loading compound %s in memory\n",id); |
|
235 that->m_compoundsLoaded.insert(id,ch); |
|
236 return ch->toICompound(); |
|
237 } |
|
238 |
|
239 void MainHandler::unloadCompound(CompoundHandler *ch) |
|
240 { |
|
241 //printf("unloading compound %s from memory\n",ch->id()->latin1()); |
|
242 bool result = m_compoundsLoaded.remove(ch->id()->latin1()); |
|
243 if (!result) debug(1,"Failed to unload component!\n"); |
|
244 } |
|
245 |
|
246 ICompound *MainHandler::compoundByName(const char *name) const |
|
247 { |
|
248 QString nameStr = name; |
|
249 if (nameStr.isEmpty()) return 0; |
|
250 CompoundEntry *ce = m_compoundNameDict[name]; |
|
251 if (ce==0) return 0; // name not found |
|
252 return compoundById(ce->id); |
|
253 } |
|
254 |
|
255 ICompound *MainHandler::memberById(const char *id) const |
|
256 { |
|
257 QString ids = id; |
|
258 if (ids.isEmpty()) return 0; |
|
259 MemberEntry *me = m_memberDict[id]; |
|
260 if (me==0) return 0; // id not found |
|
261 return compoundById(me->compound->id); |
|
262 } |
|
263 |
|
264 ICompoundIterator *MainHandler::memberByName(const char *name) const |
|
265 { |
|
266 QString nameStr = name; |
|
267 if (nameStr.isEmpty()) return 0; |
|
268 QList<CompoundEntry> *cel = m_memberNameDict[name]; |
|
269 if (cel==0) return 0; // name not found |
|
270 return new CompoundEntryIterator(this,*cel); |
|
271 } |
|
272 |
|
273 IDoxygen *createObjectModel() |
|
274 { |
|
275 compoundhandler_init(); |
|
276 sectionhandler_init(); |
|
277 memberhandler_init(); |
|
278 dochandler_init(); |
|
279 graphhandler_init(); |
|
280 return new MainHandler; |
|
281 } |
|
282 |
|
283 void MainHandler::release() |
|
284 { |
|
285 //printf("MainHandler::release()\n"); |
|
286 QDictIterator<CompoundHandler> chi(m_compoundsLoaded); |
|
287 CompoundHandler *ch; |
|
288 for (chi.toFirst();(ch=chi.current());++chi) |
|
289 { |
|
290 debug(1,"Compound %s not released\n",ch->name()->latin1()); |
|
291 } |
|
292 graphhandler_exit(); |
|
293 dochandler_exit(); |
|
294 memberhandler_exit(); |
|
295 sectionhandler_exit(); |
|
296 compoundhandler_exit(); |
|
297 delete this; |
|
298 } |
|
299 |