1 /***************************************************************************
2 * Copyright (C) 2004 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 */
14 #include <dom/html_element.h>
15 #include <dom/dom_text.h>
17 #include "kitadomtree.h"
18 #include "libkita/kitaconfig.h"
19 #include "libkita/datmanager.h"
20 #include "libkita/datinfo.h"
21 #include "libkita/kita-utf8.h"
22 #include "libkita/kita_misc.h"
25 /*---------------------------------------------------------------*/
26 /*---------------------------------------------------------------*/
29 KitaDomTree::KitaDomTree( const DOM::HTMLDocument& hdoc, const KURL& datURL )
33 m_templateNum = 20; /* default number of templates */
35 /*-----------------------------*/
42 /* create the nodes of footer, header, etc. */
44 createFooterOrHeader( "footer" );
45 createFooterOrHeader( "header" );
49 /* get pointer of DatInfo */
50 /* Note that m_datURL is already locked in the KitaHTMLPart. */
51 m_datInfo = Kita::DatManager::getDatInfoPointer( datURL );
55 KitaDomTree::~KitaDomTree() {}
59 This function creates DOM elements of both title and body.
60 To show the res, call appendRes(). . */ /* public */
62 bool KitaDomTree::createResElement( int num )
65 const int delta = 500;
67 /*---------------------------------*/
69 if ( ! m_datInfo ) return FALSE;
70 if ( m_hdoc == NULL ) return FALSE;
71 if ( num <= 0 ) return FALSE;
73 if ( num < m_bufLng ) {
74 if ( m_resStatus[ num ] != KITA_HTML_NOTPARSED ) return TRUE; /* already parsed */
76 /* resize buffer size */
79 if ( m_bufLng == 0 ) m_bufLng = mrg;
80 while ( num >= m_bufLng ) m_bufLng += delta;
82 m_titleElm.resize( m_bufLng );
83 m_bodyElm.resize( m_bufLng );
84 m_resshown.resize( m_bufLng, FALSE );
85 m_resStatus.resize( m_bufLng, KITA_HTML_NOTPARSED );
86 m_coloredNum.resize( m_bufLng, FALSE );
90 QString titleHTML, bodyHTML;
91 m_resStatus[ num ] = m_datInfo->getHTML( num, TRUE, titleHTML, bodyHTML );
92 if ( m_resStatus[ num ] == KITA_HTML_NOTPARSED ) return FALSE;
94 m_titleElm[ num ] = m_hdoc.createElement( "DIV" );
95 m_titleElm[ num ].setAttribute( "class", "res_title" );
96 m_titleElm[ num ].setAttribute( "id", QString().setNum( num ) );
97 m_titleElm[ num ].setInnerHTML( titleHTML );
99 m_bodyElm[ num ] = m_hdoc.createElement( "DIV" );
100 m_bodyElm[ num ].setAttribute( "class", "res_body" );
101 m_bodyElm[ num ].setAttribute( "id", QString().setNum( num ) );
102 m_bodyElm[ num ].setInnerHTML( bodyHTML );
104 #if KDE_IS_VERSION( 3, 2, 0 )
106 if ( KitaConfig::showAA() ) {
108 /* clear text in the span */
109 DOM::Node tmpnode = m_bodyElm[ num ].firstChild().firstChild();
110 while ( !tmpnode.isNull() ) {
111 if ( tmpnode.nodeName().string() == "span" ) {
112 if ( !tmpnode.firstChild().isNull() ) tmpnode.firstChild().setNodeValue( "" );
115 tmpnode = tmpnode.nextSibling();
125 /* append the response */ /* public */
126 bool KitaDomTree::appendRes( int num )
128 if ( !createResElement( num ) ) return FALSE;
130 m_hdoc.body().appendChild( m_titleElm[ num ] );
131 m_hdoc.body().appendChild( m_bodyElm[ num ] );
132 m_resshown[ num ] = TRUE;
134 if ( num < m_topNum ) m_topNum = num;
135 if ( num > m_bottomNum ) m_bottomNum = num;
136 if ( m_topNum <= m_templateNum ) m_topNum = 1;
144 /* redraw all */ /* public */
145 void KitaDomTree::redraw( bool force )
147 if ( ! m_datInfo ) return ;
148 if ( m_hdoc == NULL ) return ;
149 int readNum = m_datInfo->getReadNum();
151 /* don't forget to reset abone here... */
152 m_datInfo->resetAbone();
154 for ( int i = 1; i <= readNum; i++ ) {
156 if ( !m_resshown[ i ] ) continue;
158 QString titleHTML, bodyHTML;
159 int oldStatus = m_resStatus[ i ];
160 m_resStatus[ i ] = m_datInfo->getHTML( i , TRUE, titleHTML, bodyHTML );
162 if ( force || oldStatus != m_resStatus[ i ] ) {
164 m_titleElm[ i ].setInnerHTML( titleHTML );
165 m_bodyElm[ i ].setInnerHTML( bodyHTML );
171 /* change color of number of the res which is responsed. */
172 /* See also KitaDomTree::changeColorOfNumber() ,
173 DatInfo::copyOneLineToResDat(),
174 and DatInfo::collectResponsedRes(). */ /* public */
175 void KitaDomTree::changeColorOfAllResponsedNumber()
177 for ( int i = 1; i <= m_bottomNum; ++i ) {
179 if ( m_resshown[ i ] && m_datInfo->isResponsed( i ) ) changeColorOfNumber( i );
185 /*-----------------------------------------------------------------*/
187 /* public information */
190 const bool KitaDomTree::isResShown( int num ) const
192 return m_resshown[ QMIN( num, m_bufLng - 1 ) ];
196 const int KitaDomTree::getTopResNumber() const
202 const int KitaDomTree::getBottomResNumber() const
208 const int KitaDomTree::getTemplateNumber() const
210 return m_templateNum;
214 const bool KitaDomTree::isMae100Shown() const
216 if ( m_topNum <= m_templateNum ) return FALSE;
223 /*---------------------------------------------------------------------------*/
224 /* public functions for header Node, footer Node, kokomadeyonda Node, etc... */
227 /* append templates at the head of thread */ /* public */
228 void KitaDomTree::appendTemplate( int tmpNum )
230 if ( tmpNum > m_templateNum ) m_templateNum = tmpNum;
232 for ( int i = 1; i <= m_templateNum; i++ ) {
234 if ( !createResElement( i ) ) continue;
236 m_hdoc.body().appendChild( m_titleElm[ i ] );
237 m_hdoc.body().appendChild( m_bodyElm[ i ] );
238 m_resshown[ i ] = TRUE;
241 if ( m_topNum <= m_templateNum ) m_topNum = 1;
245 /* append footer & header */ /* public */
246 void KitaDomTree::appendFooterAndHeader()
248 if ( ! m_datInfo ) return ;
249 if ( m_hdoc == NULL ) return ;
251 int readNum = m_datInfo->getReadNum();
252 if ( !readNum ) return ;
254 if ( readNum > m_headerMaxNum + 100 ) {
255 updateFooterOrHeader( m_header, "header" );
256 updateFooterOrHeader( m_footer, "footer" );
259 m_hdoc.body().insertBefore( m_header, m_hdoc.body().firstChild() );
260 m_hdoc.body().appendChild( m_footer );
265 /* append kokomadeyonda & tugi 100 & mae 100*/ /* public */
266 void KitaDomTree::appendKokoyon()
268 if ( ! m_datInfo ) return ;
269 if ( m_hdoc == NULL ) return ;
271 int readNum = m_datInfo->getReadNum();
272 if ( !readNum ) return ;
274 int viewPos = m_datInfo->getViewPos();
276 || ( viewPos > m_templateNum && viewPos < m_topNum )
277 || viewPos > m_bottomNum ) return ;
280 while ( !m_resshown[ i ] && i <= readNum ) i++;
282 if ( i <= readNum ) m_hdoc.body().insertBefore( m_kokoyon, m_titleElm[ i ] );
283 else m_hdoc.body().appendChild( m_kokoyon );
288 void KitaDomTree::appendTugi100()
290 if ( ! m_datInfo ) return ;
291 if ( m_hdoc == NULL ) return ;
293 int readNum = m_datInfo->getReadNum();
294 if ( !readNum ) return ;
296 if ( m_bottomNum == readNum ) {
301 m_hdoc.body().appendChild( m_tugi100 );
305 void KitaDomTree::removeTugi100()
307 if ( ! m_datInfo ) return ;
308 if ( m_hdoc == NULL ) return ;
310 if ( m_tugi100.parentNode() == m_hdoc.body() ) m_hdoc.body().removeChild( m_tugi100 );
315 void KitaDomTree::appendMae100()
317 if ( ! m_datInfo ) return ;
318 if ( m_hdoc == NULL ) return ;
320 int readNum = m_datInfo->getReadNum();
321 if ( !readNum ) return ;
323 if ( m_topNum <= m_templateNum ) {
329 if ( i > readNum ) return ;
330 while ( !m_resshown[ i ] && i <= readNum ) i++;
332 if ( i <= readNum ) {
333 m_hdoc.body().insertBefore( m_mae100, m_titleElm[ i ] );
335 m_hdoc.body().appendChild( m_mae100 );
340 void KitaDomTree::removeMae100()
342 if ( ! m_datInfo ) return ;
343 if ( m_hdoc == NULL ) return ;
345 if ( !m_mae100.parentNode().isNull() ) m_mae100.parentNode().removeChild( m_mae100 );
349 /* create & append comment node */ /* public */
350 void KitaDomTree::createCommentNode( const QString& comment, const QString& idstr,
355 if ( m_hdoc == NULL ) return ;
357 DOM::Element rootnode;
359 rootnode = m_hdoc.createElement( "DIV" );
361 for ( int i = 0; i < beforeBR; i++ )
362 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
363 rootnode.setAttribute( "kita_type", "comment" );
364 rootnode.setAttribute( "id", idstr );
365 rootnode.appendChild( m_hdoc.createTextNode( comment ) );
366 for ( int i = 0; i < afterBR; i++ )
367 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
371 if ( m_hdoc.body().firstChild() != NULL ) {
372 m_hdoc.body().insertBefore( rootnode, m_hdoc.body().firstChild() );
377 m_hdoc.body().appendChild( rootnode );
381 /* create belt node */ /* public */
382 void KitaDomTree::createBeltNode( const QString& idstr )
384 DOM::Element rootnode;
386 QString style = "background-color: #CCCCCC; text-align: center";
388 rootnode = m_hdoc.createElement( "DIV" );
390 rootnode.setAttribute( "style", style );
391 rootnode.setAttribute( "id", idstr );
392 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
395 m_hdoc.body().appendChild( rootnode );
399 /*--------------------------------------------------------*/
401 /* private functions */
404 /* append "A" Node to rootnode */ /* private */
405 void KitaDomTree::appendANode( DOM::Element rootnode, const QString& linkstr, const QString& comment )
407 if ( m_hdoc == NULL ) return ;
410 tmpelm = rootnode.appendChild( m_hdoc.createElement( "A" ) );
412 tmpelm.setAttribute( "href", linkstr );
413 tmpelm.appendChild( m_hdoc.createTextNode( comment ) );
418 /* update footer or header No */ /* private */
419 void KitaDomTree::updateFooterOrHeader(
420 DOM::Element& targetelm, /* = m_header or m_footer */
421 QString strType /* = "header" or "footer" */
424 if ( ! m_datInfo ) return ;
425 if ( m_hdoc == NULL ) return ;
426 if ( strType != "header" && strType != "footer" ) return ;
428 DOM::Element bkupElm1, bkupElm2, bkupElm3;
429 int readNum = m_datInfo->getReadNum();
431 /* remove < a href="#tosaigo"> and <BR> */
432 if ( strType == "header" ) {
433 bkupElm1 = targetelm.removeChild( targetelm.lastChild() ); /* BR */
434 bkupElm2 = targetelm.removeChild( targetelm.lastChild() ); /* BR */
435 bkupElm3 = targetelm.removeChild( targetelm.lastChild() ); /* "#tosaigo" */
436 } else { /* "footer" */
437 bkupElm1 = targetelm.removeChild( targetelm.lastChild() ); /* "#tosaigo" */
440 DOM::Node node = targetelm.firstChild(); /* node is now "#kokomade_yonda" */
441 node = node.nextSibling(); /* " " */
442 node = node.nextSibling(); /* "#zenbu" */
443 node = node.nextSibling(); /* " " */
444 node = node.nextSibling();
446 /* append new "A" nodes */
447 for ( int num = 1; num < readNum ; num += 100 ) {
449 if ( node == NULL ) {
450 QString linkstr = QString( "#%1" ).arg( num );
451 appendANode( targetelm, linkstr, QString().setNum( num ) + "-" );
452 node = targetelm.appendChild( m_hdoc.createTextNode( " " ) );
453 node = node.nextSibling();
455 m_headerMaxNum = num;
457 node = node.nextSibling();
458 if ( node != NULL ) node = node.nextSibling();
462 /* append < a href="#tosaigo"> and <BR> */
463 if ( strType == "header" ) {
464 targetelm.appendChild( bkupElm3 ); /* "#tosaigo" */
465 targetelm.appendChild( bkupElm2 ); /* BR */
466 targetelm.appendChild( bkupElm1 ); /* BR */
467 } else { /* "footer" */
468 targetelm.appendChild( bkupElm1 ); /* "#tosaigo" */
473 /* create footer or header node */ /* private */
474 void KitaDomTree::createFooterOrHeader(
475 QString strType /* = "header" or "footer" */
478 if ( m_hdoc == NULL ) return ;
479 if ( strType != "header" && strType != "footer" ) return ;
482 DOM::Element rootnode, tmpelm;
484 rootnode = m_hdoc.createElement( "DIV" );
486 rootnode.setAttribute( "kita_type", strType );
487 rootnode.setAttribute( "id", strType );
489 str = Kita::utf8ToUnicode( KITAUTF8_KOKOYON );
490 appendANode( rootnode, "#kokomade_yonda", str );
491 rootnode.appendChild( m_hdoc.createTextNode( " " ) );
493 str = Kita::utf8ToUnicode( KITAUTF8_ZENBU );
494 appendANode( rootnode, "#zenbu", str );
495 rootnode.appendChild( m_hdoc.createTextNode( " " ) );
497 str = Kita::utf8ToUnicode( KITAUTF8_SAIGO );
498 appendANode( rootnode, "#tosaigo", str );
500 if ( strType == "header" ) {
501 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
502 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
506 if ( strType == "header" ) m_header = rootnode;
507 else m_footer = rootnode;
513 /* create kokomadeyonda node */ /* private */
514 void KitaDomTree::createKokoyon()
517 DOM::Element rootnode;
519 str = Kita::utf8ToUnicode( KITAUTF8_KOKOYON2 );
521 rootnode = m_hdoc.createElement( "DIV" );
523 rootnode.setAttribute( "class", "kokoyon" );
524 rootnode.setAttribute( "kita_type", "kokoyon" );
525 rootnode.setAttribute( "id", "kokomade_yonda" );
526 rootnode.appendChild( m_hdoc.createTextNode( str ) );
529 m_kokoyon = rootnode;
534 /* create tugi 100 node */ /* private */
535 void KitaDomTree::createTugi100()
538 DOM::Element rootnode;
540 style = "text-align: center";
542 rootnode = m_hdoc.createElement( "DIV" );
544 rootnode.setAttribute( "kita_type", "tugi100" );
545 rootnode.setAttribute( "id", "tugi100" );
546 rootnode.setAttribute( "style", style );
548 str = Kita::utf8ToUnicode( KITAUTF8_TUGI100 );
549 appendANode( rootnode, "#tugi100", str );
551 rootnode.appendChild( m_hdoc.createTextNode( " " ) );
553 str = Kita::utf8ToUnicode( KITAUTF8_ZENBUNOKORI );
554 appendANode( rootnode, "#nokori", str );
556 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
557 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
560 m_tugi100 = rootnode;
565 /* create mae 100 (template) node */ /* mae 100 */
566 void KitaDomTree::createMae100()
569 DOM::Element rootnode;
571 style = "text-align: center";
573 rootnode = m_hdoc.createElement( "DIV" );
575 rootnode.setAttribute( "kita_type", "mae100" );
576 rootnode.setAttribute( "id", "mae100" );
577 rootnode.setAttribute( "style", style );
580 QString tugi100 = Kita::utf8ToUnicode( KITAUTF8_TUGI100 );
581 appendANode( rootnode, "#tmp100", tugi100 );
584 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
585 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
588 style = "background-color: #CCCCCC; text-align: center";
589 DOM::Element divElement = rootnode.appendChild( m_hdoc.createElement( "DIV" ) );
591 divElement.setAttribute( "style", style );
592 QString templateStr = Kita::utf8ToUnicode( KITAUTF8_TEMPLATE );
593 divElement.appendChild( m_hdoc.createTextNode( templateStr ) );
597 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
600 QString mae100 = Kita::utf8ToUnicode( KITAUTF8_MAE100 );
601 appendANode( rootnode, "#mae100", mae100 );
604 rootnode.appendChild( m_hdoc.createTextNode( " " ) );
607 QString zenbumae = Kita::utf8ToUnicode( KITAUTF8_ZENBUMAE );
608 appendANode( rootnode, "#maezenbu", zenbumae );
611 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
612 rootnode.appendChild( m_hdoc.createElement( "BR" ) );
618 /* change color of number */
620 specify color like this: "a.coloredLink:link{ color: red; }" */ /* private */
622 void KitaDomTree::changeColorOfNumber( int num )
624 if ( ! m_datInfo ) return ;
625 if ( m_hdoc == NULL ) return ;
626 if ( m_coloredNum[ num ] ) return ;
627 if ( !m_resshown[ num ] ) return ;
629 m_coloredNum[ num ] = TRUE;
630 DOM::Node node = m_titleElm[ num ];
631 node = node.firstChild();
632 while ( node.nodeName().string() != "a" ) node = node.firstChild(); /* table tag is used. */
634 static_cast< DOM::HTMLElement> ( node ).setAttribute( "class", "coloredLink" );