OSDN Git Service

move files.
[kita/kita.git] / kita / src / previewpart.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 #include "previewpart.h"
12
13 #include <qcursor.h>
14
15 #include <khtml_events.h>
16
17 #include <dom/html_misc.h>
18
19 #include "respopup.h"
20 #include "htmlpart.h"
21
22 #include "kitaui/htmlview.h"
23
24 #include "libkita/kitaconfig.h"
25 #include "libkita/datmanager.h"
26 #include "libkita/kita_misc.h"
27 #include "libkita/signalcollection.h"
28 #include "libkita/config_xt.h"
29
30 /*
31  * Don't forget to call setup() later.
32  */
33 KitaPreviewPart::KitaPreviewPart( QWidget* parent, const char* name )
34         : KHTMLPart( new KitaHTMLView( this, parent, name ) )
35 {
36     m_popup = NULL;
37     m_datURL = QString::null;
38
39     clearPart();
40     createHTMLDocument();
41     connectSignals();
42 }
43
44 KitaPreviewPart::~KitaPreviewPart()
45 {
46     clearPart();
47 }
48
49 void KitaPreviewPart::clearPart()
50 {
51     slotDeletePopup();
52
53     if ( !m_datURL.isEmpty() ) {
54         /* This part is opened. */
55
56         /* don't forget to unlock previous datURL here. */
57         Kita::DatManager::unlock( m_datURL );
58     }
59     m_datURL = QString::null;
60 }
61
62 bool KitaPreviewPart::setup( const KURL& url )
63 {
64     if ( url.isEmpty() ) return FALSE;
65
66     clearPart();
67
68     m_datURL = Kita::getDatURL( url );
69
70     /* Lock datURL. Don't forget to unlock it later ! */
71     Kita::DatManager::lock ( m_datURL );
72
73     /* create HTML Document */
74     createHTMLDocument();
75
76     return TRUE;
77 }
78
79 void KitaPreviewPart::connectSignals()
80 {
81     Kita::SignalCollection * signalCollection = Kita::SignalCollection::getInstance();
82
83     /* rendering */
84     connect( signalCollection, SIGNAL( threadFaceChanged() ), SLOT( slotSetFaceOfHTMLPart() ) );
85     connect( signalCollection, SIGNAL( setStyleSheetOfHTMLPart() ), SLOT( slotSetStyleSheetOfHTMLPart() ) );
86
87     /* popup */
88     connect( this, SIGNAL( onURL( const QString& ) ), SLOT( slotOnURL( const QString& ) ) );
89     connect( this, SIGNAL( isKitaActive() ), signalCollection, SIGNAL( isKitaActive() ) );
90
91     connect( view(), SIGNAL( leave() ), SLOT( slotLeave() ) );
92     connect( view(), SIGNAL( verticalSliderReleased() ), SLOT( slotVSliderReleased() ) );
93     connect( view(), SIGNAL( horizontalSliderReleased() ), SLOT( slotHSliderReleased() ) );
94
95     connect( signalCollection, SIGNAL( kitaIsActive() ), SLOT( slotKitaIsActive() ) );
96     connect( signalCollection, SIGNAL( windowDeactivated() ), SLOT( slotHideChildPopup() ) );
97
98     /* click */
99     connect( this, SIGNAL( openURLRequestExt( const KURL&, const QString ) ),
100              signalCollection, SIGNAL( openURLRequestExt( const KURL&, const QString ) ) );
101 }
102
103 void KitaPreviewPart::createHTMLDocument()
104 {
105     /* style */
106     QString style = QString( "body { font-size: %1pt; font-family: \"%2\"; color: %3; background-color: %4; }" )
107                     .arg( Kita::Config::threadFont().pointSize() )
108                     .arg( Kita::Config::threadFont().family() )
109                     .arg( Kita::Config::threadColor().name() )
110                     .arg( Kita::Config::threadBackground().name() );
111
112     QString text = "<html><head><style>";
113     text += KitaConfig::defaultStyleSheetText();
114     text += style;
115     if ( Kita::Config::useStyleSheet() ) {
116         text += KitaConfig::styleSheetText();
117     }
118     text += "</style></head><body></body></html>";
119
120     setJScriptEnabled( false );
121     setJavaEnabled( false );
122
123     /* Use dummy URL here, and protocol should be "file:".
124        If protocol is "http:", local image files are not shown
125        (for security reasons ?).
126      */
127     begin( "file:/dummy.htm" );
128     write( text );
129     end();
130 }
131
132 void KitaPreviewPart::setInnerHTML( const QString& innerHTML )
133 {
134     createHTMLDocument();
135     htmlDocument().body().setInnerHTML( innerHTML );
136 }
137
138 void KitaPreviewPart::slotSetFaceOfHTMLPart()
139 {
140     QFont font = Kita::Config::threadFont();
141
142     DOM::CSSStyleDeclaration style = htmlDocument().body().style();
143     style.setProperty( "font-family", font.family(), "" );
144     style.setProperty( "font-size", QString( "%1pt" ).arg( font.pointSize() ), "" );
145     style.setProperty( "color", Kita::Config::threadColor().name(), "" );
146     style.setProperty( "background-color", Kita::Config::threadBackground().name(), "" );
147
148     htmlDocument().applyChanges();
149 }
150
151 void KitaPreviewPart::slotSetStyleSheetOfHTMLPart()
152 {
153     /* [0]<html> -> [1]<head> -> [2]<style> */
154     DOM::HTMLCollection collection = htmlDocument().all();
155     DOM::HTMLElement element;
156     unsigned int i;
157     for ( i = 0 ; i < collection.length() ; i++ ) {
158         element = collection.item( i );
159         if ( element.tagName().upper() == "STYLE" ) {
160             QString style = QString( "body { font-size: %1pt; font-family: %2; color: %3; background-color: %4; }" )
161                             .arg( Kita::Config::threadFont().pointSize() )
162                             .arg( Kita::Config::threadFont().family() )
163                             .arg( Kita::Config::threadColor().name() )
164                             .arg( Kita::Config::threadBackground().name() );
165
166             QString style0 = KitaConfig::defaultStyleSheetText();
167             style0 += style;
168             if ( Kita::Config::useStyleSheet() ) {
169                 style0 += KitaConfig::styleSheetText();
170             }
171
172             element.setInnerText( style0 );
173             htmlDocument().applyChanges();
174             break;
175         }
176     }
177 }
178
179 /*
180  * @Override
181  */
182 void KitaPreviewPart::customEvent( QCustomEvent * e )
183 {
184     if ( e->type() == EVENT_GotoAnchor ) {
185         KHTMLPart::gotoAnchor( static_cast< GotoAnchorEvent* >( e ) ->getAnc() );
186         return ;
187     }
188
189     KHTMLPart::customEvent( e );
190 }
191
192 /*
193  * @Override
194  */
195 void KitaPreviewPart::khtmlMousePressEvent( khtml::MousePressEvent* e )
196 {
197     emit mousePressed(); /* to KitaThreadView to focus this view. */
198
199     KURL kurl;
200     if ( e->url().string() != QString::null ) {
201         kurl = KURL( Kita::BoardManager::boardURL( m_datURL ), e->url().string() );
202     }
203
204     if ( e->qmouseEvent()->button() & Qt::RightButton ) {
205         m_isPushedRightButton = TRUE;
206     } else {
207         m_isPushedRightButton = FALSE;
208     }
209
210     if ( e->url() != NULL ) {
211
212         if ( e->url().string().at( 0 ) == '#' ) { /* anchor */
213             kurl = m_datURL;
214             kurl.setRef( e->url().string().mid( 1 ) ) ;
215         }
216
217         clickAnchor( kurl );
218         m_isPushedRightButton = FALSE;
219         return;
220     }
221
222     KHTMLPart::khtmlMousePressEvent( e );
223 }
224
225 /*
226  * This function is called when user clicked res anchor
227  */
228 void KitaPreviewPart::clickAnchor( const KURL& urlin )
229 {
230     QString refstr;
231     KURL datURL = Kita::getDatURL( urlin, refstr );
232
233     /*--------------------------------*/
234     /* If this is not anchor, then    */
235     /* emit openURLRequest and return */
236     if ( datURL.host() != m_datURL.host() || datURL.path() != m_datURL.path() ) {
237         emit openURLRequestExt( urlin );
238         return ;
239     }
240
241     if ( refstr == QString::null ) return ;
242
243     /*-------------------------*/
244     /* start multi-popup mdde  */
245     if ( m_isPushedRightButton && startMultiPopup() ) return ;
246
247     int refNum, refNum2;
248
249     int i = refstr.find( "-" );
250     if ( i != -1 ) {
251         refNum = refstr.left( i ).toInt();
252         refNum2 = refstr.mid( i + 1 ).toInt();
253         if ( refNum2 < refNum ) {
254             refNum2 = refNum;
255         }
256     } else {
257         refNum = refNum2 = refstr.toInt();
258     }
259
260     if ( !refNum ) return ;
261
262     emit openURLRequestExt( urlin );
263 }
264
265 void KitaPreviewPart::slotDeletePopup()
266 {
267     if ( m_popup ) delete m_popup;
268     m_popup = NULL;
269     m_multiPopup = FALSE;
270 }
271
272 /*
273  * for convenience
274  */
275 void KitaPreviewPart::showPopup( const KURL& url, const QString& innerHTML )
276 {
277     slotDeletePopup();
278     m_multiPopup = FALSE;
279
280     m_popup = new Kita::ResPopup( view() , url );
281
282     connect( m_popup, SIGNAL( hideChildPopup() ), SLOT( slotHideChildPopup() ) );
283
284     m_popup->setText( innerHTML );
285     m_popup->adjustSize();
286     m_popup->adjustPos( QCursor::pos() );
287     m_popup->show();
288 }
289
290 /*
291  * start multi-popup mode
292  */
293 bool KitaPreviewPart::startMultiPopup()
294 {
295     if ( m_popup && m_popup->isVisible() ) {
296         m_multiPopup = TRUE;
297         m_popup->moveMouseAbove();
298     } else {
299         m_multiPopup = FALSE;
300     }
301
302     return m_multiPopup;
303 }
304
305 /*
306  * Is it multi-popup mode now ?
307  */
308 bool KitaPreviewPart::isMultiPopupMode()
309 {
310     if ( !m_popup ) {
311         m_multiPopup = FALSE;
312     } else if ( m_popup->isHidden() ) {
313         m_multiPopup = FALSE;
314     }
315
316     return m_multiPopup;
317 }
318
319 void KitaPreviewPart::hidePopup()
320 {
321     if ( m_popup ) {
322         m_popup->hide();
323     }
324
325     m_multiPopup = FALSE;
326 }
327
328 void KitaPreviewPart::slotLeave()
329 {
330     if ( isMultiPopupMode() ) return ;
331     if ( view()->isHorizontalSliderPressed() ) return ;
332     if ( view()->isVerticalSliderPressed () ) return ;
333
334     hidePopup();
335 }
336
337 void KitaPreviewPart::slotVSliderReleased()
338 {
339     QScrollBar* bar = view()->verticalScrollBar();
340     QRect rt = bar->sliderRect();
341
342     hidePopup();
343 }
344
345 void KitaPreviewPart::slotHSliderReleased()
346 {
347     QScrollBar* bar = view()->horizontalScrollBar();
348     QRect rt = bar->sliderRect();
349
350     hidePopup();
351 }
352
353 void KitaPreviewPart::slotHideChildPopup()
354 {
355     hidePopup();
356 }
357
358 /*
359  * called back when kita is active.
360  * see also an explanation in slotOnURL.
361  */
362 void KitaPreviewPart::slotKitaIsActive()
363 {
364     m_kitaIsActive = TRUE;
365 }
366
367 /*
368  * This slot is called when mouse moves onto the URL
369  */
370 void KitaPreviewPart::slotOnURL( const QString& url )
371 {
372     const int maxpopup = 10;  /* max number of responses shown in the popup window */
373
374     if ( isMultiPopupMode() ) return ;
375
376     slotDeletePopup();
377
378     if ( url.isEmpty() ) return ;
379     if ( url.left( 7 ) == "mailto:" ) return ;
380
381     /* Is Kita active now ?
382
383        emit SIGNAL( isKitaActive() ) to KitaMainWindow, KitaNavi, etc. ,
384        and if one of them is active, then slotKitaIsActive() is called
385        back, and m_kitaIsActive is set to TRUE.   */
386     m_kitaIsActive = FALSE;
387     emit isKitaActive();
388     if ( !m_kitaIsActive ) return ;
389
390     /* get reference */
391     QString refstr;
392     KURL datURL = m_datURL;
393     if ( url.at( 0 ) == '#' ) {
394         refstr = url.mid( 1 );
395     } else {
396         datURL = Kita::getDatURL( KURL( m_datURL, url ), refstr );
397     }
398
399     /*-------------------------*/
400     /* popup for anchor        */
401
402     QString innerHTML = QString::null;
403     int refNum;
404     int refNum2;
405
406     int i = refstr.find( "-" );
407     if ( i != -1 ) { /* >>refNum-refNum2 */
408
409         refNum = refstr.left( i ).toInt();
410         refNum2 = refstr.mid( i + 1 ).toInt();
411
412         if ( refNum ) {
413             if ( refNum2 < refNum ) refNum2 = refNum;
414             if ( refNum2 - refNum > maxpopup - 1 ) refNum2 = refNum + maxpopup - 1;
415         }
416
417     } else { /* >>refNum */
418         refNum = refstr.toInt();
419         refNum2 = refNum;
420     }
421
422     /* another thread ? */
423     if ( datURL.host() != m_datURL.host() || datURL.path() != m_datURL.path() ) {
424
425         /* get board name */
426         QString boardName = Kita::BoardManager::boardName( datURL );
427         if ( boardName != QString::null ) {
428             innerHTML += "[" + boardName + "] ";
429         }
430
431         /* If idx file of datURL is not read, thread name cannot be obtained.
432            so, create DatInfo if cache exists, and read idx file in DatInfo::DatInfo(). */
433         Kita::DatManager::getDatInfoPointer( datURL );
434
435         /* get thread Name */
436         QString subName = Kita::DatManager::threadName( datURL );
437         if ( subName != QString::null ) {
438             innerHTML += subName + "<br><br>";
439         }
440
441         if ( !refNum ) refNum = refNum2 = 1;
442     }
443
444     /* get HTML and show it */
445     if ( !refNum ) return ;
446
447     innerHTML += Kita::DatManager::getHtml( datURL, refNum, refNum2 );
448     if ( innerHTML != QString::null ) {
449         showPopup( datURL, innerHTML );
450     }
451 }