OSDN Git Service

reformat
[kita/kita.git] / kita / src / part / kitadomtree.cpp
1 /***************************************************************************
2 *   Copyright (C) 2004 by Kita Developers                                 *
3 *   ikemo@users.sourceforge.jp                                            *
4 *                                                                         *
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 ***************************************************************************/
10
11 /* This class manages the DOM elements  */
12
13 #include <kurl.h>
14 #include <dom/html_element.h>
15 #include <dom/dom_text.h>
16
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"
23
24
25 /*---------------------------------------------------------------*/
26 /*---------------------------------------------------------------*/
27
28
29 KitaDomTree::KitaDomTree( const DOM::HTMLDocument& hdoc, const KURL& datURL )
30 {
31     /* config */
32
33     m_templateNum = 20; /* default number of templates */
34
35     /*-----------------------------*/
36
37     m_hdoc = hdoc;
38     m_bufLng = 0;
39     m_topNum = 65535;
40     m_bottomNum = 0;
41
42     /* create the nodes of footer, header, etc. */
43     createKokoyon();
44     createFooterOrHeader( "footer" );
45     createFooterOrHeader( "header" );
46     createTugi100();
47     createMae100();
48
49     /* get pointer of DatInfo */
50     /* Note that m_datURL is already locked in the KitaHTMLPart. */
51     m_datInfo = Kita::DatManager::getDatInfoPointer( datURL );
52 }
53
54
55 KitaDomTree::~KitaDomTree() {}
56
57
58 /*
59   This function creates DOM elements of both title and body.
60   To show the res, call appendRes().    .                     */ /* public */
61
62 bool KitaDomTree::createResElement( int num )
63 {
64     const int mrg = 100;
65     const int delta = 500;
66
67     /*---------------------------------*/
68
69     if ( ! m_datInfo ) return FALSE;
70     if ( m_hdoc == NULL ) return FALSE;
71     if ( num <= 0 ) return FALSE;
72
73     if ( num < m_bufLng ) {
74         if ( m_resStatus[ num ] != KITA_HTML_NOTPARSED ) return TRUE; /* already parsed */
75     }
76     /* resize buffer size */
77     else {
78
79         if ( m_bufLng == 0 ) m_bufLng = mrg;
80         while ( num >= m_bufLng ) m_bufLng += delta;
81
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 );
87     }
88
89     /* cleate elements */
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;
93
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 );
98
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 );
103
104 #if KDE_IS_VERSION( 3, 2, 0 )
105 #else
106     if ( KitaConfig::showAA() ) {
107
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( "" );
113             }
114
115             tmpnode = tmpnode.nextSibling();
116         }
117     }
118 #endif
119
120     return TRUE;
121 }
122
123
124
125 /* append the response */ /* public */
126 bool KitaDomTree::appendRes( int num )
127 {
128     if ( !createResElement( num ) ) return FALSE;
129
130     m_hdoc.body().appendChild( m_titleElm[ num ] );
131     m_hdoc.body().appendChild( m_bodyElm[ num ] );
132     m_resshown[ num ] = TRUE;
133
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;
137
138     return TRUE;
139 }
140
141
142
143
144 /* redraw all */ /* public */
145 void KitaDomTree::redraw( bool force )
146 {
147     if ( ! m_datInfo ) return ;
148     if ( m_hdoc == NULL ) return ;
149     int readNum = m_datInfo->getReadNum();
150
151     /* don't forget to reset abone here... */
152     m_datInfo->resetAbone();
153
154     for ( int i = 1; i <= readNum; i++ ) {
155
156         if ( !m_resshown[ i ] ) continue;
157
158         QString titleHTML, bodyHTML;
159         int oldStatus = m_resStatus[ i ];
160         m_resStatus[ i ] = m_datInfo->getHTML( i , TRUE, titleHTML, bodyHTML );
161
162         if ( force || oldStatus != m_resStatus[ i ] ) {
163
164             m_titleElm[ i ].setInnerHTML( titleHTML );
165             m_bodyElm[ i ].setInnerHTML( bodyHTML );
166         }
167     }
168 }
169
170
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()
176 {
177     for ( int i = 1; i <= m_bottomNum; ++i ) {
178
179         if ( m_resshown[ i ] && m_datInfo->isResponsed( i ) ) changeColorOfNumber( i );
180     }
181 }
182
183
184
185 /*-----------------------------------------------------------------*/
186
187 /* public information */
188
189 /* public */
190 const bool KitaDomTree::isResShown( int num ) const
191 {
192     return m_resshown[ QMIN( num, m_bufLng - 1 ) ];
193 }
194
195 /* public */
196 const int KitaDomTree::getTopResNumber() const
197 {
198     return m_topNum;
199 }
200
201 /* public */
202 const int KitaDomTree::getBottomResNumber() const
203 {
204     return m_bottomNum;
205 }
206
207 /* public */
208 const int KitaDomTree::getTemplateNumber() const
209 {
210     return m_templateNum;
211 }
212
213 /* public */
214 const bool KitaDomTree::isMae100Shown() const
215 {
216     if ( m_topNum <= m_templateNum ) return FALSE;
217
218     return TRUE;
219 }
220
221
222
223 /*---------------------------------------------------------------------------*/
224 /* public functions for header Node, footer Node, kokomadeyonda Node, etc... */
225
226
227 /* append templates at the head of thread */ /* public */
228 void KitaDomTree::appendTemplate( int tmpNum )
229 {
230     if ( tmpNum > m_templateNum ) m_templateNum = tmpNum;
231
232     for ( int i = 1; i <= m_templateNum; i++ ) {
233
234         if ( !createResElement( i ) ) continue;
235
236         m_hdoc.body().appendChild( m_titleElm[ i ] );
237         m_hdoc.body().appendChild( m_bodyElm[ i ] );
238         m_resshown[ i ] = TRUE;
239     }
240
241     if ( m_topNum <= m_templateNum ) m_topNum = 1;
242 }
243
244
245 /* append footer & header  */ /* public */
246 void KitaDomTree::appendFooterAndHeader()
247 {
248     if ( ! m_datInfo ) return ;
249     if ( m_hdoc == NULL ) return ;
250
251     int readNum = m_datInfo->getReadNum();
252     if ( !readNum ) return ;
253
254     if ( readNum > m_headerMaxNum + 100 ) {
255         updateFooterOrHeader( m_header, "header" );
256         updateFooterOrHeader( m_footer, "footer" );
257     }
258
259     m_hdoc.body().insertBefore( m_header, m_hdoc.body().firstChild() );
260     m_hdoc.body().appendChild( m_footer );
261 }
262
263
264
265 /* append kokomadeyonda & tugi 100 & mae 100*/ /* public */
266 void KitaDomTree::appendKokoyon()
267 {
268     if ( ! m_datInfo ) return ;
269     if ( m_hdoc == NULL ) return ;
270
271     int readNum = m_datInfo->getReadNum();
272     if ( !readNum ) return ;
273
274     int viewPos = m_datInfo->getViewPos();
275     if ( viewPos == 0
276             || ( viewPos > m_templateNum && viewPos < m_topNum )
277             || viewPos > m_bottomNum ) return ;
278
279     int i = viewPos + 1;
280     while ( !m_resshown[ i ] && i <= readNum ) i++;
281
282     if ( i <= readNum ) m_hdoc.body().insertBefore( m_kokoyon, m_titleElm[ i ] );
283     else m_hdoc.body().appendChild( m_kokoyon );
284 }
285
286
287 /* public */
288 void KitaDomTree::appendTugi100()
289 {
290     if ( ! m_datInfo ) return ;
291     if ( m_hdoc == NULL ) return ;
292
293     int readNum = m_datInfo->getReadNum();
294     if ( !readNum ) return ;
295
296     if ( m_bottomNum == readNum ) {
297         removeTugi100();
298         return ;
299     }
300
301     m_hdoc.body().appendChild( m_tugi100 );
302 }
303
304 /* public */
305 void KitaDomTree::removeTugi100()
306 {
307     if ( ! m_datInfo ) return ;
308     if ( m_hdoc == NULL ) return ;
309
310     if ( m_tugi100.parentNode() == m_hdoc.body() ) m_hdoc.body().removeChild( m_tugi100 );
311 }
312
313
314 /* public */
315 void KitaDomTree::appendMae100()
316 {
317     if ( ! m_datInfo ) return ;
318     if ( m_hdoc == NULL ) return ;
319
320     int readNum = m_datInfo->getReadNum();
321     if ( !readNum ) return ;
322
323     if ( m_topNum <= m_templateNum ) {
324         removeMae100();
325         return ;
326     }
327
328     int i = m_topNum;
329     if ( i > readNum ) return ;
330     while ( !m_resshown[ i ] && i <= readNum ) i++;
331
332     if ( i <= readNum ) {
333         m_hdoc.body().insertBefore( m_mae100, m_titleElm[ i ] );
334     } else {
335         m_hdoc.body().appendChild( m_mae100 );
336     }
337 }
338
339 /* public */
340 void KitaDomTree::removeMae100()
341 {
342     if ( ! m_datInfo ) return ;
343     if ( m_hdoc == NULL ) return ;
344
345     if ( !m_mae100.parentNode().isNull() ) m_mae100.parentNode().removeChild( m_mae100 );
346 }
347
348
349 /* create & append comment node */ /* public */
350 void KitaDomTree::createCommentNode( const QString& comment, const QString& idstr,
351                                      int beforeBR,
352                                      int afterBR,
353                                      bool binsert )
354 {
355     if ( m_hdoc == NULL ) return ;
356
357     DOM::Element rootnode;
358
359     rootnode = m_hdoc.createElement( "DIV" );
360     {
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" ) );
368     }
369
370     if ( binsert ) {
371         if ( m_hdoc.body().firstChild() != NULL ) {
372             m_hdoc.body().insertBefore( rootnode, m_hdoc.body().firstChild() );
373             return ;
374         }
375     }
376
377     m_hdoc.body().appendChild( rootnode );
378 }
379
380
381 /* create belt node */ /* public */
382 void KitaDomTree::createBeltNode( const QString& idstr )
383 {
384     DOM::Element rootnode;
385
386     QString style = "background-color: #CCCCCC; text-align: center";
387
388     rootnode = m_hdoc.createElement( "DIV" );
389     {
390         rootnode.setAttribute( "style", style );
391         rootnode.setAttribute( "id", idstr );
392         rootnode.appendChild( m_hdoc.createElement( "BR" ) );
393     }
394
395     m_hdoc.body().appendChild( rootnode );
396 }
397
398
399 /*--------------------------------------------------------*/
400
401 /* private functions */
402
403
404 /* append "A" Node to rootnode */ /* private */
405 void KitaDomTree::appendANode( DOM::Element rootnode, const QString& linkstr, const QString& comment )
406 {
407     if ( m_hdoc == NULL ) return ;
408
409     DOM::Element tmpelm;
410     tmpelm = rootnode.appendChild( m_hdoc.createElement( "A" ) );
411     {
412         tmpelm.setAttribute( "href", linkstr );
413         tmpelm.appendChild( m_hdoc.createTextNode( comment ) );
414     }
415 }
416
417
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" */
422 )
423 {
424     if ( ! m_datInfo ) return ;
425     if ( m_hdoc == NULL ) return ;
426     if ( strType != "header" && strType != "footer" ) return ;
427
428     DOM::Element bkupElm1, bkupElm2, bkupElm3;
429     int readNum = m_datInfo->getReadNum();
430
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" */
438     }
439
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();
445
446     /* append new "A" nodes */
447     for ( int num = 1; num < readNum ; num += 100 ) {
448
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();
454
455             m_headerMaxNum = num;
456         } else {
457             node = node.nextSibling();
458             if ( node != NULL ) node = node.nextSibling();
459         }
460     }
461
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" */
469     }
470 }
471
472
473 /* create footer or header node   */ /* private */
474 void KitaDomTree::createFooterOrHeader(
475     QString strType /* = "header" or "footer" */
476 )
477 {
478     if ( m_hdoc == NULL ) return ;
479     if ( strType != "header" && strType != "footer" ) return ;
480
481     QString str;
482     DOM::Element rootnode, tmpelm;
483
484     rootnode = m_hdoc.createElement( "DIV" );
485     {
486         rootnode.setAttribute( "kita_type", strType );
487         rootnode.setAttribute( "id", strType );
488
489         str = Kita::utf8ToUnicode( KITAUTF8_KOKOYON );
490         appendANode( rootnode, "#kokomade_yonda", str );
491         rootnode.appendChild( m_hdoc.createTextNode( " " ) );
492
493         str = Kita::utf8ToUnicode( KITAUTF8_ZENBU );
494         appendANode( rootnode, "#zenbu", str );
495         rootnode.appendChild( m_hdoc.createTextNode( " " ) );
496
497         str = Kita::utf8ToUnicode( KITAUTF8_SAIGO );
498         appendANode( rootnode, "#tosaigo", str );
499
500         if ( strType == "header" ) {
501             rootnode.appendChild( m_hdoc.createElement( "BR" ) );
502             rootnode.appendChild( m_hdoc.createElement( "BR" ) );
503         }
504     }
505
506     if ( strType == "header" ) m_header = rootnode;
507     else m_footer = rootnode;
508
509     m_headerMaxNum = 0;
510 }
511
512
513 /* create kokomadeyonda node */ /* private */
514 void KitaDomTree::createKokoyon()
515 {
516     QString str, style;
517     DOM::Element rootnode;
518
519     str = Kita::utf8ToUnicode( KITAUTF8_KOKOYON2 );
520
521     rootnode = m_hdoc.createElement( "DIV" );
522     {
523         rootnode.setAttribute( "class", "kokoyon" );
524         rootnode.setAttribute( "kita_type", "kokoyon" );
525         rootnode.setAttribute( "id", "kokomade_yonda" );
526         rootnode.appendChild( m_hdoc.createTextNode( str ) );
527     }
528
529     m_kokoyon = rootnode;
530 }
531
532
533
534 /* create tugi 100 node  */ /* private */
535 void KitaDomTree::createTugi100()
536 {
537     QString str, style;
538     DOM::Element rootnode;
539
540     style = "text-align: center";
541
542     rootnode = m_hdoc.createElement( "DIV" );
543     {
544         rootnode.setAttribute( "kita_type", "tugi100" );
545         rootnode.setAttribute( "id", "tugi100" );
546         rootnode.setAttribute( "style", style );
547
548         str = Kita::utf8ToUnicode( KITAUTF8_TUGI100 );
549         appendANode( rootnode, "#tugi100", str );
550
551         rootnode.appendChild( m_hdoc.createTextNode( "  " ) );
552
553         str = Kita::utf8ToUnicode( KITAUTF8_ZENBUNOKORI );
554         appendANode( rootnode, "#nokori", str );
555
556         rootnode.appendChild( m_hdoc.createElement( "BR" ) );
557         rootnode.appendChild( m_hdoc.createElement( "BR" ) );
558     }
559
560     m_tugi100 = rootnode;
561 }
562
563
564
565 /* create mae 100 (template)  node */ /* mae 100 */
566 void KitaDomTree::createMae100()
567 {
568     QString style;
569     DOM::Element rootnode;
570
571     style = "text-align: center";
572
573     rootnode = m_hdoc.createElement( "DIV" );
574     {
575         rootnode.setAttribute( "kita_type", "mae100" );
576         rootnode.setAttribute( "id", "mae100" );
577         rootnode.setAttribute( "style", style );
578
579         /* ¼¡100 */
580         QString tugi100 = Kita::utf8ToUnicode( KITAUTF8_TUGI100 );
581         appendANode( rootnode, "#tmp100", tugi100 );
582
583         /* */
584         rootnode.appendChild( m_hdoc.createElement( "BR" ) );
585         rootnode.appendChild( m_hdoc.createElement( "BR" ) );
586
587         /* */
588         style = "background-color: #CCCCCC; text-align: center";
589         DOM::Element divElement = rootnode.appendChild( m_hdoc.createElement( "DIV" ) );
590         {
591             divElement.setAttribute( "style", style );
592             QString templateStr = Kita::utf8ToUnicode( KITAUTF8_TEMPLATE );
593             divElement.appendChild( m_hdoc.createTextNode( templateStr ) );
594         }
595
596         /* */
597         rootnode.appendChild( m_hdoc.createElement( "BR" ) );
598
599         /* Á°100 */
600         QString mae100 = Kita::utf8ToUnicode( KITAUTF8_MAE100 );
601         appendANode( rootnode, "#mae100", mae100 );
602
603         /* */
604         rootnode.appendChild( m_hdoc.createTextNode( "  " ) );
605
606         /* Á´ÉôÁ° */
607         QString zenbumae = Kita::utf8ToUnicode( KITAUTF8_ZENBUMAE );
608         appendANode( rootnode, "#maezenbu", zenbumae );
609
610         /* */
611         rootnode.appendChild( m_hdoc.createElement( "BR" ) );
612         rootnode.appendChild( m_hdoc.createElement( "BR" ) );
613     }
614
615     m_mae100 = rootnode;
616 }
617
618 /* change color of number */
619 /*
620    specify color like this:  "a.coloredLink:link{ color: red; }"   */ /* private */
621
622 void KitaDomTree::changeColorOfNumber( int num )
623 {
624     if ( ! m_datInfo ) return ;
625     if ( m_hdoc == NULL ) return ;
626     if ( m_coloredNum[ num ] ) return ;
627     if ( !m_resshown[ num ] ) return ;
628
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. */
633
634     static_cast< DOM::HTMLElement> ( node ).setAttribute( "class", "coloredLink" );
635 }