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 #include "previewpart.h"
15 #include <khtml_events.h>
17 #include <dom/html_misc.h>
19 #include "thread/respopup.h"
21 #include "kitaui/htmlview.h"
23 #include "libkita/kitaconfig.h"
24 #include "libkita/datmanager.h"
25 #include "libkita/kita_misc.h"
26 #include "libkita/signalcollection.h"
27 #include "libkita/config_xt.h"
29 /*-------------------------------------*/
30 /* Don't forget to call setup() later. */
32 KitaPreviewPart::KitaPreviewPart( QWidget* parent, const char* name )
33 : KHTMLPart( new KitaHTMLView( this, parent, name ) )
36 m_datURL = QString::null;
43 KitaPreviewPart::~KitaPreviewPart()
49 void KitaPreviewPart::clearPart()
53 if ( !m_datURL.isEmpty() ) { /* This part is opened. */
55 /* don't forget to unlock previous datURL here. */
56 Kita::DatManager::unlock( m_datURL );
58 m_datURL = QString::null;
62 bool KitaPreviewPart::setup( const KURL& url )
64 if ( url.isEmpty() ) return FALSE;
68 m_datURL = Kita::getDatURL( url );
70 /* Lock datURL. Don't forget to unlock it later ! */
71 Kita::DatManager::lock ( m_datURL );
73 /* create HTML Document */
80 void KitaPreviewPart::connectSignals()
82 Kita::SignalCollection * signalCollection = Kita::SignalCollection::getInstance();
85 connect( signalCollection, SIGNAL( threadFaceChanged() ), SLOT( slotSetFaceOfHTMLPart() ) );
86 connect( signalCollection, SIGNAL( setStyleSheetOfHTMLPart() ), SLOT( slotSetStyleSheetOfHTMLPart() ) );
89 connect( this, SIGNAL( onURL( const QString& ) ), SLOT( slotOnURL( const QString& ) ) );
90 connect( this, SIGNAL( isKitaActive() ), signalCollection, SIGNAL( isKitaActive() ) );
92 connect( view(), SIGNAL( leave() ), SLOT( slotLeave() ) );
93 connect( view(), SIGNAL( verticalSliderReleased() ), SLOT( slotVSliderReleased() ) );
94 connect( view(), SIGNAL( horizontalSliderReleased() ), SLOT( slotHSliderReleased() ) );
96 connect( signalCollection, SIGNAL( kitaIsActive() ), SLOT( slotKitaIsActive() ) );
97 connect( signalCollection, SIGNAL( windowDeactivated() ), SLOT( slotHideChildPopup() ) );
100 connect( this, SIGNAL( openURLRequestExt(
101 const KURL&, const KParts::URLArgs&, QString, int,
103 signalCollection, SIGNAL( openURLRequestExt(
104 const KURL& , const KParts::URLArgs&, QString, int,
109 void KitaPreviewPart::createHTMLDocument()
112 QString style = QString( "body { font-size: %1pt; font-family: \"%2\"; color: %3; background-color: %4; }" )
113 .arg( Kita::Config::threadFont().pointSize() )
114 .arg( Kita::Config::threadFont().family() )
115 .arg( Kita::Config::threadColor().name() )
116 .arg( Kita::Config::threadBackground().name() );
118 QString text = "<html><head><style>";
119 text += KitaConfig::defaultStyleSheetText();
121 if ( Kita::Config::useStyleSheet() ) {
122 text += KitaConfig::styleSheetText();
124 text += "</style></head><body></body></html>";
126 setJScriptEnabled( false );
127 setJavaEnabled( false );
129 /* Use dummy URL here, and protocol should be "file:".
130 If protocol is "http:", local image files are not shown
131 (for security reasons ?).
133 begin( "file:/dummy.htm" );
138 /*---------------------------------------------------------------*/
139 /*---------------------------------------------------------------*/
140 /* direct rendering functions */
143 void KitaPreviewPart::setInnerHTML( const QString& innerHTML )
145 createHTMLDocument();
146 htmlDocument().body().setInnerHTML( innerHTML );
150 void KitaPreviewPart::slotSetFaceOfHTMLPart()
152 QFont font = Kita::Config::threadFont();
154 DOM::CSSStyleDeclaration style = htmlDocument().body().style();
155 style.setProperty( "font-family", font.family(), "" );
156 style.setProperty( "font-size", QString( "%1pt" ).arg( font.pointSize() ), "" );
157 style.setProperty( "color", Kita::Config::threadColor().name(), "" );
158 style.setProperty( "background-color", Kita::Config::threadBackground().name(), "" );
159 htmlDocument().applyChanges();
163 void KitaPreviewPart::slotSetStyleSheetOfHTMLPart()
165 /* [0]<html> -> [1]<head> -> [2]<style> */
166 DOM::HTMLCollection collection = htmlDocument().all();
167 DOM::HTMLElement element;
169 for ( i = 0 ; i < collection.length() ; i++ ) {
170 element = collection.item( i );
171 if ( element.tagName().upper() == "STYLE" ) {
172 QString style = QString( "body { font-size: %1pt; font-family: %2; color: %3; background-color: %4; }" )
173 .arg( Kita::Config::threadFont().pointSize() )
174 .arg( Kita::Config::threadFont().family() )
175 .arg( Kita::Config::threadColor().name() )
176 .arg( Kita::Config::threadBackground().name() );
178 QString style0 = KitaConfig::defaultStyleSheetText();
180 if ( Kita::Config::useStyleSheet() ) {
181 style0 += KitaConfig::styleSheetText();
184 element.setInnerText( style0 );
185 htmlDocument().applyChanges();
191 /*---------------------------------------------------------------*/
192 /*---------------------------------------------------------------*/
195 /* protected */ /* virtual */
196 void KitaPreviewPart::customEvent( QCustomEvent * e )
198 if ( e->type() == EVENT_GotoAnchor ) {
199 KHTMLPart::gotoAnchor( static_cast< GotoAnchorEvent* >( e ) ->getAnc() );
203 KHTMLPart::customEvent( e );
206 /*---------------------------------------------------------------*/
207 /*---------------------------------------------------------------*/
211 void KitaPreviewPart::khtmlMousePressEvent( khtml::MousePressEvent* e )
213 emit mousePressed(); /* to KitaThreadView to focus this view. */
216 if ( e->url().string() != QString::null ) {
217 kurl = KURL( Kita::BoardManager::boardURL( m_datURL ), e->url().string() );
220 if ( e->qmouseEvent()->button() & Qt::RightButton ) {
221 m_isPushedRightButton = TRUE;
223 m_isPushedRightButton = FALSE;
226 if ( e->url() != NULL ) {
228 if ( e->url().string().at( 0 ) == '#' ) { /* anchor */
230 kurl.setRef( e->url().string().mid( 1 ) ) ;
234 m_isPushedRightButton = FALSE;
238 KHTMLPart::khtmlMousePressEvent( e );
241 /*-------------------------------------------------------*/
242 /*-------------------------------------------------------*/
245 /*------------------------------------------------------*/
246 /* This function is called when user clicked res anchor */ /* private */
247 void KitaPreviewPart::clickAnchor( const KURL& urlin )
250 KURL datURL = Kita::getDatURL( urlin , refstr );
252 /*--------------------------------*/
253 /* If this is not anchor, then */
254 /* emit openURLRequest and return */
256 if ( datURL.host() != m_datURL.host() || datURL.path() != m_datURL.path() ) {
257 emit openURLRequestExt( urlin );
261 if ( refstr == QString::null ) return ;
263 /*-------------------------*/
264 /* start multi-popup mdde */
265 if ( m_isPushedRightButton && startMultiPopup() ) return ;
267 /*-------------------------------*/
268 /* open Kita Navi or goto anchor */
272 int i = refstr.find( "-" );
274 refNum = refstr.left( i ).toInt();
275 refNum2 = refstr.mid( i + 1 ).toInt();
276 if ( refNum2 < refNum ) refNum2 = refNum;
277 } else refNum = refNum2 = refstr.toInt();
279 if ( !refNum ) return ;
281 emit openURLRequestExt( urlin );
284 /*-------------------------------------------------------*/
285 /*-------------------------------------------------------*/
288 void KitaPreviewPart::slotDeletePopup()
290 if ( m_popup ) delete m_popup;
292 m_multiPopup = FALSE;
295 /* for convenience */ /* private */
296 void KitaPreviewPart::showPopup( const KURL& url, const QString& innerHTML )
299 m_multiPopup = FALSE;
301 m_popup = new Kita::ResPopup( view() , url );
303 connect( m_popup, SIGNAL( hideChildPopup() ), SLOT( slotHideChildPopup() ) );
305 m_popup->setText( innerHTML );
306 m_popup->adjustSize();
307 m_popup->adjustPos( QCursor::pos() );
311 /*------------------------*/
312 /* start multi-popup mode */ /* private */
313 bool KitaPreviewPart::startMultiPopup()
315 if ( m_popup && m_popup->isVisible() ) {
317 m_popup->moveMouseAbove();
319 m_multiPopup = FALSE;
325 /* Is it multi-popup mode now ? */ /* private */
326 bool KitaPreviewPart::isMultiPopupMode()
329 m_multiPopup = FALSE;
330 } else if ( m_popup->isHidden() ) {
331 m_multiPopup = FALSE;
338 void KitaPreviewPart::hidePopup()
344 m_multiPopup = FALSE;
348 void KitaPreviewPart::slotLeave()
350 if ( isMultiPopupMode() ) return ;
351 if ( view()->isHorizontalSliderPressed() ) return ;
352 if ( view()->isVerticalSliderPressed () ) return ;
358 void KitaPreviewPart::slotVSliderReleased()
360 QScrollBar* bar = view()->verticalScrollBar();
361 QRect rt = bar->sliderRect();
367 void KitaPreviewPart::slotHSliderReleased()
369 QScrollBar* bar = view()->horizontalScrollBar();
370 QRect rt = bar->sliderRect();
376 void KitaPreviewPart::slotHideChildPopup()
381 /*------------------------------------------*/
382 /* called back when kita is active .
383 see also an explanation in slotOnURL. */ /* private slot */
384 void KitaPreviewPart::slotKitaIsActive()
386 m_kitaIsActive = TRUE;
389 /*---------------------------------------------------*/
390 /* This slot is called when mouse moves onto the URL */ /* private slot */
391 void KitaPreviewPart::slotOnURL( const QString& url )
395 const int maxpopup = 10; /* max number of responses shown in the popup window */
397 /*----------------------------*/
399 if ( isMultiPopupMode() ) return ;
403 if ( url.isEmpty() ) return ;
404 if ( url.left( 7 ) == "mailto:" ) return ;
406 /* Is Kita active now ?
408 emit SIGNAL( isKitaActive() ) to KitaMainWindow, KitaNavi, etc. ,
409 and if one of them is active, then slotKitaIsActive() is called
410 back, and m_kitaIsActive is set to TRUE. */
411 m_kitaIsActive = FALSE;
413 if ( !m_kitaIsActive ) return ;
417 KURL datURL = m_datURL;
418 if ( url.at( 0 ) == '#' ) refstr = url.mid( 1 );
419 else datURL = Kita::getDatURL( KURL( m_datURL, url ) , refstr );
421 /*-------------------------*/
422 /* popup for anchor */
424 QString innerHTML = QString::null;
428 int i = refstr.find( "-" );
429 if ( i != -1 ) { /* >>refNum-refNum2 */
431 refNum = refstr.left( i ).toInt();
432 refNum2 = refstr.mid( i + 1 ).toInt();
435 if ( refNum2 < refNum ) refNum2 = refNum;
436 if ( refNum2 - refNum > maxpopup - 1 ) refNum2 = refNum + maxpopup - 1;
439 } else { /* >>refNum */
440 refNum = refstr.toInt();
444 /* another thread ? */
445 if ( datURL.host() != m_datURL.host() || datURL.path() != m_datURL.path() ) {
448 QString boardName = Kita::BoardManager::boardName( datURL );
449 if ( boardName != QString::null ) innerHTML += "[" + boardName + "] ";
451 /* If idx file of datURL is not read, thread name cannot be obtained.
452 so, create DatInfo if cache exists, and read idx file in DatInfo::DatInfo(). */
453 Kita::DatManager::getDatInfoPointer( datURL );
455 /* get thread Name */
456 QString subName = Kita::DatManager::threadName( datURL );
457 if ( subName != QString::null ) innerHTML += subName + "<br><br>";
459 if ( !refNum ) refNum = refNum2 = 1;
462 /* get HTML and show it */
463 if ( !refNum ) return ;
464 innerHTML += Kita::DatManager::getHtml( datURL, refNum, refNum2 );
466 if ( innerHTML != QString::null ) showPopup( datURL, innerHTML );