1 /***************************************************************************
2 * Copyright (C) 2004, 2007 by Kita Developers *
3 * ikemo@users.sourceforge.jp *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 ***************************************************************************/
11 /* This class manages the DOM elements */
16 #include <dom/dom_text.h>
18 #include "libkita/datinfo.h"
19 #include "libkita/datmanager.h"
20 #include "libkita/kita_misc.h"
21 #include "libkita/kita-utf8.h"
25 DomTree::DomTree(const DOM::HTMLDocument& hdoc, const KUrl& datUrl)
31 /* create the nodes of footer, header, etc. */
36 /* get pointer of DatInfo */
37 /* Note that m_datURL is already locked in the HTMLPart. */
38 m_datInfo = DatManager(datUrl).getDatInfoPointer();
41 DomTree::~DomTree() {}
44 * This function creates DOM elements of both title and body.
45 * To show the res, call appendRes()
47 bool DomTree::createResElement(int num)
50 Q_ASSERT(m_datInfo != 0);
52 if (num < m_bufSize && m_resStatus[ num ] != HTML_NOTPARSED) {
57 if (num >= m_bufSize) {
58 /* resize buffer size */
59 if (m_bufSize == 0) m_bufSize = 100;
60 while (num >= m_bufSize) m_bufSize += 500;
62 m_titleElm.resize(m_bufSize);
63 m_bodyElm.resize(m_bufSize);
64 int statusSize = m_resStatus.count();
65 m_resStatus.resize(m_bufSize);
66 for (int i = statusSize; i < m_bufSize; i++) {
67 m_resStatus[i] = false;
69 int numSize = m_coloredNum.count();
70 m_coloredNum.resize(m_bufSize);
71 for (int i = numSize; i < m_bufSize; i++) {
72 m_coloredNum[i] = false;
77 QString titleHTML, bodyHTML;
78 m_resStatus[ num ] = m_datInfo->getHTML(num, true, titleHTML, bodyHTML);
80 if (m_resStatus[ num ] == HTML_NOTPARSED) {
84 m_titleElm[ num ] = m_hdoc.createElement("DIV");
85 m_titleElm[ num ].setAttribute("class", "res_title");
86 m_titleElm[ num ].setAttribute("id", QString::number(num));
87 m_titleElm[ num ].setInnerHTML(titleHTML);
89 m_bodyElm[ num ] = m_hdoc.createElement("DIV");
90 m_bodyElm[ num ].setAttribute("class", "res_body");
91 m_bodyElm[ num ].setAttribute("id", QString::number(num));
92 m_bodyElm[ num ].setInnerHTML(bodyHTML);
100 bool DomTree::appendRes(int num)
102 if (!createResElement(num)) return false;
104 m_hdoc.body().appendChild(m_titleElm[ num ]);
105 m_hdoc.body().appendChild(m_bodyElm[ num ]);
107 if (num > m_bottomNum) m_bottomNum = num;
115 void DomTree::redraw(bool force)
117 Q_ASSERT(m_datInfo != 0);
119 int readNum = m_datInfo->getReadNum();
121 /* don't forget to reset abone here... */
122 m_datInfo->resetAbone();
124 for (int i = 1; i <= readNum; i++) {
125 QString titleHTML, bodyHTML;
127 int oldStatus = m_resStatus[ i ];
128 m_resStatus[ i ] = m_datInfo->getHTML(i , true, titleHTML, bodyHTML);
130 if (force || oldStatus != m_resStatus[ i ]) {
131 m_titleElm[ i ].setInnerHTML(titleHTML);
132 m_bodyElm[ i ].setInnerHTML(bodyHTML);
139 * change color of number of the res which is responsed.
141 * See also DomTree::changeColorOfNumber() ,
142 * DatInfo::copyOneLineToResDat(),
143 * and DatInfo::collectResponsedRes().
145 void DomTree::changeColorOfAllResponsedNumber()
147 for (int i = 1; i <= m_bottomNum; ++i) {
148 if (m_datInfo->isResponsed(i)) {
149 changeColorOfNumber(i);
154 int DomTree::getBottomResNumber() const
160 * append footer & header
162 void DomTree::appendFooterAndHeader()
164 Q_ASSERT(m_datInfo != 0);
166 int readNum = m_datInfo->getReadNum();
167 if (!readNum) return ;
169 updateHeader(m_header);
170 updateFooter(m_footer);
172 m_hdoc.body().insertBefore(m_header, m_hdoc.body().firstChild());
173 m_hdoc.body().appendChild(m_footer);
177 * append kokomadeyonda
179 void DomTree::appendKokoyon()
181 Q_ASSERT(m_datInfo != 0);
183 int readNum = m_datInfo->getReadNum();
184 if (!readNum) return ;
186 int viewPos = m_datInfo->getViewPos();
187 if (viewPos == 0) return ;
191 if (i <= readNum) m_hdoc.body().insertBefore(m_kokoyon, m_titleElm[ i ]);
192 else m_hdoc.body().appendChild(m_kokoyon);
200 * append "A" Node to rootnode
202 void DomTree::appendAnchorNode(const DOM::Element& root, const QString& href, const QString& linkstr)
204 DOM::Element rootnode = root;
205 DOM::Element element;
207 element = rootnode.appendChild(m_hdoc.createElement("A"));
209 element.setAttribute("href", href);
210 element.appendChild(m_hdoc.createTextNode(linkstr));
219 * before: #KokomadeYonda 1- 101- 201- #ToSaigo<br><br>
220 * after : #KokomadeYonda 1- 101- 201- 301- 401- #ToSaigo<br><br>
222 void DomTree::updateHeader(DOM::Element& headerElement)
224 if (! m_datInfo) return ;
226 DOM::Element backupElement1, backupElement2, backupElement3;
227 int readNum = m_datInfo->getReadNum();
229 /* remove <a href="#tosaigo"> and <BR> */
230 backupElement1 = headerElement.removeChild(headerElement.lastChild()); /* BR */
231 backupElement2 = headerElement.removeChild(headerElement.lastChild()); /* BR */
232 backupElement3 = headerElement.removeChild(headerElement.lastChild()); /* "#tosaigo" */
234 DOM::Node node = headerElement.firstChild(); /* node is now "#kokomade_yonda" */
235 node = node.nextSibling(); /* " " */
236 node = node.nextSibling();
238 /* '1-', '101-' などのリンクを作成 */
239 for (int num = 1; num < readNum ; num += 100) {
241 QString href = QString("#%1").arg(num);
242 QString linkStr = QString("%1-").arg(num);
244 appendAnchorNode(headerElement, href, linkStr);
245 node = headerElement.appendChild(m_hdoc.createTextNode(" "));
246 node = node.nextSibling();
248 // 既にリンクが作られている場合は飛ばす
249 node = node.nextSibling();
250 if (node != 0) node = node.nextSibling();
254 /* restore <a href="#tosaigo"> and <BR> */
255 headerElement.appendChild(backupElement3); /* "#tosaigo" */
256 headerElement.appendChild(backupElement2); /* BR */
257 headerElement.appendChild(backupElement1); /* BR */
264 * before: #KokomadeYonda 1- 101- 201- #ToSaigo
265 * after : #KokomadeYonda 1- 101- 201- 301- 401- #ToSaigo
267 void DomTree::updateFooter(DOM::Element& footerElement)
269 Q_ASSERT(m_datInfo != 0);
271 DOM::Element backupElement;
272 int readNum = m_datInfo->getReadNum();
274 backupElement = footerElement.removeChild(footerElement.lastChild()); /* "#tosaigo" */
276 DOM::Node node = footerElement.firstChild(); /* node is now "#kokomade_yonda" */
277 node = node.nextSibling(); /* " " */
278 node = node.nextSibling();
280 /* '1-', '101-' などのリンクを作成 */
281 for (int num = 1; num < readNum ; num += 100) {
283 QString href = QString("#%1").arg(num);
284 QString linkStr = QString("%1-").arg(num);
286 appendAnchorNode(footerElement, href, linkStr);
287 node = footerElement.appendChild(m_hdoc.createTextNode(" "));
288 node = node.nextSibling();
290 // 既にリンクが作られている場合は飛ばす
291 node = node.nextSibling();
292 if (node != 0) node = node.nextSibling();
296 footerElement.appendChild(backupElement); /* "#tosaigo" */
302 void DomTree::createHeader()
305 DOM::Element rootnode;
307 rootnode = m_hdoc.createElement("DIV");
309 rootnode.setAttribute("kita_type", "header");
310 rootnode.setAttribute("id", "header");
312 str = QString::fromUtf8(KITAUTF8_KOKOYON);
313 appendAnchorNode(rootnode, "#kokomade_yonda", str);
314 rootnode.appendChild(m_hdoc.createTextNode(" "));
316 str = QString::fromUtf8(KITAUTF8_SAIGO);
317 appendAnchorNode(rootnode, "#tosaigo", str);
319 rootnode.appendChild(m_hdoc.createElement("BR"));
320 rootnode.appendChild(m_hdoc.createElement("BR"));
330 void DomTree::createFooter()
333 DOM::Element rootnode;
335 rootnode = m_hdoc.createElement("DIV");
337 rootnode.setAttribute("kita_type", "footer");
338 rootnode.setAttribute("id", "footer");
340 str = QString::fromUtf8(KITAUTF8_KOKOYON);
341 appendAnchorNode(rootnode, "#kokomade_yonda", str);
342 rootnode.appendChild(m_hdoc.createTextNode(" "));
344 str = QString::fromUtf8(KITAUTF8_SAIGO);
345 appendAnchorNode(rootnode, "#tosaigo", str);
352 * create kokomadeyonda node
354 void DomTree::createKokoyon()
357 DOM::Element rootnode;
359 str = QString::fromUtf8(KITAUTF8_KOKOYON2);
361 rootnode = m_hdoc.createElement("DIV");
363 rootnode.setAttribute("class", "kokoyon");
364 rootnode.setAttribute("kita_type", "kokoyon");
365 rootnode.setAttribute("id", "kokomade_yonda");
366 rootnode.appendChild(m_hdoc.createTextNode(str));
369 m_kokoyon = rootnode;
373 * change color of number
374 * specify color like this: "a.coloredLink:link{ color: red; }"
376 void DomTree::changeColorOfNumber(int num)
378 if (m_coloredNum[ num ]) return ;
380 m_coloredNum[ num ] = true;
382 DOM::Node node = m_titleElm[ num ];
383 node = node.firstChild();
385 static_cast<DOM::HTMLElement>(node).setAttribute("class", "coloredLink");